pandas Python通过迭代一列中的单词列表并返回列表中的任何单词都可以在另一列中找到的行来过滤 Dataframe

s3fp2yjn  于 2023-02-14  发布在  Python
关注(0)|答案(3)|浏览(101)

我正在处理一个包含多列的大型 Dataframe
数据的缩减版本如下所示(插入ROW列只是为了说明我遇到的问题,下文将进一步解释)

    • 第一季度**

| 世界其他地区|搜索词|文本到搜索|
| - ------|- ------|- ------|
| 1个|货币、交叉货币掉期、COPTIONS|文本1文本2,"文本3":文本4;货币|
| 第二章|异国债券|text1、text 2/text 3 "外来债券"|
| 三个|JPN,日本|日本、亚洲、日本、EMEA、美国|
| 四个|基差互换,基差互换,互换|欧洲、中东和非洲|
| 五个|欧洲、中东和非洲|美国、日本|
| 六个|利率互换|[空值]|
| 七|向前|远期债券交易|
| 八个|股票互换|股票、认股权证、可转换股票、掉期|
目标是过滤 Dataframe ,以便仅包含search_words列中的单词(存在于text_to_search列中)所在的行
过滤后, Dataframe 应如下所示:

    • 第一季度**

| 搜索词|文本到搜索|
| - ------|- ------|
| * * 货币**、交叉货币掉期、COPTIONS|文本1文本2,"文本3":文本4;货币|
| * * 奇异债券**|文本1、文本2/文本3 "奇异键"|
| 日本、日本|* * 日本**、亚洲、日本、EMEA、美国|
| * * 前进**|远期利率协议远期债券交易|
如图所示,search_words列可以包含一个或多个要搜索的单词,其中search_words包含短语(如第8行"equity swap"),为了找到匹配项,整个短语必须存在于text_to_search中。
text_to_search列没有可识别的格式,因此我无法将文本拆分为单词列表,以便与search_words列中的每个单词进行比较。
我开始使用下面的代码行:
df1 = df1 [df1.应用(λ x:www.example.com_x中的单词["要搜索的文本"],轴= 1)]x.search_words in x['text_to_search'], axis=1)]
这不会返回正确的结果。
然后,我尝试重新格式化search_words列,以便用竖线分隔单词,而不是使用,""分隔符。"|',这样数据看起来就像这样:通货|交叉货币互换|公约(等等.)
并使用以下代码尝试建立匹配:
df1 = df1.loc [df1 ['要搜索的文本'].字符串包含('|'. join(Map(字符串,df1 ['搜索字']))))]
这行代码也不起作用,它似乎将search_words列中的 * 所有 * 单词连接在一起,并将 * 所有 * search_words与text_to_search列中的每一行文本匹配。我得到了错误的匹配项。例如,第5行作为匹配项返回,因为在联接的search_words字符串中找到了"Japan",尽管在第5行的search_words列中没有找到"Japan"。
我想我需要的是这样的东西:
df1 = df1 [df1.应用(λ x:字符串中的单词(zip(x.搜索单词,x.要搜索的文本)),轴= 1)]
定义字符串中的单词(搜索单词,要搜索的文本):字计数= 0
对于search_words中的单词:单词计数=单词计数+要搜索的文本. lower(). find(单词. lower())
返回(字数〉0)
我肯定不会因为这个代码赢得任何奖励。它太糟糕了。而且它不起作用。请你能告诉我哪里出错了,以及如何解决这个问题吗?
谢谢你们!!!

cyvaqqii

cyvaqqii1#

我会这么做:

ser1 = df["search_words"].str.split("\s*,\s*")
ser2 = df["text_to_search"].str.lower()
​
m = [any(w.lower() in t for w in lst) for lst, t in zip(ser1, ser2)]
​
out = df.loc[m]

输出:

print(out)
                          search_words                           text_to_search
0  currency,CrossCurrencySwap,COPTIONS    text1 text2, "text3": TEXT4; Currency
1                          Exotic Bond     text1, text 2 / text 3 'Exotic Bond'
2                            JPN,Japan               Japan, Asia, JPN, EMEA, US
6                              forward  FRAforwardrateagreementforwardbondtrade
nbnkbykc

nbnkbykc2#

这是你想要的吗?

df = pd.DataFrame(
    {
        "search_words": ['word1, word2, word3', 'word4, word5, word6', 'word7, word8, word9'],
        "sentence" : ['this will not match', 'this will match word4', 'this will match word8 word9']
     }
)

df['matched'] = df.apply(lambda row: [search_word for search_word in row['search_words'].split(', ') if search_word in row['sentence']], axis=1)
df[df["matched"].str.len() > 0]

原始DF如下所示:

search_words                     sentence
0  word1, word2, word3          this will not match
1  word4, word5, word6        this will match word4
2  word7, word8, word9  this will match word8 word9

最终df如下所示:

search_words                     sentence         matched
1  word4, word5, word6        this will match word4         [word4]
2  word7, word8, word9  this will match word8 word9  [word8, word9]

编辑:lambda函数中的列表解析看起来很复杂,所以下面是函数格式中的等价物:

def my_function(row: pd.Series):
    search_words = row['search_words'].split(', ')
    result = []
    for search_word in search_words:
        if search_word in row['sentence']:
            result.append(search_word)
    return result
5m1hhzi4

5m1hhzi43#

下面是使用apply()执行此操作的两种方法:

    • 方法#1**:将re.search()与从search_wordsSeries.str.replace()创建的正则表达式模式一起使用,以正则表达式特殊字符|替换逗号分隔符(可能在左右两侧使用空格):
df2 = pd.DataFrame({
    'search_pat':df.search_words.str.replace('\s*,\s*', '|', regex=True),
    'text_to_search':df.text_to_search})
import re
mask = df2.apply(lambda row: 
    bool(re.search(row.search_pat, row.text_to_search, flags=re.IGNORECASE)), 
    axis=1).tolist()
res = df[mask]
    • 方法#2**:使用Series.str.contains()而不是re.search()创建遮罩:
mask = df2.apply(lambda row: 
    pd.Series(row.text_to_search).str.contains(row.search_pat, case=False).squeeze(),
    axis=1).tolist()
    • 输出**:
search_words                           text_to_search
0  currency,CrossCurrencySwap,COPTIONS    text1 text2, "text3": TEXT4; Currency
1                          Exotic Bond     text1, text 2 / text 3 'Exotic Bond'
2                            JPN,Japan               Japan, Asia, JPN, EMEA, US
6                              forward  FRAforwardrateagreementforwardbondtrade

相关问题