【问题标题】:Change monthly data to daily data and spread out values over each day of that month将每月数据更改为每日数据,并将值分布在该月的每一天
【发布时间】:2021-01-08 11:06:44
【问题描述】:

我有一个包含每月数据的 df:

date       | type   | value1 | value2 
2020-04-01 | "a"    | 30     | 60     
2020-04-01 | "b"    | 60     | 120    
2020-04-01 | "c"    | 45     | 180    
...        | ...    | ...    | ...    
2021-02-01 | "a"    | 28     | 56    
2021-02-01 | "b"    | 21     | 42   
2021-02-01 | "c"    | 5.6    | 16.8    

我需要获取每个月的每日数据。 每个 value1 和 value2 应该每个月平均分布。

如果该月有 30 天 = "value1 / 30" 和 "value2 / 30" 该月的每一天。 如果该月有 28 天 = "value1 / 28" 和 "value2 / 28" 该月的每一天。

31 天不变。

结束数据框应该是:

    date   | type | value1 | value2 
2020-04-01 | "a"  | 1      | 2     # 30 days in April 2020
2020-04-02 | "a"  | 1      | 2
2020-04-03 | "a"  | 1      | 2
...        | ...  | ..
2020-04-01 | "b"  | 2      | 4     # 30 days in April 2020
2020-04-02 | "b"  | 2      | 4
2020-04-03 | "b"  | 2      | 4
...        | ...  | ..
2020-04-01 | "c"  | 1.5    | 3     # 30 days in April 2020
2020-04-02 | "c"  | 1.5    | 3
2020-04-03 | "c"  | 1.5    | 3
...        | ...  | ..
2021-02-01 | "a"  | 1      | 2     # 28 days in February 2021
2021-02-02 | "a"  | 1      | 2
2021-02-03 | "a"  | 1      | 2
...        | ...  | ..
2021-02-01 | "b"  | 0.75   | 1.5     # 28 days in February 2021
2021-02-02 | "b"  | 0.75   | 1.5
2021-02-03 | "b"  | 0.75   | 1.5
...        | ...  | ..
2021-02-01 | "c"  | 0.2    | 6     # 28 days in February 2021
2021-02-02 | "c"  | 0.2    | 6
2021-02-03 | "c"  | 0.2    | 6

我怎样才能用熊猫做到这一点?

【问题讨论】:

    标签: python pandas datetime converters


    【解决方案1】:

    首先将DataFrame.reindexdate_range 相加,然后除以DataFrame.divdaysinmonth 每月的天数:

    df['date'] = pd.to_datetime(df['date'])
    rng = pd.date_range(df['date'].min(), df['date'].max() + pd.offsets.MonthEnd(), name='date')
    
    df = df.set_index('date').reindex(rng, method='ffill')
    df = df.div(df.index.daysinmonth, axis=0).reset_index()
    
    print (df)
              date    value1    value2
    0   2020-04-01  1.000000  2.000000
    1   2020-04-02  1.000000  2.000000
    2   2020-04-03  1.000000  2.000000
    3   2020-04-04  1.000000  2.000000
    4   2020-04-05  1.000000  2.000000
    ..         ...       ...       ...
    329 2021-02-24  0.714286  1.071429
    330 2021-02-25  0.714286  1.071429
    331 2021-02-26  0.714286  1.071429
    332 2021-02-27  0.714286  1.071429
    333 2021-02-28  0.714286  1.071429
    
    [334 rows x 3 columns]
    

    编辑:reindex 每个 type 列的解决方案分别使用自定义 lambda 函数:

    df['date'] = pd.to_datetime(df['date'])
    
    f = (lambda x: x.set_index('date')
                    .reindex(pd.date_range(x['date'].min(), 
                                           x['date'].max() + pd.offsets.MonthEnd(), 
                                           name='date'), method='ffill'))
    df = (df.groupby('type').apply(f)
           .reset_index(level=0, drop=True)
           .set_index('type', append=True))
    
    df = df.div(df.index.get_level_values(0).daysinmonth, axis=0, level=0).reset_index()
    print (df)
               date type    value1    value2
    0    2020-04-01    a  0.033333  0.066667
    1    2020-04-02    a  0.033333  0.066667
    2    2020-04-03    a  0.033333  0.066667
    3    2020-04-04    a  0.033333  0.066667
    4    2020-04-05    a  0.033333  0.066667
            ...  ...       ...       ...
    997  2021-02-24    c  0.007143  0.214286
    998  2021-02-25    c  0.007143  0.214286
    999  2021-02-26    c  0.007143  0.214286
    1000 2021-02-27    c  0.007143  0.214286
    1001 2021-02-28    c  0.007143  0.214286
    

    【讨论】:

    • 感谢您的回答,但我需要将一个月中的每一天作为一行,如末尾 df 示例所示。
    • 我很抱歉,但我忘了补充一下,每个月都有一个类型列有大约 18 个不同的值(相应地更改了 df + df 最终结果)。我需要为每个类型列添加月份的天数,您的解决方案给了我“无法使用方法或列表重新索引非唯一索引”。如果你知道这个问题的解决方案,你会这么好心地改变你的答案吗?很抱歉给您带来麻烦。
    猜你喜欢
    • 2021-09-27
    • 1970-01-01
    • 2023-01-15
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    相关资源
    最近更新 更多