第一:也许这适合代码审查更好,但我认为这里是更多熊猫仿射用户。随意移动它,如果你认为否则根据其他列创建新列:DRY并启用功能
这是常有的情况下,一个要计算一个新列了现有的: 考虑以下大熊猫据帧
df = pd.DataFrame({'ItemNumber':np.arange(1, 10),
'A':[1,1,1,2,2,2,3,3,3], 'B': [1,2,3]*3})
print(df)
A B ItemNumber
0 1 1 1
1 1 2 2
2 1 3 3
3 2 1 4
4 2 2 5
5 2 3 6
6 3 1 7
7 3 2 8
8 3 3 9
比方说,我们计算通过
df.loc[(df["A"] == 1) & (df["B"] > 1), 'C'] = 1
df.loc[(df["B"] == 1) & (df["A"] > 1), 'C'] = 2
df.loc[(df["A"] > 1) & (df["B"] > 1), 'C' ] = 3
df.loc[(df["A"] == 1) & (df["B"] == 1), 'C' ] = 4
新列“C”这会相比,迭代的方法,在大型dataframes执行相当快也呈现here。 特别是,该方法的性能问题使我得到了上述代码。
但是,这段代码违反了DRY原则。复制粘贴感觉很尴尬。
所以,让我们多一点的功能和定义两个咖喱功能:
def col_equals_value(col, value):
def filter_df(df):
return df[col] == value
return filter_df
def col_greater_value(col, value):
def filter_df(df):
return df[col] > value
return filter_df
从那里,我们定义的比较:需要
a1 = col_equals_value('A', 1)
b1 = col_equals_value('B', 1)
agt1 = col_greater_value('A', 1)
bgt1 = col_greater_value('B', 1)
另一个函数的值赋给列:
def assign_value(cond_1, cond_2, value):
def assign_col_value(df, col):
df.loc[df.apply(cond_1, axis=1) & df.apply(cond_2, axis=1), col] =value
return assign_col_value
最后,我们可以定义condtion-to-values mappin G作为
mapping = [(a1, b1, 4),
(a1, bgt1, 1),
(agt1, b1, 2),
(agt1, bgt1, 3)]
构建assign_value_functions
m = [assign_value(x, y, z) for (x,y,z) in mapping]
和各功能适用于数据框:
for f in m:
f(df, 'C')
print(df)
A B ItemNumber
0 1 1 1
1 1 2 2
2 1 3 3
3 2 1 4
4 2 2 5
5 2 3 6
6 3 1 7
7 3 2 8
8 3 3 9
那么什么是问题? 这种方法似乎不是非常可扩展的。对于每个比较运算符,我似乎都需要定义一个全新的函数。比较运算符是一个变量吗? 目前,我只支持2个条件与&运营商连接。如何推广? 我不确定如何调用apply方法。我觉得应该有一个更简单的方法。
欢迎任何帮助
嘿,我真的很喜欢你的想法,它很简单,映射的定义比较精确。但是,我还不确定我是否在寻找更多功能的解决方案。我想,我的解决方案可以通过使用运算符模块和reduce函数来改进,以允许任意多个条件。但映射/转换可能不太可读。 – Quickbeam2k1