我有两个DataFrames C和D,如下所示:
C
A B
0 AB 1
1 CD 2
2 EF 3
D
A B
1 CD 4
2 GH 5
我必须合并两个数据帧,但是合并应覆盖正确df中的值。数据框中的其余行不应更改。
Output
A B
0 AB 1
1 CD 4
2 EF 3
3 GH 5
df的行顺序不得更改,即CD
应该保留在索引1中。我尝试使用外部合并来处理索引,但要复制列而不是覆盖。
>>> pd.merge(c,d, how='outer', on='A')
A B_x B_y
0 AB 1.0 NaN
1 CD 2.0 4.0
2 EF 3.0 NaN
3 GH NaN 5.0
基本上,B_y应该替换了B_x中的值(仅在出现值的地方)。 我正在使用Python3.7。
答案 0 :(得分:5)
您将必须替换行以覆盖适当的值。这与放置重复项不同,因为它将更改行的顺序。
合并DF接受“ pkey”作为参数,这是应在其上进行合并的主要列。
def update_df_row(row=None, col_name="", df=pd.DataFrame(), pkey=""):
try:
match_index = df.loc[df[pkey] == col_name].index[0]
row = df.loc[match_index]
except IndexError:
pass
except Exception as ex:
raise
finally:
return row
def combine_dfs(parent_df, child_df, pkey):
filtered_child_df = child_df[child_df[pkey].isin(parent_df[pkey])]
parent_df[parent_df[pkey].isin(child_df[pkey])] = parent_df[
parent_df[pkey].isin(child_df[pkey])].apply(
lambda row: update_df_row(row, row[pkey], filtered_child_df, pkey), axis=1)
parent_df = pd.concat([parent_df, child_df]).drop_duplicates([pkey])
return parent_df.reset_index(drop=True)
以上代码段的输出将是:
A B
0 AD 1
1 CD 4
2 EF 3
3 GH 5
答案 1 :(得分:1)
使用:
df = pd.merge(C,D, how='outer', on='A', suffixes=('_',''))
#filter columns names
new_cols = df.columns[df.columns.str.endswith('_')]
#remove last char from column names
orig_cols = new_cols.str[:-1]
#dictionary for rename
d = dict(zip(new_cols, orig_cols))
#filter columns and replace NaNs by new appended columns
df[orig_cols] = df[orig_cols].combine_first(df[new_cols].rename(columns=d))
#remove appended columns
df = df.drop(new_cols, axis=1)
print (df)
A B
0 AB 1.0
1 CD 4.0
2 EF 3.0
3 GH 5.0
答案 2 :(得分:0)
如果可以假设列A
的字母顺序是可以接受的:
C = pd.DataFrame({"A": ["AB", "CD", "EF"], "B": [1, 2, 3]})
D = pd.DataFrame({"A": ["CD", "GH"], "B": [4, 5]})
df_merge = pd.concat([C,D]).drop_duplicates('A', keep='last').sort_values(by=['A']).reset_index(drop=True)
df_merge
A B
0 AB 1
1 CD 4
2 EF 3
3 GH 5
修改
如果每个类别在原始数据框中的显示顺序最重要,则将执行此操作:
C = pd.DataFrame({"A": ["AB", "CD", "EF"], "B": [1, 2, 3]})
D = pd.DataFrame({"A": ["CD", "GH"], "B": [4, 5]})
df_merge = pd.concat([C,D]).drop_duplicates('A', keep='last')
df_merge['A'] = pd.Categorical(df_merge['A'], C.A.append(D.A).drop_duplicates())
df_merge.sort_values(by=['A'], inplace=True)
df_merge.reset_index(drop=True, inplace=True)
df_merge