Панды обновляют один кадр данных суммой существующих и других значений

В моем фактическом фрейме данных более миллиона строк, но образец мультииндексного фрейма данных выглядит так (с 1,0 в IN_VALUE для простоты):

# INDEX  ID  | MATCH  IN_VALUE  OUT_VALUE
# 0      7   | 1      1.0      -0.33
#        8   | 6      1.0       0.0
#        10  | 0      1.0      -0.54
#        11  | 6      1.0       0.0
# 1      7   | 1      1.0      -0.15
#        8   | 6      1.0       0.0
#        10  | 0      1.0      -0.54
#        11  | 6      1.0      -0.54

и я получаю еще один Dataframe с помощью некоторых вычислений, например:

# INDEX  MATCH  IN_VALUE
# 0      6      -0.33
# 1      6      -0.66

Я пытаюсь суммировать столбцы IN_VALUE, когда столбцы INDEX и MATCH совпадают, обновляя первый кадр данных новым IN_VALUE.

Пример вывода для вышеуказанного:

# INDEX  ID  | MATCH  IN_VALUE  OUT_VALUE
# 0      7   | 1      1.0      -0.33
#        8   | 6      0.67       0.0
#        10  | 0      1.0      -0.54
#        11  | 6      0.67       0.0
# 1      7   | 1      1.0      -0.15
#        8   | 6      0.34       0.0
#        10  | 0      1.0      -0.54
#        11  | 6      0.34     -0.54

Обратите внимание, что в первом кадре данных есть несколько строк идентификаторов, к которым может применяться изменение. 8 и 11 в данном случае.

Я могу сбросить индекс, а затем установить его равным ['INDEX', 'MATCH'] для обоих фреймов данных, чтобы использовать команду update(), и это близко к тому, что я хочу. Однако я не хочу просто перезаписывать первый кадр данных вторым, поэтому он не совсем работает.

Кроме того, я нахожу много других возможностей, но ничего из того, что явно работает для применения к нескольким строкам в исходном фрейме данных.

Как я могу добиться этого с помощью панд, сохраняя при этом скорость для больших кадров данных?


person DoubleDouble    schedule 23.07.2020    source источник


Ответы (2)


Сбросьте индекс df1 и используйте DataFrame.merge, чтобы left объединить df1 с df2 в столбцах INDEX и MATCH, затем используйте Series.add, чтобы добавить IN_VALUE к IN_VALUE из правого фрейма данных, наконец, используйте DataFrame.assign, чтобы присвоить это значение обратно столбцу IN_VALUE:

df3 = df1.reset_index().merge(
    df2, on=['INDEX', 'MATCH'], how='left', suffixes=['', '_r'])
    
df3 = df3.assign(IN_VALUE=df3['IN_VALUE'].add(
    df3.pop('IN_VALUE_r'), fill_value=0)).set_index(['INDEX', 'ID'])

Результат:

print(df3)
          MATCH  IN_VALUE  OUT_VALUE
INDEX ID                            
0     7       1      1.00      -0.33
      8       6      0.67       0.00
      10      0      1.00      -0.54
      11      6      0.67       0.00
1     7       1      1.00      -0.15
      8       6      0.34       0.00
      10      0      1.00      -0.54
      11      6      0.34      -0.54
person Shubham Sharma    schedule 23.07.2020
comment
@DoubleDouble Это ответило на ваш вопрос? - person Shubham Sharma; 23.07.2020

Это должно сделать это:

import pandas as pd

#data for df1
d1 = {'INDEX':[0, 0, 0, 0, 1, 1, 1, 1], 'ID':[7, 8, 10, 11, 7, 8, 10, 11],
 'MATCH':[1, 6, 0, 6, 1, 6, 0, 6], 'IN_VALUE':[1, 1, 1, 1, 1, 1, 1, 1],
 'OUT_VALUE':[-0.33, 0.0, -0.54, 0.0, -0.15, 0.0, -0.54, -0.54]}

#data for df2
d2 = {'MATCH':[6, 6], 'IN_VALUE':[-0.33, -0.66]}

#create dataframes
df1 = pd.DataFrame(data = d1)
df2 = pd.DataFrame(data = d2)

#reset index
df1 = df1.reset_index()
df2 = df2.reset_index()

#merge df2 to df1
df3 = df1.merge(df2, how='left', left_on=['INDEX', 'MATCH'], right_on=['index', 'MATCH'])

#sum IN_VALUEs for matches
df3['IN_VALUE_x'].loc[df3['IN_VALUE_y'].notnull()] = df3['IN_VALUE_x'] + df3['IN_VALUE_y']

#rename inValues  
df3 = df3.rename(columns={'IN_VALUE_x': 'IN_VALUE'})
#keep needed columns
df3 = df3[['INDEX', 'ID', 'MATCH', 'IN_VALUE', 'OUT_VALUE']]
#re-index
df3 = df3.set_index(['INDEX', 'ID'])
print(df3)

          MATCH  IN_VALUE  OUT_VALUE
INDEX ID                            
0     7       1      1.00      -0.33
      8       6      0.67       0.00
      10      0      1.00      -0.54
      11      6      0.67       0.00
1     7       1      1.00      -0.15
      8       6      0.34       0.00
      10      0      1.00      -0.54
      11      6      0.34      -0.54
person Mit    schedule 23.07.2020