J'ai df1:
ID1 ID2 ColA ColB ColC 0 45.0 23.0 a 1.0 xyz 1 56.0 24.0 b 2.0 abc 2 23.0 45.0 NaN 0.0 e 3 56.0 29.0 NaN 0.0 NaN
df2:
u = df1.set_index(['ID1','ID2']) u = u.loc[u.index.dropna()] v = df2.set_index(['ID1','ID2']) v= v.loc[v.index.dropna()] v.update(u) v.reset_index()
I J'essaie de mettre à jour df2 uniquement sur les colonnes qui seront un choix = ['ColA', 'ColB'] où ID1 et ID2 correspondent dans les 2 dfs.
Résultat attendu:
ColA ColB ID1 ColC ID2 0 a 1.0 45.0 NaN 23.0 1 b 2.0 56.0 NaN 24.0 2 NaN 0 NaN fd 25.0 3 NaN 0 NaN NaN 26.0 4 NaN 0 23.0 e 45.0 5 NaN 0 45.0 r NaN 6 NaN 0 56.0 NaN 29.0
Jusqu'à présent, j'ai essayé:
ColA ColB ID1 ColC ID2 0 i 0 45.0 NaN 23.0 1 j 0 56.0 NaN 24.0 2 NaN 0 NaN fd 25.0 3 NaN 0 NaN NaN 26.0 4 NaN 0 23.0 e 45.0 5 NaN 0 45.0 r NaN 6 NaN 0 56.0 NaN 29.0
Ce qui me donne la bonne mise à jour (mais je perds les Ids qui sont NaN) aussi la mise à jour a lieu sur ColC dont je ne veux pas:
ColA ColB ID1 ColC ID2 0 a 1.0 45.0 xyz 23.0 1 b 2.0 56.0 abc 24.0 2 c 3.0 34.0 qwerty 28.0 3 d 4.0 34.0 wer 33.0 4 e NaN NaN NaN NaN
J'ai également essayé merge et combine_first. impossible de comprendre quelle est la meilleure approche pour le faire en fonction de la liste de choix.
3 Réponses :
voici un moyen
df1
ColA ColB ID1 ColC ID2 0 a 1.0 45.0 NaN 23.0 1 b 2.0 56.0 NaN 24.0 2 NaN 0.0 NaN fd 25.0 3 NaN 0.0 NaN NaN 26.0 4 NaN 0.0 23.0 e 45.0 5 NaN 0.0 45.0 r NaN 6 NaN 0.0 56.0 NaN 29.0
df2
ColA ColB ID1 ColC ID2 0 i 0 45.0 NaN 23.0 1 j 0 56.0 NaN 24.0 2 NaN 0 NaN fd 25.0 3 NaN 0 NaN NaN 26.0 4 NaN 0 23.0 e 45.0 5 NaN 0 45.0 r NaN 6 NaN 0 56.0 NaN 29.0 df3 = df1.merge(df2, on=['ID1','ID2'], left_index=True)[['ColA_x','ColB_x']] df2.loc[df3.index, 'ColA'] = df3['ColA_x'] df2.loc[df3.index, 'ColB'] = df3['ColB_x']
sortie
ColA ColB ID1 ColC ID2 0 a 1.0 45.0 xyz 23.0 1 b 2.0 56.0 abc 24.0 2 c 3.0 34.0 qwerty 28.0 3 d 4.0 34.0 wer 33.0 4 e NaN NaN NaN NaN
Merci, je vérifierai dans un moment et vous le ferai savoir. Bdw, le problème est que j'ai beaucoup de telles colonnes et pas seulement 2 comme dans l'exemple. :)
Il semble y avoir encore le problème dans 0.24 où NaN fusionne avec NaN quand ce sont des clés. Évitez cela en supprimant ces enregistrements avant la fusion. Je suppose que ['ID1', 'ID2'] est une clé unique pour df1 (pour les lignes où les deux ne sont pas nulles):
#df3 = df3.sort_index(axis=1) # If not sorted _x left of _y
df3.groupby([x[0] for x in df3.columns.str.split('_')], axis=1).apply(lambda x: x.ffill(1).iloc[:, -1])
ColA ColB ColC ID1 ID2
0 a 1.0 NaN 45.0 23.0
1 b 2.0 NaN 56.0 24.0
2 NaN 0.0 fd NaN 25.0
3 NaN 0.0 NaN NaN 26.0
4 NaN 0.0 e 23.0 45.0
5 NaN 0.0 r 45.0 NaN
6 NaN 0.0 NaN 56.0 29.0
j'ai donc essayé cette logique, en utilisant df3 = df2.merge (df1 [mises à jour + clés] .dropna (sous-ensemble = clés), on = keys, how = 'left', suffixes = ('', '_ y') ) et df3.groupby (df3.columns.str.strip ('_ y'). tolist (), axis = 1) .apply (lambda x: x.ffill (1) .iloc [: , -1]) puisque j'avais des traits de soulignement dans les noms de colonnes comme Col_A , Col_B , ne fonctionnait pas. :(
@ anky_91. Dans ce cas, vous pouvez ajouter des suffixes "plus rares" (moins susceptibles de correspondre à une chaîne aléatoire dans vos colonnes) à la fusion, essayez d'ajouter suffixes = ['_ lmerge', '_rmerge'] puis < code> .groupby (df3.columns.str.replace ('_ lmerge | _rmerge', ''), axis = 1) avec la même logique. Bien qu'il semble que vous ayez déjà trouvé votre réponse.
J'essaierais de le faire à nouveau et en fonction des performances, je pourrais sélectionner le meilleur. :) merci beaucoup d'avoir lu votre temps pour ma question. :) Oui, la réponse de jez fonctionne plutôt bien dans les vrais dfs.
Utilisez merge avec right join puis combine_first :
choice= ['ColA','ColB']
joined = ['ID1','ID2']
c = choice + joined
df3 = df1[c].merge(df2[c], on=joined, suffixes=('','_'), how='right')[c]
print (df3)
ColA ColB ID1 ID2
0 a 1.0 45.0 23.0
1 b 2.0 56.0 24.0
2 NaN NaN NaN 25.0
3 NaN NaN NaN 26.0
4 NaN NaN 23.0 45.0
5 NaN NaN 45.0 NaN
6 NaN NaN 56.0 29.0
df2[c] = df3.combine_first(df2[c])
print (df2)
ColA ColB ID1 ColC ID2
0 a 1.0 45.0 NaN 23.0
1 b 2.0 56.0 NaN 24.0
2 NaN 0.0 NaN fd 25.0
3 NaN 0.0 NaN NaN 26.0
4 NaN 0.0 23.0 e 45.0
5 NaN 0.0 45.0 r NaN
6 NaN 0.0 56.0 NaN 29.0
1 question, les noms d'identifiant dans mon dataframe d'origine sont différents, auraient besoin de left_on et right on, dans ce cas, devrais-je inclure toutes les clés dans c?
@ anky_91 - Je pense que pour un code plus simple, il est préférable de renommer les colonnes pour les mêmes dans les deux dataframes. Parce que left_on et right_on colonnes dupliquées - mêmes valeurs que des noms de colonnes différents.