我在Python3中使用Pandas DataFrame。它有分类、日期和值的列。对于每个类别,我希望添加包含缺失天数的行,这样的值是线性内插的。
要创建最小的示例,我使用以下代码
df = pd.DataFrame({
'cat':['A', 'A', 'A', 'A', 'B', 'B', 'B'],
'date': ['2021-1-1', '2021-1-4', '2021-1-5', '2021-1-7', '2021-11-1', '2021-11-2', '2021-11-5'],
'value': [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 9.0]})
df['cat'] = df['cat'].astype('category')
df['date'] = df['date'].astype('datetime64'),它提供了以下数据
cat date value
A 2021-01-01 1.0
A 2021-01-04 2.0
A 2021-01-05 3.0
A 2021-01-07 4.0
B 2021-11-01 5.0
B 2021-11-02 6.0
B 2021-11-05 9.0我希望输出类似于这个例子,其中我使用'<‘来指示新插入的行
cat date value
A 2021-01-01 1.0
A 2021-01-02 1.333 <
A 2021-01-03 1.667 <
A 2021-01-04 2.0
A 2021-01-05 3.0
A 2021-01-06 3.5 <
A 2021-01-07 4.0
B 2021-11-01 5.0
B 2021-11-02 6.0
B 2021-11-03 7.0 <
B 2021-11-04 8.0 <
B 2021-11-05 9.0在实际问题中,我不希望周末(星期六和星期日),但我已经说明了上述问题,以防止添加额外的层(我可以轻松过滤周末天以后,如果需要)。但是,不将它们包含在第一步可能会允许更高效的代码,所以我想我也会提到这个问题。谢谢你的帮助!
发布于 2021-11-09 11:02:47
将DataFrame.groupby与重采样或Series.asfreq一起使用,用于丢失数天,然后在lambda函数中对每个组内插:
df = (df.set_index('date')
.groupby('cat')['value']
.apply(lambda x: x.asfreq('d').interpolate())
.reset_index())
print (df)
cat date value
0 A 2021-01-01 1.000000
1 A 2021-01-02 1.333333
2 A 2021-01-03 1.666667
3 A 2021-01-04 2.000000
4 A 2021-01-05 3.000000
5 A 2021-01-06 3.500000
6 A 2021-01-07 4.000000
7 B 2021-11-01 5.000000
8 B 2021-11-02 6.000000
9 B 2021-11-03 7.000000
10 B 2021-11-04 8.000000
11 B 2021-11-05 9.000000df = (df.set_index('date')
.groupby('cat')['value']
.apply(lambda x: x.resample('d').first().interpolate())
.reset_index())
print (df)
cat date value
0 A 2021-01-01 1.000000
1 A 2021-01-02 1.333333
2 A 2021-01-03 1.666667
3 A 2021-01-04 2.000000
4 A 2021-01-05 3.000000
5 A 2021-01-06 3.500000
6 A 2021-01-07 4.000000
7 B 2021-11-01 5.000000
8 B 2021-11-02 6.000000
9 B 2021-11-03 7.000000
10 B 2021-11-04 8.000000
11 B 2021-11-05 9.000000或者:
f = lambda x: x.interpolate()
s = df.set_index('date').groupby('cat')['value'].resample('d').first().groupby(level=0).apply(f)
print (s)
cat date
A 2021-01-01 1.000000
2021-01-02 1.333333
2021-01-03 1.666667
2021-01-04 2.000000
2021-01-05 3.000000
2021-01-06 3.500000
2021-01-07 4.000000
B 2021-11-01 5.000000
2021-11-02 6.000000
2021-11-03 7.000000
2021-11-04 8.000000
2021-11-05 9.000000
Name: value, dtype: float64发布于 2021-11-09 11:08:14
您可以使用一个助手函数:
def interpolate(d, on='date', vals=['value']):
return (d.set_index(on).reindex(pd.date_range(d[on].min(), d[on].max()))
[vals].interpolate()
.rename_axis(on)
)
df.groupby('cat').apply(interpolate).reset_index()产出:
cat date value
0 A 2021-01-01 1.000000
1 A 2021-01-02 1.333333
2 A 2021-01-03 1.666667
3 A 2021-01-04 2.000000
4 A 2021-01-05 3.000000
5 A 2021-01-06 3.500000
6 A 2021-01-07 4.000000
7 B 2021-11-01 5.000000
8 B 2021-11-02 6.000000
9 B 2021-11-03 7.000000
10 B 2021-11-04 8.000000
11 B 2021-11-05 9.000000发布于 2021-11-09 11:20:11
# pip install git+https://github.com/pyjanitor-devs/pyjanitor.git
import pandas as pd
import janitor
dates = dict(date = lambda df: pd.date_range(df.min(), df.max(), freq='1D'))
(df.complete(dates, by='cat', sort = True)
.assign(value = lambda df: df.value.interpolate())
)
cat date value
0 A 2021-01-01 1.000000
1 A 2021-01-02 1.333333
2 A 2021-01-03 1.666667
3 A 2021-01-04 2.000000
4 A 2021-01-05 3.000000
5 A 2021-01-06 3.500000
6 A 2021-01-07 4.000000
7 B 2021-11-01 5.000000
8 B 2021-11-02 6.000000
9 B 2021-11-03 7.000000
10 B 2021-11-04 8.000000
11 B 2021-11-05 9.000000complete公开缺少的值,然后我们在linear方法上进行插值。
https://stackoverflow.com/questions/69896763
复制相似问题