将每月数据更改为每日数据,并将值分布在该月的每一天
Posted
技术标签:
【中文标题】将每月数据更改为每日数据,并将值分布在该月的每一天【英文标题】: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
我怎样才能用熊猫做到这一点?
【问题讨论】:
【参考方案1】:首先将DataFrame.reindex
与date_range
相加,然后除以DataFrame.div
与daysinmonth
每月的天数:
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 最终结果)。我需要为每个类型列添加月份的天数,您的解决方案给了我“无法使用方法或列表重新索引非唯一索引”。如果你知道这个问题的解决方案,你会这么好心地改变你的答案吗?很抱歉给您带来麻烦。以上是关于将每月数据更改为每日数据,并将值分布在该月的每一天的主要内容,如果未能解决你的问题,请参考以下文章
AppEngine cron (python) 中的每一天、每周、每月、每年
如何在 PostgreSQL 中获取表的每一天的第一个日期并将其转换为 JSON