【发布时间】:2023-04-03 14:45:02
【问题描述】:
我还是 Pandas 的新手,似乎无法将这几个基本步骤结合起来。
目标:
我想根据条件对多个列进行高效查找和替换。
我有数据框 df,如果列 lower_limit 和 upper_limit 则需要从另一个数据框 lookup 进行索引查找都是NaN。
我无法让合并/加入工作,因为索引名称之间存在差异(想想 C_something,F_something 来自 DataFrame lookup ),为简单起见省略了。
输入:
数据帧:
import pandas as pd; import numpy as np
df = pd.DataFrame([['A', 3, 5],['B', 2, np.NaN],['C', np.NaN, np.NaN],['D', np.NaN, np.NaN]])
df.columns = ['Name','lower_limit','upper_limit']
df = df.set_index('Name')
lookup = pd.DataFrame([['C_Male', 4, 6],['C_Female', 5, 7],['E_Male', 2, 3],['E_Female', 3, 4]])
lookup.columns = ['Name', 'lower', 'upper']
lookup = lookup.set_index('Name')
# index: Name + index_modifier is the lookup index of interest for example
index_modifier = '_Male'
可视化的数据帧:
# df # lookup
lower_limit upper_limit lower upper
Name Name
A 3.0 5.0 C_Male 4 6
B 2.0 NaN C_Female 5 7
C NaN NaN E_Male 2 3
D NaN NaN E_Female 3 4
预期输出:
# df
lower_limit upper_limit
Name
A 3.0 5.0
B 2.0 NaN #<-- Does not meet conditional
C 4.0 6.0 #<-- Looked-up with index_modifier and changed
D NaN NaN #<-- Looked-up with index_modifier and left unchanged
破解密码:
我曾尝试使用df.loc() docs 和this answer 来屏蔽和设置值,但似乎无法根据该行的索引获取唯一值。
使用 df.loc 屏蔽和设置
# error: need get index of each row only
df.loc[(df.lower_limit.isnull()) & (df.upper_limit.isnull()), ['lower_limit','upper_limit'] ] = lookup.loc[df.index + index_modifier]
用 df.loc 掩码然后设置
ix_of_interest = df.loc[(df.lower_limit.isnull()) & (df.upper_limit.isnull())].index
# only keep index values that are in DataFrame 'lookup'
ix_of_interest = [ix for ix in ix_of_interest if ((ix + index_modifier) in lookup.index)]
lookup_ix = [ix + index_modifier for ix in lookup_ix]
# error: Not changing values. I think there is a mismatch of bracket depths for one
df.loc[ix_of_interest, ['lower_limit','upper_limit'] ] = lookup.loc[lookup_ix]
我也尝试使用 df.apply() 来设置值。见this question。
def do_lookup(row):
# error:'numpy.float64' object has no attribute 'is_null'
if row.lower_limit.isnull() and row.upper_limit.isnull():
if (row.name + index_modifier) in lookup.index:
return lookup.loc[row.name + index_modifier]
df['lower_limit', 'upper_limit'] = df.apply(do_lookup, axis=1)
或lambda
df['lower_limit', 'upper_limit'] = df.apply(lambda x: lookup.loc[x.name + index_modifier].to_list()
# isnull() or isnan() would be better
if ((x.lower_limit == np.NaN) and (x.upper_limit == np.NaN))
# else may not be needed here
else [np.NaN, np.NaN],
axis=1)
这似乎应该是一系列简单的步骤,但我无法让它们正常工作。任何见解都将不胜感激 - 我的橡皮鸭很累而且很困惑。
【问题讨论】:
-
`_something`总是相同的str吗?
-
是的。我添加了 index_modifier 作为要添加到字符串中的常量。
-
谢谢!。请检查我的解决方案!
-
附带问题:为什么 df.apply(do_lookup,axis=1) 代码会抛出“'numpy.float64' object has no attribute 'isnull'”错误?