我想使用Pandas编写新的列来提高性能和美观度,该列提供组中其他元素的平均值。
您可以将其视为每个日期其他类型的平均值。
我的原始数据帧(df)是:
idx = [np.array(['Jan-18', 'Jan-18', 'Feb-18', 'Mar-18', 'Mar-18', 'Mar-18','Mar-18', 'Mar-18', 'May-18', 'Jun-18', 'Jun-18', 'Jun-18','Jul-18', 'Aug-18', 'Aug-18', 'Sep-18', 'Sep-18', 'Oct-18','Oct-18', 'Oct-18', 'Nov-18', 'Dec-18', 'Dec-18',]),np.array(['A', 'B', 'B', 'A', 'B', 'C', 'D', 'E', 'B', 'A', 'B', 'C','A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'A', 'B', 'C'])]
data = [{'xx': 1}, {'xx': 5}, {'xx': 3}, {'xx': 2}, {'xx': 7}, {'xx': 3},{'xx': 1}, {'xx': 6}, {'xx': 3}, {'xx': 5}, {'xx': 2}, {'xx': 3},{'xx': 1}, {'xx': 9}, {'xx': 3}, {'xx': 2}, {'xx': 7}, {'xx': 3}, {'xx': 6}, {'xx': 8}, {'xx': 2}, {'xx': 7}, {'xx': 9}]
df = pd.DataFrame(data, index=idx, columns=['xx'])
df.index.names=['date','type']
df=df.reset_index()
df['date'] = pd.to_datetime(df['date'],format = '%b-%y')
df=df.set_index(['date','type'])
我的代码是:
df['avg'] = df.groupby('date').transform('mean')
df['N'] = (df.assign(TYPE = df.index.get_level_values('type')).groupby('date').TYPE.transform('nunique'))
df['zzz']= df['avg'].multiply(df['N'], axis=0)
df['hhh']= df['zzz']-df['xx']
df['yy'] = df['hhh'].div((df['N']-1))
del df['avg']
del df['N']
del df['zzz']
del df['hhh']
结果是:
xx yy
date type
2018-01-01 A 1.0 5.00
B 5.0 1.00
2018-02-01 B 3.0 NaN
2018-03-01 A 2.0 4.25
B 7.0 3.00
C 3.0 4.00
D 1.0 4.50
E 6.0 3.25
2018-05-01 B 3.0 NaN
2018-06-01 A 5.0 2.50
B 2.0 4.00
C 3.0 3.50
2018-07-01 A 1.0 NaN
2018-08-01 B 9.0 3.00
C 3.0 9.00
2018-09-01 A 2.0 7.00
B 7.0 2.00
2018-10-01 C 3.0 7.00
A 6.0 5.50
B 8.0 4.50
2018-11-01 A 2.0 NaN
2018-12-01 B 7.0 9.00
C 9.0 7.00
尽管如此,我能够正确地获取给定日期的其他元素的平均值,但我认为使用Pandas可以找到一种更清洁/更快的方法。
欢迎您使用任何认为可以改善代码的解决方案。谢谢!
答案 0 :(得分:2)
您在这里:
df['yy'] = (df.groupby('date').xx
.apply(lambda x: (x.sum() - x)/(len(x) - 1))
)
输出:
xx yy
date type
2018-01-01 A 1 5.00
B 5 1.00
2018-02-01 B 3 NaN
2018-03-01 A 2 4.25
B 7 3.00
C 3 4.00
D 1 4.50
E 6 3.25
2018-05-01 B 3 NaN
2018-06-01 A 5 2.50
B 2 4.00
C 3 3.50
2018-07-01 A 1 NaN
2018-08-01 B 9 3.00
C 3 9.00
2018-09-01 A 2 7.00
B 7 2.00
2018-10-01 C 3 7.00
A 6 5.50
B 8 4.50
2018-11-01 A 2 NaN
2018-12-01 B 7 9.00
C 9 7.00
答案 1 :(得分:1)
我认为您的代码还不错。您唯一可以做的就是在一行中进行数学运算,而无需保存和删除中间列。
df['avg'] = df.groupby('date').transform('mean')
N = (df.assign(TYPE = df.index.get_level_values('type')).groupby('date').TYPE.transform('nunique'))
df['yy'] = (df['avg'].multiply(N, axis=0) - df['xx']).div(N-1)
这给您最终的结果。
N
是一个单独的数据框(您可以将其保留在此处或根据需要执行del N
),而无需删除其他列。
在性能方面,您的分配较少,因此应该更快(但可以忽略)。