【问题标题】:Conditionally Set Multiple Column Values with Dynamic Values Using Loc or Apply使用 Loc 或 Apply 有条件地使用动态值设置多个列值
【发布时间】:2023-04-03 14:45:02
【问题描述】:

我还是 Pandas 的新手,似乎无法将这几个基本步骤结合起来。

目标:

我想根据条件对多个列进行高效查找和替换。

我有数据框 df,如果列 lower_limitupper_limit 则需要从另一个数据框 lookup 进行索引查找都是NaN

我无法让合并/加入工作,因为索引名称之间存在差异(想想 C_somethingF_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() docsthis 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'”错误?

标签: python pandas


【解决方案1】:

您可以将Series.fillnaDataFrame.add_suffix 一起使用:

index_modifier = '_Male'

init_index=df.index
df=df.T.add_suffix(index_modifier).T
df['lower_limit'].fillna(lookup['lower'],inplace=True)
df['upper_limit'].fillna(lookup['upper'],inplace=True)
df.index=init_index
print(df)


   lower_limit  upper_limit
A          3.0          5.0
B          2.0          NaN
C          4.0          6.0
D          NaN          NaN

【讨论】:

  • 乍一看,这似乎与合并有共同的问题。即它要求索引相同(为简单起见,我将其取出)。如果查找有一个修改后的名称“C_someModifier”,我该如何应用fillna?
  • 根据索引的修改,一种或另一种形式将被执行。最好使用修改后索引的示例更新数据框
  • 如果 _something 总是相同的,也许最简单的方法是使用 df = df.T.add_prefix ('somethin _')。 T 然后合并或填充...
  • 我可以为适当的行做一个索引修饰符,然后在查找后取消修改。虽然有多层复杂性,但如果可能的话,我宁愿直接使用 apply/loc mapping/equivalent。
猜你喜欢
  • 2019-09-04
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
  • 2010-09-08
  • 2019-04-12
  • 1970-01-01
  • 2020-12-04
  • 1970-01-01
相关资源
最近更新 更多