Mam dwie ramki danych:

import pandas as pd
df1 = pd.DataFrame({
    "id": [1,2,3,4,5,6], "c1": [1,2,3,4,5,6], "c2": [1,2,3,4,5,6], "c3": [1,2,3,4,5,6]
})

I

df2 = pd.DataFrame({
    "id": [1,2,3,4,5,6], "column": ["c1", "c2", "c3", "c1", "c2", "c3"], "new-value": [10,20,30,40,50,60]
})

Chciałbym zaktualizować df1 na podstawie informacji z df2, aby wynik był następujący:

df3 = pd.DataFrame({
    "id": [1,2,3,4,5,6], "c1": [10,2,3,40,5,6], "c2": [1,20,3,4,50,6], "c3": [1,2,30,4,5,60]
})
  1. Czy można to zrobić za pomocą pand?
  2. Czy opcje aktualizacji/scalania są w tym przypadku wykonalne?
2
José Edson 5 styczeń 2022, 14:30

3 odpowiedzi

Najlepsza odpowiedź

Możemy zmienić kształt df2 za pomocą pivot , a następnie użyj go do zastąpienia wartości w df1

df1.replace(df2.pivot(*df2.columns)).fillna(df1)

   id    c1    c2    c3
0   1  10.0   1.0   1.0
1   2   2.0  20.0   2.0
2   3   3.0   3.0  30.0
3   4  40.0   4.0   4.0
4   5   5.0  50.0   5.0
5   6   6.0   6.0  60.0
1
Shubham Sharma 5 styczeń 2022, 14:54
Myślę, że możesz uniknąć df1.replace do df2.pivot(*df2.columns).fillna(df1.set_index('id')).
 – 
Mayank Porwal
5 styczeń 2022, 15:03
To może działać, ale w takim przypadku konieczne jest, aby df2 zawierał wszystkie ids, które są obecne w df1
 – 
Shubham Sharma
5 styczeń 2022, 15:06
1
To też jest dobry punkt.
 – 
Mayank Porwal
5 styczeń 2022, 15:08

Jest to możliwe z pandami o następującym kodzie:

ids = df2["id"].to_list()
columns = df2.columns.to_list()
new_values = df2["new-value"].to_list()

for id in ids:
    for col in columns:
        for value in new_values:
            df3.loc[id, col] = value

Prawdopodobnie nie jest optymalny, jeśli twoje zbiory danych są bardzo duże.

0
kelyen 5 styczeń 2022, 14:43

Jest to wykonalne, ale nie jestem pewien, czy to najlepszy sposób na wykonanie takiej operacji.

  1. Trudna droga:
df1 = df1.set_index('id')
for idx, row in df2.iterrows():
    df1.loc[row['id'], row['column']] = row['new-value']
df1.reset_index()
  1. Bardziej pytoniczny sposób:
df2 = df2.pivot(index='id', columns='column', values='new-value').reset_index()
df1.update(df2)
0
Daniel Wlazło 5 styczeń 2022, 14:59