【问题标题】:Python Pandas Pivot() with Dates as Column Names Need to Sort and Format以日期为列名的 Python Pandas Pivot() 需要排序和格式化
【发布时间】:2023-04-05 11:19:01
【问题描述】:

我在这里看到了其他 cmets,了解当 pivot() 将日期设为列名时如何正确地对列进行排序。我没有看到的是如何在排序后将这些日期转换为我想要的格式。

这是我的例子。我的数据如下所示:

category date value1 value2
a 12/1/2018 1 25
a 1/1/2019 2 26
a 2/1/2019 3 27
b 12/1/2018 4 28
b 1/1/2019 5 29
b 2/1/2019 6 30
c 12/1/2018 7 31
c 1/1/2019 8 32
c 2/1/2019 9 33

我想要的是这样的:

category value Dec-18 Jan-19 Feb-19
a value1 1 2 3
a value2 25 26 27
b value1 4 5 6
b value2 28 29 30
c value1 7 8 9
c value2 31 32 33

我已经想出了如何让枢轴一次执行一个值,并且只要我不尝试格式化日期,就可以对日期进行排序。但是 pivot 正在将这些日期转换为文本,所以我不能再更改格式了。

这是我目前所拥有的:

#df['date'] = pd.to_datetime(df.date).dt.strftime('%b-%y') final = df.pivot(index='category', columns='date', values='value1')

如果我先进行日期格式化,则排序不正确。我也尝试过 pivot_table,但它不允许我设置 aggfunc=None

日期格式必须是动态的,也就是每个月的日期范围都会不同(过去 12 个月),所以我不想硬编码日期。

谢谢!

【问题讨论】:

    标签: python pandas date pivot


    【解决方案1】:

    这可能不是最干净的解决方案。

    这是我用来重现您已有内容的代码:

    import pandas as pd
    
    df = pd.DataFrame({
        "category":["a","a","a","b","b","b","c","c", "c"],
        "date":["12/1/2018", "1/1/2019", "2/1/2019", "12/1/2018", "1/1/2019", 
        "2/1/2019", "12/1/2018", "1/1/2019", "2/1/2019"], 
        "value1": [1,2,3,4,5,6,7,8,9], 
        "value2":[25,26,27,28,29,30,31,32,33],
        })
    
    df["date"] = pd.to_datetime(df["date"]).dt.strftime("%b-%y")
    

    然后,您可以通过以下方式接近您想要的pandas.DataFrame

    df = df.pivot(index="date", columns="category") # rows are `date` and columns are `value-category` pairs
    df = df.unstack()                               # Bring back `value1` and `value2` as an index
    df = df.reset_index("date")                     # `date` was an index, we bring it back as a column
    df = df.pivot(columns="date")                   # Use pandas.DataFrame.pivot() once more to pivot on `date`
    df = df.sort_values(by="category")              # Sort output as shown in your desired `pandas.DataFrame`
    

    这会导致pandas.DataFrame

                         0              
    date            Dec-18 Feb-19 Jan-19
           category                     
    value1 a             1      3      2
    value2 a            25     27     26
    value1 b             4      6      5
    value2 b            28     30     29
    value1 c             7      9      8
    value2 c            31     33     32
    

    【讨论】:

    • 感谢您的回复。我最终得到了多个类别,这很好,但我无法格式化日期。当我尝试这样做时: pd.to_datetime(df.ACTUAL_DATE).dt.strftime('%b-%y') 我收到以下错误:AttributeError: 'DataFrame' object has no attribute 'date'。我在顶部的日期值如下所示:2016-12-01
    • 所以我之前没有看到格式的东西。这导致列被错误地排序,即 Apr-18、Apr-19、Apr-20 而不是 Apr-18、May-18、Jun-18。我发现正确排序的唯一方法是在进行数据透视之前将日期值设为 2016-12-01。
    • 仍然没有弄清楚如何格式化日期。欢迎任何想法!
    【解决方案2】:

    我在一位同事的帮助下解决了这个问题。

    df2= df.pivot(index="date", columns="category")
    df2= df2.unstack() 
    df2= df2.reset_index("date")  
    df2= df2.pivot(columns="date") 
    df2= df2.sort_values(by="category")
    df2.columns = df2.columns.set_levels(summary2.columns.levels[1].strftime('%Y-%b-%d'), level='date')
    

    这种日期格式并不完全符合我的要求,但它比原来的格式有效且看起来更好。

    df2= df2.droplevel(level=0, axis=1)
    df2.columns = [''.join(col).strip() for col in df2.columns.values]
    df2.columns = summary2.columns.get_level_values(0)
    

    表格最终看起来像这样:

    category 2018-Dec-1 2019-Jan-1 2019-Feb-1
    value1 a 1 2 3
    value2 a 25 26 27
    value1 b 4 5 6
    value2 b 28 29 30
    value1 c 7 8 9
    value2 c 31 32 33

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-23
      • 2017-06-28
      • 1970-01-01
      • 2011-09-22
      • 2021-05-08
      • 2016-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多