通过将函数应用于另一个数据框的列来创建新的数据框

时间:2019-02-13 15:22:36

标签: python pandas pandas-apply

我尝试了解有关python中apply方法的更多信息,并问自己如何使用apply编写以下代码:

我有一个数据框df,如下所示:

  A B C D E points
0 0 0 0 1 43 94
1 0 0 1 1 55 62
2 1 1 0 1 21 84
3 1 0 1 0 13 20

此外,我还有一个类似以下的功能,可以完成其工作:

def f1(df):
  df_means = pd.DataFrame(columns = ['Mean_Points'])
  for columnname in df.columns:
    if len(df[df[columnname] == 1]) > 1:
      df_means.loc[columnname] = [df[df[columnname] == 1]['points'].mean()]
  return df_means

所以f1的输出是

  'Mean_Points'
A      52
C      41
D      80

那很好。 但是我想知道是否有可能(通过应用确定)获得相同的结果。 我尝试过:

df_means = pd.DataFrame(columns = ['Mean_Points'])
cols = [col for col in df.columns if len(df[df[col] == 1]) > 1]
df_means.loc[cols] = df[cols].apply(lambda x: df[df[x] == 1]['points'].mean(), axis = 1)

或类似的内容:

df_means = pd.DataFrame(columns = ['Mean_Points'])
df.columns.apply(lambda x: df_means.loc[x] = [df[df[x] == 1]['points'].mean()] if len(df[df[x] == 1]) > 1 else None)

和其他2,3件事,但没有任何效果... 我希望有人可以在这里帮助我吗?!

3 个答案:

答案 0 :(得分:3)

通常,您应该尝试看看是否可以避免使用.apply(axis=1)

在这种情况下,您可以使用DataFrame.mulitply()来代替,将0替换为np.NaN,这样就不会计入平均值。

import numpy as np

s = df.replace(0, np.NaN).multiply(df.points, axis=0).mean()
#A           52.0
#B           84.0
#C           41.0
#D           80.0
#E         2369.0
#points    5034.0
#dtype: float64

现在,我们将添加您的条件,以仅考虑具有多个1实例的列以及属于.reindex的那些列的子集

m = df.eq(1).sum().gt(1)
s = s.reindex(m[m].index)

输出s

A      52.0
C      41.0
D      80.0
dtype: float64

答案 1 :(得分:3)

pd.DataFrame.dot

#                      filters s to be just those
#                      things greater than 1
#                      v
s = df.eq(1).sum().loc[lambda x: x > 1]
df.loc[:, s.index].T.dot(df.points).div(s)

A    52.0
C    41.0
D    80.0
dtype: float64

一种班轮运输方式

这删除了谷壳,但可能进行了不必要的计算。

df.T.dot(df.points).div(df.sum())[df.eq(1).sum().gt(1)]

A    52.0
C    41.0
D    80.0
dtype: float64

答案 2 :(得分:0)

这是另一种方法,不仅仅像其他人所展示的那样是熊猫

cols = ['A', 'B', 'C', 'D']

def consolidate(series):
    cond = series > 0
    points = df.loc[cond, 'points']
    if len(points) > 1:
        return series.name, points.mean()
    else:
        return series.name, np.nan

df1 = pd.DataFrame([consolidate(df[col]) for col in cols], columns=['name', 'mean_points'])


print(df1)


  name  mean_points
0    A         52.0
1    B          NaN
2    C         41.0
3    D         80.0

如果不需要NaN,那么

df1.dropna()

  name  mean_points
0    A         52.0
2    C         41.0
3    D         80.0

并使用apply

df[cols].apply(consolidate,result_type='expand')
        .T.dropna()
        .reset_index()
        .drop('index', axis=1)

0  A  52
1  C  41
2  D  80