web-dev-qa-db-fra.com

Python Pandas mettre à jour une valeur de trame de données à partir d'une autre trame de données

J'ai deux dataframes en python. Je souhaite mettre à jour les lignes de la première trame de données à l'aide des valeurs correspondantes d'un autre trame de données. La deuxième trame de données sert de remplacement.

Voici un exemple avec les mêmes données et le même code:

DataFrame 1:

enter image description here

DataFrame 2:

enter image description here

Je souhaite mettre à jour la base de données de mise à jour 1 en fonction du code et du nom correspondants. Dans cet exemple, Dataframe 1 doit être mis à jour comme suit:

enter image description here

Remarque: la ligne avec Code = 2 et Nom = Company2 est mise à jour avec la valeur 1000 (provenant de Dataframe 2)

import pandas as pd

data1 = {
         'Code': [1, 2, 3],
         'Name': ['Company1', 'Company2', 'Company3'],
         'Value': [200, 300, 400],

    }
df1 = pd.DataFrame(data1, columns= ['Code','Name','Value'])

data2 = {
         'Code': [2],
         'Name': ['Company2'],
         'Value': [1000],
    }

df2 = pd.DataFrame(data2, columns= ['Code','Name','Value'])

Des pointeurs ou des indices?

10
ProgSky

Vous pouvez utiliser concat + drop_duplicates

pd.concat([df1,df2]).drop_duplicates(['Code','Name'],keep='last').sort_values('Code')
Out[1280]: 
   Code      Name  Value
0     1  Company1    200
0     2  Company2   1000
2     3  Company3    400
11
WeNYoBen

Utilisation de DataFrame.update, qui s'aligne sur les indices ( https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.update.html ):

>>> df1.set_index('Code', inplace=True)
>>> df1.update(df2.set_index('Code'))
>>> df1.reset_index()  # to recover the initial structure

   Code      Name   Value
0     1  Company1   200.0
1     2  Company2  1000.0
2     3  Company3   400.0
16
Nic

Vous pouvez d'abord fusionner les données, puis utiliser numpy.where, ici comment utiliser numpy.where

updated = df1.merge(df2, how='left', on=['Code', 'Name'], suffixes=('', '_new'))
updated['Value'] = np.where(pd.notnull(updated['Value_new']), updated['Value_new'], updated['Value'])
updated.drop('Value_new', axis=1, inplace=True)

   Code      Name   Value
0     1  Company1   200.0
1     2  Company2  1000.0
2     3  Company3   400.0

Vous pouvez aligner les indices puis utiliser combine_first :

res = df2.set_index(['Code', 'Name'])\
         .combine_first(df1.set_index(['Code', 'Name']))\
         .reset_index()

print(res)

#    Code      Name   Value
# 0     1  Company1   200.0
# 1     2  Company2  1000.0
# 2     3  Company3   400.0
5
jpp

Vous pouvez utiliser pd.Series.where sur le résultat de la jonction gauche df1 et df2

merged = df1.merge(df2, on=['Code', 'Name'], how='left')
df1.Value = merged.Value_y.where(~merged.Value_y.isnull(), df1.Value)
>>> df1
    Code    Name    Value
0   1   Company1    200.0
1   2   Company2    1000.0
2   3   Company3    400.0

Vous pouvez changer la ligne en

df1.Value = merged.Value_y.where(~merged.Value_y.isnull(), df1.Value).astype(int)

afin de renvoyer la valeur à un entier.

3
Ami Tavory

En supposant que company et code sont des identifiants redondants, vous pouvez également faire

import pandas as pd
vdic = pd.Series(df2.Value.values, index=df2.Name).to_dict()

df1.loc[df1.Name.isin(vdic.keys()), 'Value'] = df1.loc[df1.Name.isin(vdic.keys()), 'Name'].map(vdic)

#   Code      Name  Value
#0     1  Company1    200
#1     2  Company2   1000
#2     3  Company3    400
2
ALollz