Панды : Применяйте веса к другому столбцу только для определенных идентификаторов

#python #pandas #performance

Вопрос:

Давайте возьмем этот образец фрейма данных и этот список идентификаторов :

 df=pd.DataFrame({'Id':['A','A','A','B','C','C','D','D'], 'Weight':[50,20,30,1,2,8,3,2], 'Value':[100,100,100,10,20,20,30,30]})

  Id  Weight  Value
0  A      50    100
1  A      20    100
2  A      30    100
3  B       1     10
4  C       2     20
5  C       8     20
6  D       3     30
7  D       2     30

L = ['A','C']
 

Столбец Значение имеет одинаковые значения для каждого идентификатора в столбце Идентификатор. Для конкретных идентификаторов L я хотел бы применить вес столбца » Вес «к столбцу «Значение». В настоящее время я делаю следующее, но это очень медленно с моим реальным большим фреймом данных :

 for i in L :
    df.loc[df["Id"]==i,"Value"] = (df.loc[df["Id"]==i,"Value"] * df.loc[df["Id"]==i,"Weight"] / 
    df[df["Id"]==i]["Weight"].sum())
 

Как, пожалуйста, я мог бы сделать это эффективно ?

Ожидаемый результат :

   Id  Weight  Value
0  A      50     50
1  A      20     20
2  A      30     30
3  B       1     10
4  C       2      4
5  C       8     16
6  D       3     30
7  D       2     30
 

Ответ №1:

Идея работает только для отфильтрованных строк по Series.isin с GroupBy.transform и sum для суммы по группам с тем же размером, что и исходный кадр данных:

 L = ['A','C']

m = df['Id'].isin(L)
df1 = df[m].copy()
s = df1.groupby('Id')['Weight'].transform('sum')
df.loc[m, 'Value'] = df1['Value'].mul(df1['Weight']).div(s)

print (df)
  Id  Weight  Value
0  A      50   50.0
1  A      20   20.0
2  A      30   30.0
3  B       1   10.0
4  C       2    4.0
5  C       8   16.0
6  D       3   30.0
7  D       2   30.0