用 groupby 对象中的“ones”填充缺失的组合

时间:2021-04-18 13:50:53

标签: python pandas pandas-groupby

我有以下格式的数据。

date        group   ret
1986-01-31  1       1.3
1986-01-31  1       0.9
1986-01-31  2       1.4
1986-01-31  2       1.6
1986-01-31  2       1.5
1986-01-31  3       1.1
1986-02-28  2       1.3
1986-02-28  2       1.1

我想获得每个日期和组的平均回报,我这样做了:

output = df.groupby(['date', 'group'])['ret'].mean() + 1 
output = output.reset_index()

给出以下输出:

date        group   ret
1986-01-31  1       1.1
1986-01-31  2       1.5
1986-01-31  3       1.1
1986-02-28  2       1.2

但是,由于在日期 1986-02-28 没有为第 1 类和第 3 类给出“ret”,因此该日期在第 1 类和第 3 类的输出中没有行。我想要的是,对于原始数据框中未给出返回值的日期和类的任何组合,此组合在输出中获取并输出“1”。因此,所需的输出是:

date        group   ret
1986-01-31  1       1.1
1986-01-31  2       1.5
1986-01-31  3       1.1
1986-02-28  1       1
1986-02-28  2       1.2
1986-02-28  3       1

这个问题有什么好的解决方案?提前致谢!

3 个答案:

答案 0 :(得分:4)

我们可以先pivot_table然后stack

out = df.pivot_table(index='date',columns='group',values='ret',aggfunc = 'mean').fillna(1).stack().reset_index(name='value')
         date  group  value
0  1986-01-31      1    1.1
1  1986-01-31      2    1.5
2  1986-01-31      3    1.1
3  1986-02-28      1    1.0
4  1986-02-28      2    1.2
5  1986-02-28      3    1.0

答案 1 :(得分:2)

您可以重新索引 groupbymean 的结果并用 1 填充空值:

output = df.groupby(['date', 'group'])['ret'].mean().reindex(
    pd.MultiIndex.from_product(
        (pd.date_range(df.date.min(), df.date.max(), freq='M'),
         sorted(df.group.unique())),
        names=['date', 'group'],
    )
).fillna(1).reset_index()

这是您问题中 DataFrame 的结果:

        date  group  ret
0 1986-01-31      1  1.1
1 1986-01-31      2  1.5
2 1986-01-31      3  1.1
3 1986-02-28      1  1.0
4 1986-02-28      2  1.2
5 1986-02-28      3  1.0

答案 2 :(得分:2)

您可以使用 complete 中的 pyjanitor 函数来公开显式缺失的值,并将 fillna1 一起使用:

# pip install pyjanitor
import janitor
(df.groupby(['date', 'group'], as_index = False)
   .ret
   .mean()
   .complete(['date', 'group'])
   .fillna(1)
 )

         date  group  ret
0  1986-01-31      1  1.1
1  1986-01-31      2  1.5
2  1986-01-31      3  1.1
3  1986-02-28      1  1.0
4  1986-02-28      2  1.2
5  1986-02-28      3  1.0

或者,您可以将 group 列转换为 categorical dtype,所有类别都将在 groupby 期间保持:

from pandas.api.types import CategoricalDtype
(df
 .astype({"group": CategoricalDtype(categories=df.group.unique())})
 .groupby(['date', 'group'], as_index = False)
 .ret
 .mean()
 .fillna(1)
 )

         date group  ret
0  1986-01-31     1  1.1
1  1986-01-31     2  1.5
2  1986-01-31     3  1.1
3  1986-02-28     1  1.0
4  1986-02-28     2  1.2
5  1986-02-28     3  1.0