【问题标题】:Best way to perform multiple amount of Pandas lookups between two DataFrames在两个 DataFrame 之间执行多个 Pandas 查找的最佳方法
【发布时间】:2020-11-27 23:56:10
【问题描述】:

我正在尝试使用两个数据框进行简单的 Pandas 查找。我有一个主要的主数据框(左)和一个查找数据框(右)。我想在匹配的整数代码上加入它们并从item_df 返回项目title

我看到了一个带有键值对想法的轻微解决方案,但它看起来很麻烦。我的想法是使用col3name 作为关键列将merge 数据帧一起使用,并将value 保留在我想要的正确帧中,即title。因此我决定drop 我加入的key 列,所以我剩下的就是value。现在假设我想用我自己的手动命名约定多次执行此操作。为此,我使用rename 重命名我合并的值。现在我将重复此合并操作并将我的下一个连接重命名为second_title 之类的名称(参见下面的示例)。

是否有一种不那么繁琐的方法来执行这种重复操作,而无需不断删除合并的额外列并在每个合并步骤之间重命名新列?

示例代码如下:

import pandas as pd

master_dict: dict = {'col1': [3,4,8,10], 'col2': [5,6,9,10], 'col3': [50,55,59,60]}
master_df: pd.DataFrame = pd.DataFrame(master_dict)
item_dict: dict = {'name': [55,59,50,5,6,7], 'title': ['p1','p2','p3','p4','p5','p6']}
item_df: pd.DataFrame = pd.DataFrame(item_dict)
    
print(master_df.head())
   col1  col2  col3
0     3     5    50
1     4     6    55
2     8     9    59
3    10    10    60
print(item_df.head())
   name title
0    55    p1
1    59    p2
2    50    p3
3     5    p4
4     6    p5

# merge on col3 and name
combined_df = pd.merge(master_df, item_df, how = 'left', left_on = 'col3', right_on = 'name')
# rename title to "first_title"
combined_df.rename(columns = {'title':'first_title'}, inplace = True)
combined_df.drop(columns = ['name'], inplace = True) # remove 'name' column that was joined in from right frame
# repeat operation for "second_title"
combined_df = pd.merge(combined_df, item_df, how = 'left', left_on = 'col2', right_on = 'name')
combined_df.rename(columns = {'title': 'second_title'}, inplace = True)
combined_df.drop(columns = ['name'], inplace = True)
print(combined_df.head())
   col1  col2  col3 first_title second_title
0     3     5    50          p3           p4
1     4     6    55          p1           p5
2     8     9    59          p2          NaN
3    10    10    60         NaN          NaN

【问题讨论】:

    标签: python pandas dataframe join merge


    【解决方案1】:

    我们可以将您的键值映射与map 函数一起使用:

    以下代码获取 item_df name 列的值字典,该列分别位于 master_df col3 和 col2 中。

    col3 = dict(zip(*(value for _, value in
                      item_df[item_df.name.isin(master_df.col3)].items()))
               )
    
    col2 = dict(zip(*(value for _, value in
                     item_df[item_df.name.isin(master_df.col2)].items()))
               )
    
    
    col3
    {55: 'p1', 59: 'p2', 50: 'p3'}
    
    col2
    {5: 'p4', 6: 'p5'}
    

    接下来是使用assign 并创建列 first_title 和 second_title:

    master_df.assign(
        first_title=master_df.col3.map(col3),
        second_title=master_df.col2.map(col2)
        )
    
    
    
       col1 col2    col3    first_title second_title
    0   3   5       50      p3            p4
    1   4   6       55      p1            p5
    2   8   9       59      p2            NaN
    3   10  10      60      NaN           NaN
    

    更新

    我考虑过您对单个字典的评论,并且似乎可以通过使用系列来实现。这将大大减少我之前分享的臃肿代码。 在这种情况下,我们将item_df 转换为一个系列并将其映射到每个相关列:

    item_df = item_df.set_index("name").loc[:, "title"]
    
    item_df
    
    name
    55    p1
    59    p2
    50    p3
    5     p4
    6     p5
    7     p6
    Name: title, dtype: object
    

    现在使用 assign 函数创建您的特定列:

    master_df.assign(first_title=master_df.col3.map(item_df), 
                     second_title=master_df.col2.map(item_df)
                     )
    
       col1 col2    col3    first_title second_title
    0   3   5       50      p3            p4
    1   4   6       55      p1            p5
    2   8   9       59      p2            NaN
    3   10  10      60      NaN           NaN
    

    更加简单直接。

    【讨论】:

    • 所以为了确保我理解,这个想法是从 item_df 创建“查找表”,其中键存在于原始框架中。那么想法是显式使用这些字典来查找匹配值并将它们映射到最终数据帧中的新列?在映射之前制作所有这些查找字典是否有效?或者有没有办法制作一个适用于所有键查找的超级字典?
    • 您的值在不同的列中,因此您必须制作单独的字典。至于效率,您可以运行代码并与您当前的解决方案进行比较,看看它是否更好。一个用于所有键查找的超级字典。不太确定。你会怎么做?
    • @Coldchain9,用更简单的代码更新了我的答案。
    • 太棒了!刚刚尝试过,我更喜欢这种方法而不是多字典方法。非常感谢您的帮助! :)。只是为了确认我理解。您使用set_index() 使name 成为结果pd.Series 的新索引。那么在后面使用.map()时,它会将col3的值映射到item_df的正确索引值,并返回匹配的单个值(因为它是单列系列)? .map() 在这种情况下是这样工作的吗?
    • 是的。这就是地图的工作原理。不得不再次阅读文档:)
    猜你喜欢
    • 2011-05-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多