Pandas .replace() 具有多个多对一映射

问题描述 投票:0回答:1

我有一个 pandas 列,其中有一些字符串。我想将相似的字符串分组,并替换为它们的类别。在我的真实示例中,我有 6 个不同的字符串,我想用 3 个不同的字符串替换它们的类别。

我找到了这个答案,了解如何在replace()函数中使用将许多值映射到1,所以我尝试扩展一些答案来为多个组进行多对1映射,但是并非我的所有值都是正确的改变了,我不知道为什么。

举个例子:

df1 = pd.DataFrame({'col1':['foo', 'foo too', 'bar', 'BAR', 'bar ii']})
    col1
0   foo
1   foo too
2   bar
3   BAR
4   bar ii

从其中一个答案来看,您似乎可以使用“|”如果您使用正则表达式来分隔不同的关键选项,所以我这样做如下:

df1['col1'].replace({'foo|foo too' : 'Foo',
                     'bar|BAR|bar ii' : 'Bar'}, regex=True)

它转换了我的大部分字符串,但不是全部:

    col1
0   Foo
1   Foo too
2   Bar
3   Bar
4   Bar ii

从这个例子中,我猜想与空格有关?尽管在我的实际示例中,一些带空格的字符串确实被正确替换,所以我不确定。任何关于为什么这不起作用/我如何实现我所追求的目标的帮助将不胜感激

python pandas
1个回答
0
投票

您必须精心设计正则表达式,以确保另一个模式的子字符串不会出现在较长字符串之前。

这意味着

foo|foo too
将在
foo
之前匹配
foo to
。因此,应该使用
foo to|foo

df1['col1'].replace({'foo too|foo' : 'Foo',
                     'bar ii|BAR|bar' : 'Bar'}, regex=True)

输出:

0    Foo
1    Foo
2    Bar
3    Bar
4    Bar
Name: col1, dtype: object

确保较长的单词始终首先出现的通用方法是对字符串进行排序:

import re

motifs = {'Foo': ['foo', 'foo too'],
          'Bar': ['bar', 'BAR', 'bar ii'],
         }

dic = {'|'.join(map(re.escape, sorted(lst, key=lambda x: -len(x)))) : k
       for k, lst in motifs.items()}

df1['col1'].replace(dic, regex=True)

请注意,这仅适用于简单的字符串,不一定适用于更复杂的正则表达式,较短的正则表达式比较长的正则表达式可以匹配更通用的字符串。

© www.soinside.com 2019 - 2024. All rights reserved.