我正在尝试使用两个数据框来使用Pandas进行简单查找。我有一个主要的主数据框(左)和一个查找数据框(右)。我想在匹配的整数代码上加入它们,并title
从中返回该项目item_df
。
我看到一个关于键值对的想法的解决方案,但似乎很麻烦。我的想法是merge
使用col3
和name
作为键列将数据帧放在一起,并保持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
我们可以将你的key:value映射与map函数一起使用:
下面的代码获取分别name
在master_df
col3和col2中的item_df列的值的字典。
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'}
接下来是使用分配并创建列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
更新
我考虑过你对一本字典的评论,并且似乎可以通过使用“系列”来实现。这将大大减少我之前共享的code肿代码。在这种情况下,我们将转换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()
在这种情况下,如何运作?是的。地图就是这样工作的。不得不再次阅读文档:)