【问题标题】:replace value of a dataframe based on value from another dataframe根据来自另一个数据帧的值替换数据帧的值
【发布时间】:2020-04-21 02:36:47
【问题描述】:

如何根据另一个查找数据框在一个数据框之间进行合并。

这是我要替换值的数据框 A:

  InfoType  IncidentType    DangerType
0   NaN          A             NaN
1   NaN          C             NaN
2   NaN          B            C
3   NaN          B            NaN

这是查找表:

    ID  ParamCode   ParamValue  ParmDesc1   ParamDesc2  SortOrder   ParamStatus
0   1   IncidentType    A       ABC            DEF          1            1
1   2   IncidentType    B       GHI            JKL          2            1
2   3   IncidentType    C       MNO            PQR          7            1
2   3   DangerType      C       STU            VWX          6            1

预期输入:

  InfoType  IncidentType    DangerType
0   NaN          ABC           NaN
1   NaN          MNO           NaN
2   NaN          GHI           STU
3   NaN          GHI           NaN

请注意,ParamCode 是列名,我需要将 ParamDesc1 替换为数据框 A 中的相应列。数据框 A 中的每一列都可能有 NaN,我不打算删除它们。忽略它们。

这就是我所做的:

ntf_cols = ['InfoType','IncidentType','DangerType']
for c in ntf_cols:
    if (c in ntf.columns) & (c in param['ParamCode'].values):
        paramValue = param['ParamValue'].unique()
        for idx, pv in enumerate(paramValue):
            ntf['NewIncidentType'] = pd.np.where(ntf.IncidentType.str.contains(pv), param['ParmDesc1'].values, "whatever")

错误:

ValueError: 操作数不能与形状一起广播 (25,) (13,) ()

【问题讨论】:

  • 这是一个常见的副本。参见,例如,stackoverflow.com/questions/36413993/…
  • @Eric Truett,在这被投票为重复关闭之前,是否有更好的匹配问题? OP 似乎需要引用另一个 df 中两列的值而不是一列。 @dee 如果您提供了迄今为止为解决此问题所做的尝试,那么@dee 会改善您的问题。
  • 这是怎么复制的? @EricTruett我的问题需要在列与数据框中的值之间进行比较。这是完全不同的。它不在两列之间。
  • @Phillyclause89 我尝试了多次,但我一直在删除它们。由于比较是在另一个数据框中的列名称和值之间进行的,因此我无法转过头来。我不确定在这种情况下如何映射它们。
  • @Phillyclause89 更新了我一直在尝试做的代码。

标签: python pandas


【解决方案1】:

使用查找表制作dict,然后替换原始数据框的列值。假设原始数据框为df1,查找表为df2

...
dict_map = dict(zip(df2.ParamCode + "-" + df2.ParamValue, df2.ParmDesc1))

df1['IncidentType'] = ("IncidentType" +'-'+ df1.IncidentType).replace(dict_map)
df1['DangerType'] = ("DangerType" +'-'+ df1.DangerType).replace(dict_map)
...

【讨论】:

  • 这似乎有效。我有一个问题如何用变量替换df1.IncidentType。而不是硬编码?因为我需要将此应用于每一列。我可以给你看我的代码。
  • 使用 for 循环遍历要应用的列,例如 for col in df1.columns: df1[col] = (col+"-"+df1[col]).replace(dict_map)
  • 是否有一些dtype是float64的列,你应该把它改成str。 for col in df1.columns: df1[col] = (col+"-"+df1[col].astype(str)).replace(dict_map)
【解决方案2】:

编辑:Lambda 的 answer 给了我一个想法,让我知道如何对许多要应用此逻辑模式的列执行此操作:

import pandas as pd

df1 = pd.DataFrame(dict(
    InfoType = [None, None, None, None],
    IncidentType = 'A C B B'.split(),
    DangerType = [None, None, 'C', None],
))

df2 = pd.DataFrame(dict(
    ParamCode = 'IncidentType IncidentType IncidentType DangerType'.split(),
    ParamValue  = 'A B C C'.split(),
    ParmDesc1 = 'ABC GHI MNO STU'.split(),
))


for col in df1.columns[1:]:
    dict_map = dict(
        df2[df2.ParamCode == col][['ParamValue','ParmDesc1']].to_records(index=False)
    )
    df1[col] = df1[col].replace(dict_map)

print(df1)

这假定df1 中第一列之后的每一列都需要更新,并且要更新的列名作为值存在于df2'ParamCode' 列中。

Python tutor link to code


这个问题可以使用一些自定义函数和pandas.Series.apply()来解决:

import pandas as pd

def find_incident_type(x):
    if pd.isna(x):
        return x
    return df2[
        (df2['ParamCode'] == 'IncidentType') & (df2['ParamValue']==x)
    ]["ParmDesc1"].values[0]


def find_danger_type(x):
    if pd.isna(x):
        return x
    return df2[
        (df2['ParamCode'] == 'DangerType') & (df2['ParamValue']==x)
    ]["ParmDesc1"].values[0]


df1 = pd.DataFrame(dict(
    InfoType = [None, None, None, None],
    IncidentType = 'A C B B'.split(),
    DangerType = [None, None, 'C', None],
))

df2 = pd.DataFrame(dict(
    ParamCode = 'IncidentType IncidentType IncidentType DangerType'.split(),
    ParamValue  = 'A B C C'.split(),
    ParmDesc1 = 'ABC GHI MNO STU'.split(),
))

df1['IncidentType'] = df1['IncidentType'].apply(find_incident_type)
df1['DangerType'] = df1['DangerType'].apply(find_danger_type)

print(df1)

step through the code in python tutor

很有可能有更有效的方法来做到这一点。希望有知道的人分享一下。

此外,外部作用域对df2 的引用被硬编码到自定义函数中,因此仅适用于外部作用域中的变量名。如果您不希望这些函数依赖于该引用,则需要为 pandas.Series.applyargs 参数使用参数。

【讨论】:

  • 非常感谢。我需要尽快看看这个!但由于性能问题,我尽量避免使用apply。如上所述,我仍在尝试编写自己的内容并与您的进行比较,我无法对列进行硬编码,因为我还有其他列要转换。
  • @dee 我的想法是为df1 中的每一列创建一个自定义函数,您需要根据df2(您的查找表)中的特定值替换值,然后调用pandas.Series.apply 方法,每个需要替换值的列都有相应的函数。
  • 嘿,我也尝试了您的第二个解决方案,它按预期工作!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 2020-01-24
相关资源
最近更新 更多