根据另一列的条件在数据框中应用特定函数替换列值
我想要做的是:
Dataframe before:
name value apply_f
0 SEBASTIEN 9 false
1 JOHN 4 false
2 JENNY np.inf true
Apply function f: len(df['name']) to columns 'value' only if columns 'apply_f' == True
Dataframe after:
name value apply_f
0 SEBASTIEN 9 False
1 JOHN 4 False
2 JENNY 5 True
这是我现在的代码:
from pandas import *
from numpy import *
df = DataFrame( { "name": ['SEBASTIEN', 'JOHN', 'JENNY'] ,
"value": [9, 4, np.inf] ,
"apply_f": [False,False,True]} )
def f(x):
return len(x)
df['value'] = df[df['apply_f'] == True]['name'].apply(f)
但是结果并不是我想要的:
apply_f name value
0 False SEBASTIEN NaN
1 False JOHN NaN
2 True JENNY 5
这个列把最开始的值都替换成了NaN
1 个回答
4
之所以会覆盖,是因为左边的索引默认是整个数据表。如果你在左边也使用 loc
来应用这个条件,那么它只会影响那些满足条件的行:
In [272]:
df.loc[df['apply_f'] == True, 'value'] = df[df['apply_f'] == True]['name'].apply(lambda row: f(row))
df
Out[272]:
apply_f name value
0 False SEBASTIEN 9
1 False JOHN 4
2 True JENNY 5
上面使用 loc
是因为如果我用相同的布尔条件,这可能会不管用,甚至在最新的 pandas 版本中会报错:
In[274]:
df[df['apply_f'] == True]['value'] = df[df['apply_f'] == True]['name'].apply(lambda row: f(row))
df
-c:8: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_index,col_indexer] = value instead
Out[274]:
apply_f name value
0 False SEBASTIEN 9.000000
1 False JOHN 4.000000
2 True JENNY inf
对于你正在做的事情,使用 numpy 的 where
会更简洁、更易读:
In [279]:
df['value'] = np.where(df['apply_f']==True, len(df['name']), df['value'])
df
Out[279]:
apply_f name value
0 False SEBASTIEN 9
1 False JOHN 4
2 True JENNY 3
我明白你的例子是为了展示一个问题,但在某些情况下你也可以使用 where
。