簡體   English   中英

使用Lambda從句子中刪除單詞列表

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM