【问题标题】:map column according to nested dictionary accorging to second column根据第二列的嵌套字典映射列
【发布时间】:2020-11-05 00:02:04
【问题描述】:

使用矢量化,我想根据嵌套字典重新映射列,具体取决于第二列的值。在迭代逻辑中,我会遍历行;根据第二列中的值,我会从字典的第一级(又是字典)中选择一个条目,根据该条目映射值。

MWE

我有一个包含两列感兴趣的数据框:countryvariable

df= pd.DataFrame({"country": ["AA", "BB", "AA", "AA", "BB", "AA"],
                "variable": ["foo/tball", "palace", "bla", "car", "bla", "dog"]})

我还有一个嵌套字典dctvariable 中的值仅与country 结合使用是唯一的,因此我无法取消嵌套字典)。 dct 包含 df['variable'] 中的条目字符串及其子字符串:

dct = {"AA": {'foo': 'NEWFOO', # substring of 'foo/tball'
          'bla' : 'NEWBLA', 
          'cart': 'this value is not in the dataframe'}, # sic! -- not substring of any entry
       "BB": {'pal': 'NEWPAL', # substring of palace
          'bla': 'DIFFERENT_NEWBLA'},
       "CC": {"this": "'CC' dictionary can be ignored"}}

我现在想按照以下规则根据dct[df['country']] 映射df['variable'] 的条目:

  • 如果字符串匹配或者字典键是df['variable']中条目的子字符串(例如dct['AA']中的'foo':根据字典替换条目
  • 否则(即如果单元格条目不在字典中(例如'dog'),则替换为某个预定义值(此处为_some_flag_value_
  • 忽略字典中与'country' 列(例如dct["CC"])或'variable' 列(例如dct['AA'] 中的'cart')不匹配的条目。

所需的输出应如下所示:

out = pd.DataFrame({"country": ["AA", "BB", "AA", "AA", "BB", "AA"],
                    "variable": ["NEWFOO", "NEWPAL", "NEWBLA", "_some_flag_value_", 
                                 "DIFFERENT_NEWBLA", "_some_flag_value_"]})

我尝试使用df.mapapply()lambda 的几种组合都无济于事 - 有人能指出我正确的方向吗?提前非常感谢。

【问题讨论】:

    标签: python pandas dictionary replace apply


    【解决方案1】:

    您可以使用pd.Series.str.cat 使用自定义分隔符连接两列,然后使用pd.Series.map

    def f(x):
        c, v = x.split('-')
        d = dct.get(c)
        for k,val in d.items():
            if k in v:
               return val
        else:
            return '_some_flag_value_'
    
    df.assign(variable = df['country'].str.cat(df['variable'],sep='-').map(f))
    
      country           variable
    0      AA             NEWFOO
    1      BB             NEWPAL
    2      AA             NEWBLA
    3      AA  _some_flag_value_
    4      BB   DIFFERENT_NEWBLA
    5      AA  _some_flag_value_
    

    或使用df.apply1

    def f(x):
        c, v = x
        d = dct.get(c)
        for k,val in d.items():
            if k in v:
               return val
        else:
            return '_some_flag_value_'
    
    df.assign(variable = df.apply(f,axis=1))
    

    Timeit 结果:

    使用问题中给出的数据框进行基准测试。

    In [84]: %timeit df.assign(variable = df['country'].str.cat(df['variable'],sep='-').map(f))
        ...:
    694 µs ± 22.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    In [82]: %timeit df.assign(variable = df.apply(f,axis=1))
        ...:
    915 µs ± 40.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    

    1 df.apply 过轴通常被避免,因为它很慢并且引擎盖下有for循环。看看这个answer by cs95

    【讨论】:

    • 谢谢,这看起来很有希望;如果使用应用,输入xf 是什么对象之王?这是拆包的,但我不明白我们在那里传递了什么。 dfpd.Series?!
    • pd.Series.map 将函数 f 应用于系列的每个值。因此,df['country'].str.cat(df['variable'],sep='-').map(f) 对每个字符串值应用函数。 @Ivo
    • df.apply over axis 1 将函数 f 应用于每个行值,即函数 f 应用于 ('AA', 'foo/tball') 并且类似地应用于每一行。
    猜你喜欢
    • 1970-01-01
    • 2015-07-24
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2020-03-23
    • 1970-01-01
    • 2021-12-08
    • 2018-03-05
    相关资源
    最近更新 更多