通过将函数应用于另一个数据框的列来创建新数据框
Create a new dataframe by applying function to columns of another dataframe
我尝试在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 其他东西,但没有任何效果......
我希望有人能在这里帮助我?!
一般来说,您应该尝试看看是否可以避免使用 .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
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
这是另一种方法,不像其他人所展示的那样纯粹pandas。
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
我尝试在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 其他东西,但没有任何效果...... 我希望有人能在这里帮助我?!
一般来说,您应该尝试看看是否可以避免使用 .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
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
这是另一种方法,不像其他人所展示的那样纯粹pandas。
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