1

我尝试更多地了解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

这完全没问题。但我想知道是否有可能(我确信有)使用 apply 方法获得相同的结果。我试过了:

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 件事,但没有任何效果......我希望有人可以在这里帮助我?!

4

3 回答 3

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
于 2019-02-13T15:32:03.597 回答
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
于 2019-02-13T15:36:27.637 回答
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
于 2019-02-13T15:41:45.007 回答