2014-12-11 3 views
0

의 소스를 보여주는 저는 두 팬더의 dataframes이 : 내가하고 싶은 무엇병합이 팬더의 dataframes에서 열 각 행

import pandas as pd 
a = pd.DataFrame({'key' : [123, 234, 345, 456] }) 
b = pd.DataFrame({'key' : [  234, 345, 456, 567 ] }) 

두 개의 열이있는 하나의 dataframe로 병합입니다 : 하나 key를, 둘 다의 결합; 다른 하나는 source이고 두 개의 원래 데이터 프레임 중 어느 것이 해당 키를 포함하고 있는지에 대한 목록입니다.

위의 입력의 경우,이 원하는 :

+---+-----+--------+ 
| | key | source | 
+---+-----+--------+ 
| 0 | 123 | [a] | 
| 1 | 234 | [a, b] | 
| 2 | 345 | [a, b] | 
| 3 | 456 | [a, b] | 
| 4 | 567 | [b] | 
+---+-----+--------+ 

나는 작동하지만 (나는 상상이) 큰 테이블에 대한 무시 무시 느린 구현이 있습니다 더 좋은 방법이 무엇

union = set(a.key) 
union.update(b.key) 
union_series = pd.Series(data=sorted(list(union))) 

def append_ifin_src(urow, acc, (name, src)): 
    acc.extend([name] if len(src[src==urow]) != 0 else []) 
    return acc 

source_series = union_series.apply(lambda urow : reduce(lambda acc, tocheck : append_ifin_src(urow, acc, tocheck), [('a', a.key), ('b', b.key)], [])) 

pd.DataFrame({ 'key' : union_series, 'source' : source_series }) 

을 이것을하기 위해? 그들과 합류하고 새로운 열을 계산 한 후

aa = pd.DataFrame(['a']*len(a), index=a.key, columns=['a']) 
bb = pd.Series(['b']*len(b), index=b.key, name='b') 

과 :

aa.join(bb, how='outer')\ 
    .fillna('')\ 
    .apply(lambda x: x['a'] + x['b'], axis=1) 

것은 나는 또한 시도 할 것을이 작업을 수행하는

답변

0

A "pandy"방법은 먼저 인덱스에 열을 촉진하는 것입니다 초기 순서가 중요하지 않은 경우 순수한 파이썬 솔루션 :

def source(key): 
    if key in sa and key in sb: 
     return '[a, b]' 
    if key in sa: 
     return '[a]' 
    if key in sb: 
     return '[b]' 

sa = set(a.key) 
sb = set(b.key) 
pd.DataFrame([[key, source(key)] 
       for key in sa.union(sb)], 
       columns=['key', 'source'])  
Out[99]: 
key source 
0 456 [a, b] 
1 234 [a, b] 
2 567 [b] 
3 345 [a, b] 
4 123 [a] 

내 빠른 테스트에서 순수 파이썬 6 배 빨랐지 만 자신의 데이터로 확인해야합니다. 원래 dataframes에 열을 추가

1
import pandas as pd 

a = pd.DataFrame({'key' : [123, 234, 345, 456], 
        'source': ['a','a','a','a'] }) 
b = pd.DataFrame({'key' : [  234, 345, 456, 567 ], 
        'source': ['b','b','b','b']}) 

df = a.merge(b, how='outer', on='key').fillna("") 
df['source'] = df['source_x'] +df['source_y'] 
df[['key', 'source']] 

다른 생각 ... 열을 추가하면 병합 후 np.in1d를 사용할 수있는 옵션이없는 경우

0

입니다. 제거 할 빈 문자열이있는 경우를 제외하고는 대부분의 방법을 사용합니다.

df = pd.merge(a, b, how='outer') 
df['source'] = zip(np.where(np.in1d(df, a), 'a', ''), 
        np.where(np.in1d(df, b), 'b', '')) 

    key source 
0 123 (a,) 
1 234 (a, b) 
2 345 (a, b) 
3 456 (a, b) 
4 567 (, b) 
관련 문제