将数据帧与不可用的列合并

时间:2017-08-31 23:36:48

标签: python pandas dataframe merge

我想合并两个Pandas DataFrame。如果item代码(例如A,B,C,D)相同, 他们的属性ab必须相同,但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

4 个答案:

答案 0 :(得分:5)

您可以使用df.mergedf.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

然而,合并后需要进行一些修补工作。因为我们只 合并itemresult得到两列ab - 来自bar的列 被称为a_yb_yupdate方法用于填充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