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

Для каждой группы в groupby я хочу суммировать определенные строки из нескольких столбцов и вывести их в новый столбец is_m_days.

  • Каждая группа (группа имеет CT/RT и имеет количество из 1, 2, 3 или более строк, случайно перемешанных) в 'ATEXT'
  • Для суммы каждая группа имеет строку до и после.

Датафрейм:

data = {'ATEXT': ['', 'CT', 'RT', '', '', '', '', 'CT', 'CT', 'CT', 'TT', ''], 
        'BEGUZ_UE': [11.0, 23.0, 33.0, 15.0, 12.75, 19.75, 14.75, 23.0, 
                     24.0, 24.0, 33.0, 15.0], 
        'subtract': [0.0, 0.0, 0.0, 0.2, np.nan, np.nan, 2.0, np.nan, 
                     np.nan, np.nan, np.nan, 0.0], 
        'add': [3.92, 0.0, 0.0, 0.0, np.nan, np.nan, 0.0, np.nan, np.nan, 
                np.nan, np.nan, 3.57], 
        'UE_more_days': [np.nan, np.nan, 56.0, np.nan, np.nan, np.nan, np.nan, 
                         np.nan, np.nan, np.nan, 104.0, np.nan]}

Результат должен быть:

    ATEXT   BEGUZ_UE    subtract      add      UE_more_days  is_m_days
0             11.00     *0.00*        *3.92*
1     CT      *23.00*    0.00         0.00
2     RT      *33.00*    0.00         0.00          56.0
3             *15.00*    0.20         0.00                      *74.92*
4             12.75         
5             19.75
6             14.75     *2.00*       *0.00*
7     CT      *23.00*
8     RT      *24.00*
9     CT      *24.00*
10    CT      *33.00*                              104.0
11            *15.00*    0.00         3.57                     *117.00*
12
etc

Моя попытка была:

m = df['ATEXT'].eq("")
cond = (~m) & m.shift(-1)
df['UE_more_days'] = (df['BEGUZ_UE'].mask(m)
                      .groupby(m.cumsum()).cumsum()
                      .where(cond)
                     )
tmv = (df[['subtract', 'add']]
       .shift()
       .groupby(m.cumsum())
       .transform('max')
       .eval('add-subtract')
      )


df['is_m_days'] = (df.groupby(m[::-1].cumsum())['BEGUZ_UE']
                .transform('sum')
                .add(tmv)
                .where(cond)
                .shift()
               )

Есть ли лучшее решение?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
112
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш подход хорош, вы могли бы упростить его, используя один groupby (с дополнительными логическими масками):

m1 = df['ATEXT'].eq('')
m2 = m1 & m1.shift(fill_value=True)
m3 = m1!=m2
group = m2.cumsum()

df.loc[m3, 'is_m_days'] = (pd
  .DataFrame({'A': df['BEGUZ_UE'].mask(m2),
              'B': df['add'].sub(df['subtract']).where(m2)})
  .groupby(group).transform('sum').sum(axis=1)
)

Выход:

   ATEXT  BEGUZ_UE  subtract   add  UE_more_days  is_m_days
0            11.00       0.0  3.92           NaN        NaN
1     CT     23.00       0.0  0.00           NaN        NaN
2     RT     33.00       0.0  0.00          56.0        NaN
3            15.00       0.2  0.00           NaN      74.92
4            12.75       NaN   NaN           NaN        NaN
5            19.75       NaN   NaN           NaN        NaN
6            14.75       2.0  0.00           NaN        NaN
7     CT     23.00       NaN   NaN           NaN        NaN
8     CT     24.00       NaN   NaN           NaN        NaN
9     CT     24.00       NaN   NaN           NaN        NaN
10    TT     33.00       NaN   NaN         104.0        NaN
11           15.00       0.0  3.57           NaN     117.00

Другие вопросы по теме