rob*_*ntw 6 python merge pandas
我有两个pandas DataFrame,如下所示:
df1 = pd.DataFrame({('Q1', 'SubQ1'):[1, 2, 3], ('Q1', 'SubQ2'):[1, 2, 3], ('Q2', 'SubQ1'):[1, 2, 3]})
df1['ID'] = ['a', 'b', 'c']
df2 = pd.DataFrame({'item_id': ['a', 'b', 'c'], 'url':['a.com', 'blah.com', 'company.com']})
Run Code Online (Sandbox Code Playgroud)
df1:
Q1 Q2 ID
SubQ1 SubQ2 SubQ1
0 1 1 1 a
1 2 2 2 b
2 3 3 3 c
Run Code Online (Sandbox Code Playgroud)
df2:
item_id url
0 a a.com
1 b blah.com
2 c company.com
Run Code Online (Sandbox Code Playgroud)
注意,df1有一些列具有层次索引(例如('Q1', 'SubQ1')),而一些列具有正常的索引(例如ID).
我想在ID和item_id字段上合并这两个数据帧.使用:
result = pd.merge(df1, df2, left_on='ID', right_on='item_id')
Run Code Online (Sandbox Code Playgroud)
得到:
(Q1, SubQ1) (Q1, SubQ2) (Q2, SubQ1) (ID, ) item_id url
0 1 1 1 a a a.com
1 2 2 2 b b blah.com
2 3 3 3 c c company.com
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,合并本身工作正常,但MultiIndex已丢失并已恢复为元组.我试图通过使用重新创建MultiIndex pd.MultiIndex.from_tuples,如:
result.columns = pd.MultiIndex.from_tuples(result)
Run Code Online (Sandbox Code Playgroud)
但这会导致item_id和url列的问题,只取其名称的前两个字符:
Q1 Q2 ID i u
SubQ1 SubQ2 SubQ1 t r
0 1 1 1 a a a.com
1 2 2 2 b b blah.com
2 3 3 3 c c company.com
Run Code Online (Sandbox Code Playgroud)
将列转换df2为单元素元组(即,('item_id',)而不是仅仅'item_id')没有区别.
如何合并这两个DataFrame并正确保持MultiIndex?或者,我如何获取合并的结果并返回具有适当MultiIndex的列而不会删除item_id和url列的名称?
如果你无法击败他们,请加入他们.(在合并之前,使两个DataFrames具有相同数量的索引级别):
import pandas as pd
df1 = pd.DataFrame({('Q1', 'SubQ1'):[1, 2, 3], ('Q1', 'SubQ2'):[1, 2, 3], ('Q2', 'SubQ1'):[1, 2, 3]})
df1['ID'] = ['a', 'b', 'c']
df2 = pd.DataFrame({'item_id': ['a', 'b', 'c'], 'url':['a.com', 'blah.com', 'company.com']})
df2.columns = pd.MultiIndex.from_product([df2.columns, ['']])
result = pd.merge(df1, df2, left_on='ID', right_on='item_id')
print(result)
Run Code Online (Sandbox Code Playgroud)
产量
Q1 Q2 ID item_id url
SubQ1 SubQ2 SubQ1
0 1 1 1 a a a.com
1 2 2 2 b b blah.com
2 3 3 3 c c company.com
Run Code Online (Sandbox Code Playgroud)
这也避免了UserWarning:
pandas/core/reshape/merge.py:551:UserWarning:在不同级别之间合并会产生意想不到的结果(左边2个级别,右边1个)
的列ID不是“非分层的”。它由 表示('ID', )。但是,pandas允许您仅引用第一级列,就像引用单个级别的列结构一样。这意味着这应该df1['ID']和 一样df1[('ID',)]有效df1.loc[:, ('ID',)]。但是,如果顶层碰巧'ID'在第二层中有更多与之关联的列,df1['ID']则会返回一个数据帧。我对这个解决方案感觉更舒服,它看起来很像@JohnGalt 在评论中的答案。
df1.assign(u=df1[('ID', '')].map(df2.set_index('item_id').url))
Q1 Q2 ID u
SubQ1 SubQ2 SubQ1
0 1 1 1 a a.com
1 2 2 2 b blah.com
2 3 3 3 c company.com
Run Code Online (Sandbox Code Playgroud)
将单级列式数据帧连接到多级列式数据帧很困难。我必须人为地添加另一个级别。
def rnm(d):
d = d.copy()
d.columns = [d.columns, [''] * len(d.columns)]
return d
df1.join(rnm(df2.set_index('item_id')), on=('ID',))
Q1 Q2 ID url
SubQ1 SubQ2 SubQ1
0 1 1 1 a a.com
1 2 2 2 b blah.com
2 3 3 3 c company.com
Run Code Online (Sandbox Code Playgroud)