将两个pandas数据帧的值相互组合并完成

时间:2018-02-17 03:00:34

标签: python pandas

我有2个数据帧,缺少值,我想合并并完成彼此的数据,

简单的可视化:

df1 :
A,B,C
A1,B1,C1
A2,B2,
A3,B3,C3 

df2 :
A,B,C
A1,,C1
A4,B4,C4
A2,B2,C2

The result wanted:
A,B,C
A1,B1,C1
A2,B2,B2
A3,B3,C3
A4,B4,C4

基本上合并数据框而不复制“A”列,并通过比较数据框之间相同列“A”的值来完成行中是否存在缺失值。

我在Stackexchange上的Pandas文档+解决方案上尝试了很多东西,但每次都失败了

这些都是我尝试的不同之处:

pd.merge_ordered(df1, df2, fill_method='ffill', left_by='A')
df1.combine_first(df2)
df1.update(df2)
pd.concat([df1, df2])
pd.merge(df1, df2, on=['A','B','C'], how='right')
pd.merge(df1, df2, on=['A','B','C'], how='outer')
pd.merge(df1, df2, on=['A','B','C'], how='left')
df1.join(df2, how='outer')
df1.join(df2, how='left')
df1.set_index('A').join(df2.set_index('A'))

(你可以看到我最后非常绝望)

知道怎么做吗?

4 个答案:

答案 0 :(得分:4)

您是否以combine_first作为索引来尝试A

df1.set_index('A').combine_first(df2.set_index('A')).reset_index()

    A   B   C
0  A1  B1  C1
1  A2  B2  C2
2  A3  B3  C3
3  A4  B4  C4

答案 1 :(得分:4)

或者您可以使用first

pd.concat([df1,df2]).replace('',np.nan).groupby('A',as_index=False).first()
Out[53]: 
    A   B   C
0  A1  B1  C1
1  A2  B2  C2
2  A3  B3  C3
3  A4  B4  C4

答案 2 :(得分:4)

<强>设置
既然你把它们写成了csvs,我就会假设它们是csvs。

df1 = pd.read_csv('df1.csv', sep=',', index_col=0)
df2 = pd.read_csv('df2.csv', sep=',', index_col=0)

<强>解决方案
使用fillna

后使用align
pd.DataFrame.fillna(*df1.align(df2))

     B   C
A         
A1  B1  C1
A2  B2  C2
A3  B3  C3
A4  B4  C4

如果你坚持,你可以使用reset_index,但我认为让它保持原样更漂亮。

答案 3 :(得分:1)

您可以使用pandas categorical data类型设置有序的类别列表,排序这些有序类别,并删除具有Null值的行以获得所需结果:

from pandas.api.types import CategoricalDtype
# Create first dataframe from OP values
df1 = pd.DataFrame({'A': ['A1', 'A2', 'A3'],
                    'B': ['B1', 'B2', 'B3'],
                    'C': ['C1', '', 'C3']})

# create second dataframe from original values
df2 = pd.DataFrame({'A': ['A1', 'A4', 'A2'],
                    'B': ['', 'B4', 'B2'],
                    'C': ['C1', 'C4', 'C2']})

# concatenate the two together for a long dataframe
final = pd.concat([df1, df2])

# specify the letters in your dataset  
letters = ['A', 'B', 'C']
# create a placeholder dictionary to store the categorical datatypes
cat_dict = {}

# iterate over the letters
for let in letters:
    # create the ordered categories - set hte range for the max # of values
    cats = ['{}{}'.format(let, num) for num in list(range(1000))]
    # create ordered categorical datatype
    cat_type = CategoricalDtype(cats, ordered=True)
    # insert into placeholder
    cat_dict[let] = cat_type

# properly format your columns as the ordered categories
final['A'] = final['A'].astype(cat_dict['A'])
final['B'] = final['B'].astype(cat_dict['B'])
final['C'] = final['C'].astype(cat_dict['C'])
# finally sort on the three columns and drop rows with NA values
final.sort_values(['A', 'B', 'C']).dropna(how='any')

# which outputs desired results
    A   B   C
0  A1  B1  C1
2  A2  B2  C2
2  A3  B3  C3
1  A4  B4  C4

虽然这有点长,但这样做的一个好处是你的数据在输入时可以是任何顺序。这会将继承等级插入每列中的值,因此A1&lt; A2&lt; A3等等等等。这也使您可以对列进行排序。