根据嵌套字典将列映射到第二列

时间:2020-07-15 13:12:23

标签: python pandas dictionary replace apply

使用向量化,我想根据第二列的值根据嵌套字典重新映射一列。在迭代逻辑中,我将遍历所有行;根据第二列中的值,我将从字典的第一级(也就是字典)中选择一个条目,据此映射值。

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"}}

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

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

所需的输出应如下所示:

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的几种组合一起使用都无济于事-有人可以指出我正确的方向吗?提前谢谢。

1 个答案:

答案 0 :(得分: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.apply 1

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))

时间结果:

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

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,因为它运行缓慢并且在引擎盖下循环。看看这个answer by cs95

相关问题