我想合并两个Pandas DataFrame。如果item
代码(例如A,B,C,D)相同,
他们的属性a
,b
必须相同,但b
是一个numpy数组或列表是
unhashable。
富:
item a b
A 1 [2,0]
B 1 [3,0]
C 0 [4,0]
栏:
item a b
A 1 [2,0]
D 0 [6,1]
这就是我想要的
code a b Foo Bar
A 1 [2,0] 1 1
B 1 [3,0] 1 0
C 0 [4,0] 1 0
D 0 [6,1] 0 1
答案 0 :(得分:5)
您可以使用df.merge
和df.fillna
:
out = foo.assign(Foo=1).merge(bar.assign(Bar=1), 'outer').fillna(0)
print(out)
item a b Foo Bar
0 A 1 (2, 0) 1.0 1.0
1 B 1 (3, 0) 1.0 0.0
2 C 0 (4, 0) 1.0 0.0
3 D 0 (6, 1) 0.0 1.0
如果b
是列表类型,您可以先将其转换为元组,然后合并。
foo.b = foo.b.apply(tuple)
bar.b = bar.b.apply(tuple)
out = foo.assign(Foo=1).merge(bar.assign(Bar=1), 'outer').fillna(0)
out.b = out.b.apply(list)
print(out)
item a b Foo Bar
0 A 1 [2, 0] 1.0 1.0
1 B 1 [3, 0] 1.0 0.0
2 C 0 [4, 0] 1.0 0.0
3 D 0 [6, 1] 0.0 1.0
答案 1 :(得分:5)
这是一种在不将不可用数据转换为元组的情况下进行合并的方法。
由于item
代码与a
中的值具有一对一的对应关系,
b
列,仅在item
上合并就足够了。由于item
列中的值是可清除的,
合并没有问题:
import pandas as pd
foo = pd.DataFrame({'item': list('ABC'), 'a':[1,1,0], 'b':[[2,0], [3,0], [4,0]]})
bar = pd.DataFrame({'item': list('AD'), 'a':[1,0], 'b':[[2,0], [6,1]]})
result = pd.merge(foo.assign(Foo=1), bar.assign(Bar=1), on='item', how='outer',
suffixes=['', '_y'])
for col in ['a','b']:
result[col].update(result[col+'_y'])
for col in ['Foo', 'Bar']:
result[col] = result[col].fillna(0)
result = result.drop(['a_y', 'b_y'], axis=1)
print(result)
产量
a b item Foo Bar
0 1.0 [2, 0] A 1.0 1.0
1 1.0 [3, 0] B 1.0 0.0
2 0.0 [4, 0] C 1.0 0.0
3 0.0 [6, 1] D 0.0 1.0
然而,合并后需要进行一些修补工作。因为我们只
合并item
,result
得到两列a
和b
- 来自bar
的列
被称为a_y
和b_y
。 update
方法用于填充NaN值
来自a
的{{1}}的相应值,然后也是如此
a_y
。
使用b
获取foo.assign(Foo=1), bar.assign(Bar=1)
和Foo
列的聪明主意取自cᴏʟᴅsᴘᴇᴇᴅ's solution。
答案 2 :(得分:3)
或者你可以试试这个
foo.b = foo.b.apply(tuple)
bar.b = bar.b.apply(tuple)
df=pd.concat([foo,bar],axis=0).drop_duplicates()
df['foo']=df.isin(foo).a.astype(int)
df['bar']=df.isin(bar).a.astype(int)
df.b=df.b.apply(list)
df
Out[60]:
a b item foo bar
0 1 [2, 0] A 1 1
1 1 [3, 0] B 1 0
2 0 [4, 0] C 1 0
1 0 [6, 1] D 0 1
答案 3 :(得分:2)
cols = ['a', 'b', 'item']
pd.concat([Foo, Bar], keys=['Foo', 'Bar']) \
.assign(c=1).pipe(lambda d: d.assign(b=d.b.apply(tuple))) \
.set_index(cols, append=True) \
.c.unstack(0, fill_value=0).reset_index(cols) \
.pipe(lambda d: d.assign(b=d.b.apply(list)))
a b item Bar Foo
0 1 [2, 0] A 1 1
1 0 [6, 1] D 1 0
1 1 [3, 0] B 0 1
2 0 [4, 0] C 0 1