【问题标题】:Search for a matching string between two dataframes, and assign the matching column's name to the other dataframe with a function (Pandas)搜索两个数据框之间的匹配字符串,并使用函数(熊猫)将匹配列的名称分配给另一个数据框
【发布时间】:2019-06-04 15:43:25
【问题描述】:

“unique_receivers”是一个 Pandas 数据框,其中包含用于唯一交易接收者的列、金额和用于我想用函数填充的类别的空列。

unique_receivers

    Receiver    Amount  Category
144 SALE        -18.93  
141 TACO BELL   -19.20  
78  MCDONALDS   -19.65  
104 EXPRESS     -20.00  
154 SHOP        -24.00  

我想根据其“接收者”列与另一个数据帧“category_searchterms”中的搜索词匹配来填充上述数据框的“类别”列。

“category_searchterms”以类别作为列名,每个类别的列都有各自的搜索词。

这是该数据框的示例:

categories

    Groceries   Electricity Fastfood
0   SHOP        ELCOMPANY   MCDONALDS
1   MARKET      POWER       SUBWAY
2   SALE                    PIZZA       

我想遍历“unique_receivers”的“Receiver”列的每一行,在“categories”数据框中查找匹配项,获取匹配列的名称并将其分配给第一个数据框的“Category” "列。

我正在尝试使用此功能:

def add_category(searchterm):
    unique_receivers["Category"] = (category_searchterms == searchterm).any().idxmax()

然后调用它:

unique_receivers.apply(add_category(unique_receivers["Receiver"]), axis=1)

问题:

TypeError: ("'NoneType' object is not callable", 'occurred at index 144')

索引 144 是“unique_receivers”中的第一行。如果我现在调用数据框,则每一行都填充了第一个类别:

unique_receivers

    Receiver    Amount  Category
144 SALE        -18.93  Groceries   
141 TACO BELL   -19.20  Groceries   
78  MCDONALDS   -19.65  Groceries   
104 EXPRESS     -20.00  Groceries   
154 SHOP        -24.00  Groceries   

如何让真正匹配的类别出现在每一行的“类别”列中?谢谢。

【问题讨论】:

  • 如果接收者的名字中有空格,即两个或多个单独的单词怎么办?这些方法只能找到 1-word 接收者?

标签: python pandas function dataframe string-matching


【解决方案1】:

这是一种使用apply 和自定义lambda 函数的方法:

unique_receivers['Category'] = unique_receivers.Receiver.apply(lambda x:
                               ''.join([i for i in categories.columns 
                               if categories.loc[:,i].str.contains(x).any()]) 
                               or None)

 Receiver  Amount   Category
144       SALE  -18.93  Groceries
141   TACOBELL  -19.20       None
78   MCDONALDS  -19.65   Fastfood
104    EXPRESS  -20.00       None
154       SHOP  -24.00  Groceries

或者使用pd.melt 和右mergedf1

categories.melt(var_name='Category').merge(unique_receivers, 
                                           left_on='value', right_on='Receiver',
                                           how='right')\
                                           [['Receiver','Amount','Category']]

    Receiver  Amount   Category
0       SHOP  -24.00  Groceries
1       SALE  -18.93  Groceries
2  MCDONALDS  -19.65   Fastfood
3   TACOBELL  -19.20       None
4    EXPRESS  -20.00       None

【讨论】:

  • 你知道为什么这两种方法都只能找到只包含一个单词的接收者的匹配项,而如果接收者的名字是2个以上的单词则不能?例如,如果有 TACO BELL 作为接收者,如果类别中的搜索词是 TACO,这些方法将找不到它的类别。
【解决方案2】:

这行得通吗?

import pandas as pd

unique_receivers['Category'] = unique_receivers['Receivers'].apply(lambda x: pd.np.resize(categories.columns.values[pd.np.where(categories.isin([x]))[1]],1)[0])

np.resize 是为了确保在没有找到值的情况下不会得到IndexError

【讨论】:

  • 谢谢,它确实为 100 多个接收器中的 2 个添加了正确的类别,但其余的没有,我会尝试理解为什么这 2 个(它们似乎与其他接收器没有任何不同) .
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 2018-10-01
  • 1970-01-01
  • 2021-05-15
  • 2019-06-21
  • 1970-01-01
  • 2017-10-01
相关资源
最近更新 更多