时间序列中的多个 X 轴

Multiple X axis in plotly timeseries

我正在尝试在 Plotly.js 中创建一个时间序列,它具有多个 X 轴以直观地对比赛的四节进行分组。所需最终状态的粗略描述:

我知道 Plotly.js 支持多个 x 轴,但我遇到了一些奇怪的行为,其中标签在图表中呈现不正确。我的尝试基于 plotly 提供的用于处理多轴的示例 - 核心区别在于我的数据是基于时间的并且是面向 x 的:https://plotly.com/javascript/multiple-axes/

这是我的代码和奇怪的行为:

Codepen

data = [
    {
        "x": [
            "2020-01-08 00:00:29",
            "2020-01-08 00:00:40",
            "2020-01-08 00:00:55",
            "2020-01-08 00:01:38",
            "2020-01-08 00:01:52",
            "2020-01-08 00:02:17",
            "2020-01-08 00:02:25",
            "2020-01-08 00:02:41",
            "2020-01-08 00:03:12",
            "2020-01-08 00:03:28",
            "2020-01-08 00:03:59",
            "2020-01-08 00:04:07",
            "2020-01-08 00:04:49",
            "2020-01-08 00:05:06",
            "2020-01-08 00:05:23",
            "2020-01-08 00:06:14",
            "2020-01-08 00:07:53",
            "2020-01-08 00:08:04",
            "2020-01-08 00:09:42",
            "2020-01-08 00:10:04",
            "2020-01-08 00:10:25",
            "2020-01-08 00:11:24"
        ],
        "y": [
            -2,
            1,
            -1,
            -4,
            -2,
            0,
            -2,
            0,
            -1,
            1,
            3,
            1,
            -2,
            0,
            -2,
            -7,
            -7,
            -9,
            -13,
            -16,
            -14,
            -10
        ],
        "mode": "lines",
        "name": "Q1",
        "xaxis": "xaxis"
    },
    {
        "x": [
            "2020-01-08 00:12:42",
            "2020-01-08 00:13:43",
            "2020-01-08 00:14:03",
            "2020-01-08 00:14:37",
            "2020-01-08 00:14:48",
            "2020-01-08 00:16:15",
            "2020-01-08 00:16:31",
            "2020-01-08 00:16:59",
            "2020-01-08 00:17:23",
            "2020-01-08 00:17:55",
            "2020-01-08 00:18:34",
            "2020-01-08 00:19:07",
            "2020-01-08 00:19:38",
            "2020-01-08 00:20:11",
            "2020-01-08 00:21:03",
            "2020-01-08 00:21:23",
            "2020-01-08 00:21:59",
            "2020-01-08 00:22:33",
            "2020-01-08 00:23:43"
        ],
        "y": [
            -8,
            -6,
            -8,
            -10,
            -8,
            -5,
            -8,
            -6,
            -8,
            -6,
            -8,
            -6,
            -4,
            -2,
            -4,
            -6,
            -4,
            -5,
            -4
        ],

        "mode": "lines",
        "name": "Q2",
        "xaxis": "xaxis2"
    },
    {
        "x": [
            "2020-01-08 00:24:41",
            "2020-01-08 00:24:58",
            "2020-01-08 00:25:21",
            "2020-01-08 00:25:46",
            "2020-01-08 00:26:12",
            "2020-01-08 00:26:32",
            "2020-01-08 00:27:19",
            "2020-01-08 00:28:01",
            "2020-01-08 00:28:34",
            "2020-01-08 00:29:08",
            "2020-01-08 00:30:34",
            "2020-01-08 00:31:05",
            "2020-01-08 00:32:02",
            "2020-01-08 00:32:21",
            "2020-01-08 00:32:55",
            "2020-01-08 00:33:42",
            "2020-01-08 00:34:09",
            "2020-01-08 00:34:22",
            "2020-01-08 00:34:58",
            "2020-01-08 00:35:09"
        ],
        "y": [
            -2,
            -4,
            -6,
            -9,
            -12,
            -10,
            -13,
            -10,
            -7,
            -5,
            -5,
            -3,
            -4,
            -6,
            -9,
            -7,
            -9,
            -7,
            -5,
            -7
        ],
        "line": {
            "shape": "linear"
        },
        "mode": "lines",
        "name": "Q3",
        "xaxis": "xaxis3"
    },
    {
        "x": [
            "2020-01-08 00:36:46",
            "2020-01-08 00:37:44",
            "2020-01-08 00:38:23",
            "2020-01-08 00:39:02",
            "2020-01-08 00:40:29",
            "2020-01-08 00:40:59",
            "2020-01-08 00:41:07",
            "2020-01-08 00:41:28",
            "2020-01-08 00:42:00",
            "2020-01-08 00:42:13",
            "2020-01-08 00:42:50",
            "2020-01-08 00:43:29",
            "2020-01-08 00:43:59",
            "2020-01-08 00:44:23",
            "2020-01-08 00:44:53",
            "2020-01-08 00:44:59",
            "2020-01-08 00:45:29",
            "2020-01-08 00:46:14",
            "2020-01-08 00:46:55",
            "2020-01-08 00:47:49",
            "2020-01-08 00:47:57"
        ],
        "y": [
            -9,
            -11,
            -5,
            -8,
            -11,
            -13,
            -10,
            -12,
            -14,
            -12,
            -14,
            -12,
            -10,
            -11,
            -11,
            -10,
            -7,
            -4,
            -1,
            1,
            -1
        ],
        "line": {
            "shape": "linear"
        },
        "mode": "lines",
        "name": "Q4",
        "xaxis": "xaxis4"
    }
]

layout = {
    "title": {
        "text": "Game data"
    },
    "xaxis": {
        "title": {
            "text": "q1"
        },
        "tickvals": [
            "2020-01-08 00:00:00",
            "2020-01-08 00:02:00",
            "2020-01-08 00:04:00",
            "2020-01-08 00:06:00",
            "2020-01-08 00:08:00",
            "2020-01-08 00:12:00"
        ],
        "tickformat": "%M:%S",
        "type": "date",
    },
    "xaxis2": {
        "title": {
            "text": "q2"
        },
        "tickvals": [
            "2020-01-08 00:12:00",
            "2020-01-08 00:14:00",
            "2020-01-08 00:16:00",
            "2020-01-08 00:18:00",
            "2020-01-08 00:20:00",
            "2020-01-08 00:22:00",
            "2020-01-08 00:24:00"
        ],
        "tickformat": "%M:%S",
        "type": "date",
    },
    "xaxis3": {
        "title": {
            "text": "q3"
        },
        "tickvals": [
            "2020-01-08 00:24:00",
            "2020-01-08 00:26:00",
            "2020-01-08 00:28:00",
            "2020-01-08 00:30:00",
            "2020-01-08 00:32:00",
            "2020-01-08 00:34:00",
            "2020-01-08 00:36:00"
        ],
        "tickformat": "%M:%S",
        "type": "date",
    },
    "xaxis4": {
        "title": {
            "text": "q4"
        },
        "tickvals": [
            "2020-01-08 00:36:00",
            "2020-01-08 00:38:00",
            "2020-01-08 00:40:00",
            "2020-01-08 00:42:00",
            "2020-01-08 00:44:00",
            "2020-01-08 00:46:00",
            "2020-01-08 00:48:00"
        ],
        "tickformat": "%M:%S",
        "type": "date",
    },
    "yaxis": {
        "type": "linear",
        "autorange": true
    }
}

Plotly.newPlot('myDiv', data, layout);

我认为多 x 轴不是您要找的东西,因为那些通常意味着您有另一个 x 轴,其比例与主 x 轴相反,但在您想要的输出中只有一个 x 轴。

相反,您可以使用 multi-categorical x-axis,但我认为您不能将 x 轴指定为 "type": "date",因为一个类别将是日期,而另一个类别将是一个像“Q1”这样的字符串。

因此,我认为表示多类别 x 轴的最佳方法是简单地将字符串 "Q1", ... "Q4" 添加为文本注释,然后使用纸张坐标将它们放置在日期刻度下方。

然后使用 Plotly shapes,您可以在每个季度时间标记周围画线,使您的 x 轴看起来有一个多类别。

您可以查看代码笔here

category_annotations = [];
text_annotations = []
quarter_names = ["Q1","Q2","Q3","Q4"]
quarter_positions = [0.125,0.375,0.625,0.875]
quarter_times = [
  "2020-01-08 00:00:00",
  "2020-01-08 00:12:00",
  "2020-01-08 00:24:00",
  "2020-01-08 00:36:00",
  "2020-01-08 00:48:00"
]

for (let i = 0; i < quarter_times.length; i++) {
  category_annotations.push(
    {
        type: 'line',
        x0: quarter_times[i],
        x1: quarter_times[i],
        y0: -0.20,
        y1: 0.05,
        xref: 'x',
        yref: 'paper',
        line: {
          color: 'black',
          width: 1
        }
    }
  )
}

category_annotations.push(
  {
        type: 'line',
        x0: 0,
        x1: 1,
        y0: 0.05,
        y1: 0.05,
        xref: 'paper',
        yref: 'paper',
        line: {
          color: 'black',
          width: 1
        }
    }
)

for (let i = 0; i < quarter_names.length; i++) {
  text_annotations.push(
    {
      x: quarter_positions[i],
      y: -0.15,
      xref: 'paper',
      yref: 'paper',
      text: quarter_names[i],
      showarrow: false,
    }
  )
}

data = [
    {
        "x": [
            "2020-01-08 00:00:29",
            "2020-01-08 00:00:40",
            "2020-01-08 00:00:55",
            "2020-01-08 00:01:38",
            "2020-01-08 00:01:52",
            "2020-01-08 00:02:17",
            "2020-01-08 00:02:25",
            "2020-01-08 00:02:41",
            "2020-01-08 00:03:12",
            "2020-01-08 00:03:28",
            "2020-01-08 00:03:59",
            "2020-01-08 00:04:07",
            "2020-01-08 00:04:49",
            "2020-01-08 00:05:06",
            "2020-01-08 00:05:23",
            "2020-01-08 00:06:14",
            "2020-01-08 00:07:53",
            "2020-01-08 00:08:04",
            "2020-01-08 00:09:42",
            "2020-01-08 00:10:04",
            "2020-01-08 00:10:25",
            "2020-01-08 00:11:24"
        ],
        "y": [
            -2,
            1,
            -1,
            -4,
            -2,
            0,
            -2,
            0,
            -1,
            1,
            3,
            1,
            -2,
            0,
            -2,
            -7,
            -7,
            -9,
            -13,
            -16,
            -14,
            -10
        ],
        "mode": "lines",
        "name": "Q1",
    },
    {
        "x": [
            "2020-01-08 00:12:42",
            "2020-01-08 00:13:43",
            "2020-01-08 00:14:03",
            "2020-01-08 00:14:37",
            "2020-01-08 00:14:48",
            "2020-01-08 00:16:15",
            "2020-01-08 00:16:31",
            "2020-01-08 00:16:59",
            "2020-01-08 00:17:23",
            "2020-01-08 00:17:55",
            "2020-01-08 00:18:34",
            "2020-01-08 00:19:07",
            "2020-01-08 00:19:38",
            "2020-01-08 00:20:11",
            "2020-01-08 00:21:03",
            "2020-01-08 00:21:23",
            "2020-01-08 00:21:59",
            "2020-01-08 00:22:33",
            "2020-01-08 00:23:43"
        ],
        "y": [
            -8,
            -6,
            -8,
            -10,
            -8,
            -5,
            -8,
            -6,
            -8,
            -6,
            -8,
            -6,
            -4,
            -2,
            -4,
            -6,
            -4,
            -5,
            -4
        ],

        "mode": "lines",
        "name": "Q2",
    },
    {
        "x": [
            "2020-01-08 00:24:41",
            "2020-01-08 00:24:58",
            "2020-01-08 00:25:21",
            "2020-01-08 00:25:46",
            "2020-01-08 00:26:12",
            "2020-01-08 00:26:32",
            "2020-01-08 00:27:19",
            "2020-01-08 00:28:01",
            "2020-01-08 00:28:34",
            "2020-01-08 00:29:08",
            "2020-01-08 00:30:34",
            "2020-01-08 00:31:05",
            "2020-01-08 00:32:02",
            "2020-01-08 00:32:21",
            "2020-01-08 00:32:55",
            "2020-01-08 00:33:42",
            "2020-01-08 00:34:09",
            "2020-01-08 00:34:22",
            "2020-01-08 00:34:58",
            "2020-01-08 00:35:09"
        ],
        "y": [
            -2,
            -4,
            -6,
            -9,
            -12,
            -10,
            -13,
            -10,
            -7,
            -5,
            -5,
            -3,
            -4,
            -6,
            -9,
            -7,
            -9,
            -7,
            -5,
            -7
        ],
        "line": {
            "shape": "linear"
        },
        "mode": "lines",
        "name": "Q3",
    },
    {
        "x": [
            "2020-01-08 00:36:46",
            "2020-01-08 00:37:44",
            "2020-01-08 00:38:23",
            "2020-01-08 00:39:02",
            "2020-01-08 00:40:29",
            "2020-01-08 00:40:59",
            "2020-01-08 00:41:07",
            "2020-01-08 00:41:28",
            "2020-01-08 00:42:00",
            "2020-01-08 00:42:13",
            "2020-01-08 00:42:50",
            "2020-01-08 00:43:29",
            "2020-01-08 00:43:59",
            "2020-01-08 00:44:23",
            "2020-01-08 00:44:53",
            "2020-01-08 00:44:59",
            "2020-01-08 00:45:29",
            "2020-01-08 00:46:14",
            "2020-01-08 00:46:55",
            "2020-01-08 00:47:49",
            "2020-01-08 00:47:57"
        ],
        "y": [
            -9,
            -11,
            -5,
            -8,
            -11,
            -13,
            -10,
            -12,
            -14,
            -12,
            -14,
            -12,
            -10,
            -11,
            -11,
            -10,
            -7,
            -4,
            -1,
            1,
            -1
        ],
        "line": {
            "shape": "linear"
        },
        "mode": "lines",
        "name": "Q4",
    }
];

layout = {
    "title": {
        "text": "Game data"
    },
    "xaxis": {
      "tickformat": "%M:%S",
      "type": "date",
      "tickvals": [
            "2020-01-08 00:00:00",
            "2020-01-08 00:02:00",
            "2020-01-08 00:04:00",
            "2020-01-08 00:06:00",
            "2020-01-08 00:08:00",
            "2020-01-08 00:10:00",
            "2020-01-08 00:12:00",
            "2020-01-08 00:14:00",
            "2020-01-08 00:16:00",
            "2020-01-08 00:18:00",
            "2020-01-08 00:20:00",
            "2020-01-08 00:22:00",
            "2020-01-08 00:24:00",
            "2020-01-08 00:26:00",
            "2020-01-08 00:28:00",
            "2020-01-08 00:30:00",
            "2020-01-08 00:32:00",
            "2020-01-08 00:34:00",
            "2020-01-08 00:36:00",
            "2020-01-08 00:38:00",
            "2020-01-08 00:40:00",
            "2020-01-08 00:42:00",
            "2020-01-08 00:44:00",
            "2020-01-08 00:46:00",
            "2020-01-08 00:48:00"
      ],
    },
    "yaxis": {
        "tickmode": "linear",
        "tick0": -1,
        "dtick": 1.00,
        "zeroline": false
    },
    "annotations": text_annotations,
    "shapes": category_annotations
}

Plotly.newPlot('myDiv', data, layout);