[英]Removing a list of words from sentences using lambda
我有一个数据框,其中每一行对应一个字符串。 我想从这些字符串中删除某些单词-这是我使用lambda函数的方法:
def remove_words(s):
return s.apply(lambda x: [x for x in x if x not in ["name", "is", "m"]])
s = pd.DataFrame({"s":["Hi my name is Joe", "Hi my name is Hannah", "Hi my name is Brian"]})
remove_words(s.s)
这不会产生正确的结果,因为它会从所有单词中删除m
:
0 [H, i, , y, , n, a, e, , i, s, , J, o, e]
1 [H, i, , y, , n, a, e, , i, s, , H, a, n, ...
2 [H, i, , y, , n, a, e, , i, s, , B, r, i, ...
Name: s, dtype: object
我想要的理想结果是,
0 ["Hi my Joe"]
1 ["Hi my Hannah"]
2 ["Hi my Brian"]
Name: s, dtype: object
m
。 是否可以使用lambda做到这一点? 使用正则表达式时,请参见以下反例:
regex = '|'.join((' %s ' % word for word in ["in", "out", "between"]))
test = pd.DataFrame({"s": ["hello in out between inner in"]})
test.s.str.replace(regex, " ")
这不剔除掉所有out
,也不in
0 hello out inner in
Name: s, dtype: object
在这种情况下,使用.apply()
和lambda效率不高。 Pandas 字符串方法是专门为此构建的:
>>> s1 = pd.Series(["Hi my name is Joe", "Hi my name is Hannah", "Hi my name isn't Brian"])
>>> words = ['name', 'is']
>>> regex = r' *\b(?:{})\b'.format('|'.join(words))
>>> s.str.replace(regex, '').str.strip()
0 Hi my Joe
1 Hi my Hannah
2 Hi my isn't Brian
dtype: object
为什么不在这里使用.apply()
? 该方法是一种将可调用的(本机Python)映射到Pandas对象的每个元素的方法。 通常,它可能导致以不必要的速度进行更多的工作。 例如,在["".join([x for x in x if x not in ["name", "is"]])]
,则具有(1)列表理解,(2) .split()
, (3)对每个单独的“单元”进行联接操作。
对于您更新的案例:
>>> s2 = pd.Series(["hello in out between inner in"])
>>> words = ['in', 'out', 'between']
>>> regex = r' *\b(?:{})\b'.format('|'.join(words))
>>> s2.str.replace(regex, '').str.strip()
0 hello inner
dtype: object
str.strip()
是处理否则将在任一侧或两侧都用空格填充结果的情况。 即使使用方法链接,使用.str
方法也应该非常快。
使用正则表达式re.sub
import re
# construct the regex pattern
words = ['name', 'is']
pattern = re.compile(r'\b({})\b'.format('|'.join(words)))
# apply the function on the series
s.s.apply(lambda x: re.sub('\s+', ' ', re.sub(pattern, '', x)))
re.sub使用了两次,首先删除单词,然后替换多余的空格。
输出:
0 Hi my Joe
1 Hi my Hannah
2 Hi my Brian
\\b
是单词边界的正则表达式模式。 \\b(name|is|a)\\b
将与以下匹配,以删除线表示匹配
玫瑰的任何其他名称
如您所见,即使单个字母单词也正确匹配。 但是,还有一个问题尚未解决上述解决方案。
句子末尾的匹配项将留下一个空格,不会被re.sub(r'\\s+', ' ',...
清理掉re.sub(r'\\s+', ' ',...
因此,也有必要strip
空格。取决于你的数据
有了这个注释,最终的解决方案变为:
s.s.apply(lambda x: re.sub('\s+', ' ', re.sub(pattern, '', x)).strip())
这可能吗?
def remove_words(s):
return s.apply(lambda x: ["".join([x for x in x if x not in ["name", "is"]])])
您的问题是对字符串的列表理解(它将返回每个字符)。 首先对句子进行拆分,例如:
def remove_words(s, stop_words):
return s.apply(lambda x: ' '.join(w for w in x.split() if w not in stop_words))
如果要返回列表中的句子:
def remove_words_return_list(s, stop_words):
return s.apply(lambda x: [' '.join(w for w in x.split() if w not in stop_words)])
像这样称呼它:
remove_words(s, ['name', 'is', 'm'])
remove_words_return_list(s, ['name', 'is', 'm'])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.