我试图计算所有类别的日期均值。但是,每个类别(示例中称为mygroup
)都没有每个日期的值。我想在pandas中使用apply来计算每个日期的平均值,使用小于或等于当前日期的最接近日期填充值。例如,如果我有:
pd.DataFrame({'date':['1','2','3','6','1','3','4','5','1','2','3','4'],
'mygroup':['a','a','a','a','b','b','b','b','c','c','c','c'],
'myval':[10,20,30,40,50,60,70,80,90,100,110,120]})
date mygroup myval
0 1 a 10
1 2 a 20
2 3 a 30
3 6 a 40
4 1 b 50
5 3 b 60
6 4 b 70
7 5 b 80
8 1 c 90
9 2 c 100
10 3 c 110
11 4 c 120
计算date == 1
的平均值应该等于(10 + 50 + 90)/3 = 50
,这可以通过典型的平均应用组日期来完成。但是,对于date == 6
,我想使用每个mygroup
的最后已知值。 date == 6
的平均值将计算为
(40 + 80 + 120)/3 = 80
由于a
的值为date == 6
40
,b
的值不是date == 6
,所以最后已知值为date == 5
,80
,c
的最后已知值为date == 4
120
。最终结果应如下所示:
date meanvalue
1 50
2 56.67
3 66.67
4 73.33
5 76.67
6 80
是否可以使用groupby计算日期的平均值,并以这种方式应用,使用每个mygroup
并填写最后一个已知值,如果当前日期没有值?这必须在数千个日期和数万个类别中完成,因此应避免使用循环。
答案 0 :(得分:3)
df.set_index(['mygroup', 'date']).unstack().ffill(axis=1) \
.stack().groupby(level=1).mean()
myval
date
1 50.000000
2 56.666667
3 66.666667
4 73.333333
5 76.666667
6 80.000000
要记住,对于许多问题有用的关键点是堆叠/取消堆叠/旋转等...... " rubikscubing" 您的数据框始终如一填充稀疏格式的空白(比如你必须开始的柱状格式)到一个密集的NAs中。
因此,如果您能够使用全密集矩阵轻松进行计算,那么我建议您始终首先关注获得密集矩阵,以便之后可以进行简单的数学运算。
答案 1 :(得分:0)
您可以将所有隐式缺失值转换为显式,并使用前向填充方案填充缺失值,然后按平均值进行正常分组:
from itertools import product
import pandas as pd
# get all combinations of date and mygroup using product function from itertools
all_combinations = list(product(df.date.drop_duplicates(), df.mygroup.drop_duplicates()))
# convert implicit missing values to explicit missing values by merging all combinations
# with original data frame
df1 = pd.merge(df, pd.DataFrame.from_records(all_combinations,
columns = ['date', 'mygroup']), 'outer')
# fill missing date values with previous date values within each group
df1.sort_values(['mygroup', 'date']).ffill().groupby('date').mean()
# myval
#date
#1 50.000000
#2 56.666667
#3 66.666667
#4 73.333333
#5 76.666667
#6 80.000000