Plotly:如何从 x 轴删除空日期?

Posted

技术标签:

【中文标题】Plotly:如何从 x 轴删除空日期?【英文标题】:Plotly: How to remove empty dates from x axis? 【发布时间】:2020-09-05 18:25:46 【问题描述】:

我有一个数据框

   Date        Category    Sum
0  2019-06-03    "25M"      34
1  2019-06-03    "25M"      60
2  2019-06-03    "50M"      23
3  2019-06-04    "25M"      67
4  2019-06-05    "50M"     -90
5  2019-06-05    "50M"     100
6  2019-06-06    "100M"     6
7  2019-06-07    "25M"     -100
8  2019-06-08    "100M"     67
9  2019-06-09    "25M"      450
10 2019-06-10    "50M"      600
11 2019-06-11    "25M"      -9
12 2019-07-12    "50M"      45
13 2019-07-13    "50M"      67
14 2019-07-14    "100M"    130
15 2019-07-14    "50M"      45
16 2019-07-15    "100M"    100
17 2019-07-16    "25M"     -90
18 2019-07-17    "25M"     700
19 2019-07-18    "25M"     -9

我想创建一个绘图图,显示在每个描述的日期为不同的“类别”添加“总和”,但如果日期没有任何数据,我想删除它们。

代码

df["Date"]=pd.to_datetime(df["Date"], format=("%Y%m%d"))
df=df.sort_values(["Date","Category","Sum"],ascending=False)
df=round(df.groupby(["Date","Category"]).agg("Sum":"sum").reset_index(),1)


fig = px.bar(df, x=df["Date"] , y='Sum',barmode="group",color="Category") 
fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
    buttons=list([
        dict(count=1, label="day", step="day", stepmode="todate"),
        dict(count=24, label="montly", step="month", stepmode="todate"),
        dict(count=1, label="year", step="year", stepmode="todate"),
        dict(step="all")
    ])
   ))


fig.show()

我得到这样的图表,但我想从绘图图中删除空日期

【问题讨论】:

这能回答你的问题吗? Plotly: How to remove the empty gap on x-axis 【参考方案1】:

我的图表也有同样的问题。只需在布局代码中添加以下内容:

xaxis=dict(type = "category")

注意:我用过import plotly.graph_objs as go import plotly.express as px

这对我有用。希望对你也有帮助。

【讨论】:

非常感谢这个有用的答案。它在我的图表中运行良好。 在大量数据中使用 rangebreaks(如已接受的答案)导致烛台图加载缓慢。这对我很有用。谢谢。【参考方案2】:

这个问题来自这样一个事实:将您的'Date' 解释为日期,并在最旧和最新的时间戳之间创建一个连续的时间段,从而有效地将没有关联数据的日期显示为间隙。一种解决方案是在您的日期列中获取第一个和最后一个日期,并在该期间制作一个完整日期列表,然后整理出哪些日期没有观察结果,并将其存储在名为 dt_breaks 的变量中。然后,最后,您可以将这些日期包含在:

fig.update_xaxes(
    rangebreaks=[dict(values=dt_breaks)] # hide dates with no values
)

这将在您的可视化中删除这些日期,并且将 x 值保持为日期格式,以便您可以使用按钮对数据进行子集化:

正如您已经知道的,这里是没有rangebreaks=[dict(values=dt_breaks)] 的相同可视化:

为了使这项工作尽可能简单,我使用 df=df.sort_values(["Date","Category","Sum"],ascending=True) 而不是 df=df.sort_values(["Date","Category","Sum"],ascending=False) 重新排列日期列,就像在您的原始代码 sn-p 中一样

完整代码:

import pandas as pd
import plotly.express as px

df = pd.DataFrame('Date': 0: '2019-06-03',
                          1: '2019-06-03',
                          2: '2019-06-03',
                          3: '2019-06-04',
                          4: '2019-06-05',
                          5: '2019-06-05',
                          6: '2019-06-06',
                          7: '2019-06-07',
                          8: '2019-06-08',
                          9: '2019-06-09',
                          10: '2019-06-10',
                          11: '2019-06-11',
                          12: '2019-07-12',
                          13: '2019-07-13',
                          14: '2019-07-14',
                          15: '2019-07-14',
                          16: '2019-07-15',
                          17: '2019-07-16',
                          18: '2019-07-17',
                          19: '2019-07-18',
                         'Category': 0: '"25M"',
                          1: '"25M"',
                          2: '"50M"',
                          3: '"25M"',
                          4: '"50M"',
                          5: '"50M"',
                          6: '"100M"',
                          7: '"25M"',
                          8: '"100M"',
                          9: '"25M"',
                          10: '"50M"',
                          11: '"25M"',
                          12: '"50M"',
                          13: '"50M"',
                          14: '"100M"',
                          15: '"50M"',
                          16: '"100M"',
                          17: '"25M"',
                          18: '"25M"',
                          19: '"25M"',
                         'Sum': 0: 34,
                          1: 60,
                          2: 23,
                          3: 67,
                          4: -90,
                          5: 100,
                          6: 6,
                          7: -100,
                          8: 67,
                          9: 450,
                          10: 600,
                          11: -9,
                          12: 45,
                          13: 67,
                          14: 130,
                          15: 45,
                          16: 100,
                          17: -90,
                          18: 700,
                          19: -9)

df["Date"]=pd.to_datetime(df["Date"], format=("%Y-%m-%d"))
df=df.sort_values(["Date","Category","Sum"],ascending=True)
df=round(df.groupby(["Date","Category"]).agg("Sum":"sum").reset_index(),1)



dt_all = pd.date_range(start=df['Date'].iloc[0],end=df['Date'].iloc[-1])
dt_obs = [d.strftime("%Y-%m-%d") for d in df['Date']]
dt_breaks = [d for d in dt_all.strftime("%Y-%m-%d").tolist() if not d in dt_obs]

df=df.set_index('Date')

#fig = px.bar(df, x=df.index.strftime("%Y/%m/%d") , y='Sum',barmode="group",color="Category") 
fig = px.bar(df, x=df.index , y='Sum',barmode="group",color="Category")

fig.update_xaxes(
    rangebreaks=[dict(values=dt_breaks)] # hide dates with no values
)


fig.update_xaxes(
rangeslider_visible=True,
rangeselector=dict(
    buttons=list([
        dict(count=1, label="day", step="day", stepmode="todate"),
        dict(count=24, label="montly", step="month", stepmode="todate"),
        dict(count=1, label="year", step="year", stepmode="todate"),
        dict(step="all")
    ])
   ))


fig.show()

【讨论】:

【参考方案3】:

对于跳过空日期、小时,您应该使用:

import plotly.graph_objects as go

fig.add_trace(go.Candlestick(x=df['begin'], ...)

fig.layout = dict(title=ticker, xaxis = dict(type="category", categoryorder='category ascending'))
fig.show()

这个例子效果很好。 祝你好运

【讨论】:

【参考方案4】:

如果有人在这里玩股票数据,下面是隐藏交易时间以外和周末的代码。

    fig = go.Figure(data=[go.Candlestick(x=df['date'], open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'])])
    fig.update_xaxes(
        rangeslider_visible=True,
        rangebreaks=[
            # NOTE: Below values are bound (not single values), ie. hide x to y
            dict(bounds=["sat", "mon"]),  # hide weekends, eg. hide sat to before mon
            dict(bounds=[16, 9.5], pattern="hour"),  # hide hours outside of 9.30am-4pm
            # dict(values=["2020-12-25", "2021-01-01"])  # hide holidays (Christmas and New Year's, etc)
        ]
    )
    fig.update_layout(
        title='Stock Analysis',
        yaxis_title=f'symbol Stock'
    )

    fig.show()

这里是Plotly's doc。

【讨论】:

【参考方案5】:

想添加到 Mega J 的答案。首先获取您的日期范围内的市场假期列表,如下所示:

xnys = xcals.get_calendar("XNYS", start=import_start, end=import_end)
holidays = pd.to_datetime(xnys.day.holidays)
holiday_mask= (holidays > import_start) & (holidays <= import_end)
hols = holidays[holiday_mask].strftime("%Y-%m-%d").tolist()

从上面复制 Mega J 的代码并将假期添加到 rangebreak:

fig = go.Figure(data=[go.Candlestick(x=df['date'], open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'])])
    fig.update_xaxes(
        rangeslider_visible=True,
        rangebreaks=[
            # NOTE: Below values are bound (not single values), ie. hide x to y
            dict(bounds=["sat", "mon"]),  # hide weekends, eg. hide sat to before mon
            dict(bounds=[16, 9.5], pattern="hour"),  # hide hours outside of 9.30am-4pm
            dict(values=hols)  # hide market holidays inside your date range
        ]
    )
    fig.update_layout(
        title='Stock Analysis',
        yaxis_title=f'symbol Stock'
    )

    fig.show()

【讨论】:

以上是关于Plotly:如何从 x 轴删除空日期?的主要内容,如果未能解决你的问题,请参考以下文章

如何在绘图图中整齐地或以一定间隔的形式显示 X 轴日期刻度

如何在 Plotly 中添加跟踪,并为沿 x 轴的每个数据点设置自定义顺序?

绘制水平堆积条形图不适用于日期中的 x 轴

如何使用 Plotly 删除堆叠和分组条形图中的 x 轴刻度标签

如何从 plotly 中删除图中的轴刻度线?

Plotly.js x 轴无法删除线