构造一个新列,该列使用Pandas给出组中其他元素的平均值

时间:2019-05-13 23:41:21

标签: python pandas dataframe

我想使用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可以找到一种更清洁/更快的方法。

欢迎您使用任何认为可以改善代码的解决方案。谢谢!

2 个答案:

答案 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),而无需删除其他列。
在性能方面,您的分配较少,因此应该更快(但可以忽略)。