Дан следующий набор данных df:

  type module   item  value  input
0    A      a  item1      2      1
1    A      a  item2      3      0
2    A     aa  item3      4      1
3    A     aa  item4      3      0
4    A     aa  item5      1     -1
5    B      b  item1      5      0
6    B      b  item2      1     -1
7    B     bb  item3      3      0
8    B     bb  item4      3      1
9    B     bb  item5      4      0

Мне нужно вычислить sum из pct на основе следующей логики: сначала мы берем только value, input которого равно 0 или 1 как допустимые значения. Затем мне нужно сгруппировать по type, module, чтобы вычислить процент от суммы, например, pct первой строки A-a-item1 вычисляется по 2/(2 + 3) = 0.4, A-aa-item1 вычисляется на 4/(4 + 3) = 0.57, а не на 8, поскольку входное значение для A-aa-item3 равно -1, поэтому оно исключается. Столбец sum в df2 рассчитывается по группам type module, а затем по сумме sum.

df1:

  type module   item  value  input       pct 
0    A      a  item1      2      1  0.400000
1    A      a  item2      3      0  0.000000 
2    A     aa  item1      4      1  0.571429 
3    A     aa  item2      3      0  0.000000 
4    A     aa  item3      1     -1  0.000000 
5    B      b  item1      5      0  0.000000 
6    B      b  item2      1     -1  0.000000 
7    B     bb  item1      3      0  0.000000 
8    B     bb  item2      3      1  0.300000 
9    B     bb  item3      4      0  0.000000

df2:

  type module   sum
0    A      a  0.40
1    A     aa  0.57
2    B      b  0.00
3    B     bb  0.30

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

1
xarena 20 Июл 2020 в 10:36
1
Таким образом, есть 2 маски: сначала сравнить на равенство 0 или 1, а затем сравнить на 1, поэтому строки с -1, 0 устанавливаются в 0 в pct?
 – 
jezrael
20 Июл 2020 в 10:47

1 ответ

Лучший ответ

Вы можете заменить несоответствие условиям на Series.eq для сравнения по 1 с 0 и сравнения по 0, 1 по Series.isin, вместо этого используется агрегирование GroupBy.transform с sum для нового столбца, заполненного агрегированными значениями и разделены на Series.div :

s1 = df['value'].where(df['input'].eq(1), 0)
s2 = (df.assign(value = df['value'].where(df['input'].isin([0,1]), 0))
        .groupby(['type','module'])['value'].transform('sum'))
df['pct '] = s1.div(s2)
print (df)
  type module   item  value  input      pct 
0    A      a  item1      2      1  0.400000
1    A      a  item2      3      0  0.000000
2    A     aa  item3      4      1  0.571429
3    A     aa  item4      3      0  0.000000
4    A     aa  item5      1     -1  0.000000
5    B      b  item1      5      0  0.000000
6    B      b  item2      1     -1  0.000000
7    B     bb  item3      3      0  0.000000
8    B     bb  item4      3      1  0.300000
9    B     bb  item5      4      0  0.000000

Для второго DataFrame добавлены 2 новых столбца с помощью DataFrame.assign, агрегировать sum и последнее деление с помощью DataFrame.pop для использования и удаления столбца value:

df2 = (df.assign(value = df['value'].where(df['input'].isin([0,1]), 0),
                 pct = df['value'].where(df['input'].eq(1), 0))
         .groupby(['type','module'])[['value','pct']]
         .sum()
         .assign(pct = lambda x: x['pct'].div(x.pop('value')))
         .reset_index())

print (df2)
  type module       pct
0    A      a  0.400000
1    A     aa  0.571429
2    B      b  0.000000
3    B     bb  0.300000
1
jezrael 20 Июл 2020 в 10:50
Извините, я обнаружил небольшую проблему в вашем коде, как я писал в последнем вопросе, когда мы вычисляем pct для df, нам нужно исключить значения input=-1 из сумм.
 – 
xarena
20 Июл 2020 в 11:28
- выход другой в вопросе?
 – 
jezrael
20 Июл 2020 в 11:29
stackoverflow.com/questions/62989116/…. Мне нужно внедрить это и после groupby.
 – 
xarena
20 Июл 2020 в 11:30
- Итак, вам нужно изменить pct = df['value'].where(df['input'].eq(1), 0) на pct = df['value'].where(df['input'] != -1, 0)?
 – 
jezrael
20 Июл 2020 в 11:32
1
Извините, моя ошибка, ваш код идеален, я неправильно заменил value на другое имя, но в каком-то коде оно сохраняется.
 – 
xarena
20 Июл 2020 в 12:26