【问题标题】:Create facet plot of pandas dataframe with month of year on x-axis在 x 轴上创建带有年份月份的 pandas 数据帧的平面图
【发布时间】:2021-08-24 19:10:42
【问题描述】:

我有一个数据系列,其中包含各个会计年度的月销售额。我正在使用pandas 数据框来存储数据。每个会计年度从三月的第一天开始,到次年二月的最后一天结束。我正在使用plotly 平面图来显示一年中垂直对齐的月份,因此 2021 年 3 月低于 2020 年 3 月,依此类推。

尽管对 x 轴使用了分类变量,但排序略有偏差。我尝试使用具有唯一值的“yearmon”变量进行排序,但这也不起作用。具体来说,在下图中,2018 年 1 月和 2 月的值是空白的,2021 年 1 月和 2 月的值也不合适。我怎样才能在没有这些问题的情况下获得显示连续数据的方面? 编辑:我感觉它与类别的顺序有关,但还没有设法确定。

import pandas as pd
import numpy as np
import plotly.express as px
import chart_studio.plotly as py

rng = np.random.default_rng(12345)
df = pd.DataFrame(rng.integers(80, 100, size=(36, 1)), columns=list('A'))
df.index = pd.date_range("2018-03-01", periods=36, freq="M")
df['year'] = df.index.strftime('%Y')
df['month'] = df.index.strftime('%b')
df['monthindex'] = df.index.strftime('%m')
df['yearmon'] = df['year']+df['monthindex']

month_categories = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
df["month"] = pd.Categorical(df["month"], categories = month_categories)
df = df.sort_values(by = "yearmon")

fig = px.bar(df, x = 'month', y = 'A', facet_col='year', facet_col_wrap=1)
py.image.save_as(fig, 'plotly.png', width=1000, height=500)

更新

使用下面@vestland 的代码作为基础,我根据下面的评论调整了开始日期和财政年度分配,因为财政年度通常与日历年不一致。此外,数据系列的长度是任意的——可能是几个月,也可能是十年——开始和结束月份也是如此。最后,我希望 x 轴以财政年度的第一个月和最后几个月开始和结束,所以在这种情况下(三月和二月)“三月”应该是左边的第一个刻度线,“二月”右边的最后一个。如果不够清楚,我深表歉意。

import pandas as pd
import numpy as np
import plotly.express as px
import chart_studio.plotly as py

rng = np.random.default_rng(12345)
df = pd.DataFrame(rng.integers(80, 100, size=(36, 1)), columns=list('A'))
df.index = pd.date_range("2018-01-01", periods=36, freq="M")
df['year'] = df.index.strftime('%Y')
df['month'] = df.index.strftime('%b')
df['monthindex'] = df.index.strftime('%m')
df['yearmon'] = df['year']+df['monthindex']

month_categories = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
df["month"] = pd.Categorical(df["month"], categories = month_categories)
df = df.sort_values(by = "yearmon")

df['fiscal_year'] = [2017]*2+[2018]*12+[2019]*12+[2020]*10
fig = px.bar(df, x = 'month', y = 'A', facet_col='fiscal_year', facet_col_wrap=1)
fig.show()

这似乎给出了以下内容:

【问题讨论】:

    标签: python pandas plotly plotly-python


    【解决方案1】:

    这种情况下的问题似乎是 plotly 不尊重用于 x 轴的 pandas 数据系列中类别的顺序,除非特别指示这样做,如 plotly 论坛 here 中所指出的那样,并记录了here。在 px.bar 调用中使用 category_orders 允许我们覆盖默认的绘图假设并创建一个从指定财政年度的第一个月到财政年度最后一个月的 x 轴。

    import pandas as pd
    import numpy as np
    import plotly.express as px
    import chart_studio.plotly as py
    
    rng = np.random.default_rng(12345)
    df = pd.DataFrame(rng.integers(80, 100, size=(36, 1)), columns=list('A'))
    df.index = pd.date_range("2018-01-01", periods=36, freq="M")
    df['year'] = df.index.strftime('%Y')
    df['month'] = df.index.strftime('%b')
    df['monthindex'] = df.index.strftime('%m')
    df['yearmon'] = df['year']+df['monthindex']
    
    month_categories = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
    df["month"] = pd.Categorical(df["month"], categories = month_categories)
    df = df.sort_values(by = "yearmon")
    
    df['fiscal_year'] = [2017]*2+[2018]*12+[2019]*12+[2020]*10
    
    fig = px.bar(df, x = 'month', y = 'A', 
                  facet_col='fiscal_year',
                  facet_col_wrap=1,
                  category_orders={ # replaces default order by column name
                    "month": ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
                })       
    fig.show() 
    

    【讨论】:

      【解决方案2】:

      如果我理解正确,那么除了一个小细节之外,您似乎做的一切都是正确的。这有点令人惊讶,所以我很可能误解了你问题的前提。总之……

      具体来说,在下图中,2018 年 1 月和 2 月的值是空白的

      那是因为df.head() 中不存在这样的日期

                   A  year month monthindex yearmon
      2018-03-31  93  2018   Mar         03  201803
      2018-04-30  84  2018   Apr         04  201804
      2018-05-31  95  2018   May         05  201805
      2018-06-30  86  2018   Jun         06  201806
      2018-07-31  84  2018   Jul         07  201807
      

      如果我正确理解您的意图,您实际上希望将january and february of 2019 与第一个 x 轴相关联。尽管您付出了极大的努力,但还没有建立这样的关联。我不太确定你会怎么做,但如果你确保设置这样的东西:

      df['fiscal_year'] = [2018]*12+[2019]*12+[2020]*12
      

      得到:

      然后就可以运行了

      fig = px.bar(df, x = 'month', y = 'A', facet_col='fiscal_year',facet_col_wrap=1)
      

      得到:

      如您所见,January and february of 2019 现在出现在 2018 年的 x 轴上。其余年份以此类推。我希望这就是你要找的。如果没有,请随时告诉我。

      完整代码:

      import pandas as pd
      import numpy as np
      import plotly.express as px
      import chart_studio.plotly as py
      
      rng = np.random.default_rng(12345)
      df = pd.DataFrame(rng.integers(80, 100, size=(36, 1)), columns=list('A'))
      df.index = pd.date_range("2018-03-01", periods=36, freq="M")
      df['year'] = df.index.strftime('%Y')
      df['month'] = df.index.strftime('%b')
      df['monthindex'] = df.index.strftime('%m')
      df['yearmon'] = df['year']+df['monthindex']
      
      month_categories = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
      df["month"] = pd.Categorical(df["month"], categories = month_categories)
      df = df.sort_values(by = "yearmon")
      
      df['fiscal_year'] = [2018]*12+[2019]*12+[2020]*12
      fig = px.bar(df, x = 'month', y = 'A', facet_col='fiscal_year', facet_col_wrap=1)
      fig.show()
      

      【讨论】:

      • 谢谢你。请注意,财政年度从三月到二月,而不是(在您的示例中)一月到十二月,在这种情况下,您的代码似乎不会产生所需的输出。我们可以通过将开始日期从2018-03-01 更改为2018-01-01 并将会计年度分配为df['fiscal_year'] = [2017]*2+[2018]*12+[2019]*12+[2020]*10 来测试这一点。现在您可以看到 2018 年 1 月和 2 月是 2017 财年的一部分。这给出了一个有四个面的图表(2017 年到 2020 年),x 轴从 1 月到 12 月运行,我希望它固定在 3 月到二月
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      相关资源
      最近更新 更多