Условная агрегация по столбцам фрейма данных с объединением ‘n’ строк в 1 строку

#python #pandas #dataframe #aggregation

#python #pandas #фрейм данных #агрегация

Вопрос:

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

 NAME    TEXT                                            START   END
Tim     Tim Wagner is a teacher.                        10      20.5
Tim     He is from Cleveland, Ohio.                     20.5    40
Frank   Frank is a musician.                            40      50
Tim     He like to travel with his family               50      62
Frank   He is a performing artist who plays the cello.  62      70
Frank   He performed at the Carnegie Hall last year.    70      85
Frank   It was fantastic listening to him.              85      90
Frank   I really enjoyed                                90      93
  

Требуется вывести фрейм данных следующим образом:

 NAME    TEXT                                                                                       START       END
Tim     Tim Wagner is a teacher.  He is from Cleveland, Ohio.                                         10          40  
Frank   Frank is a musician                                                                           40          50
Tim     He like to travel with his family                                                             50          62
Frank   He is a performing artist who plays the cello. He performed at the Carnegie Hall last year.   62          85
Frank   It was fantastic listening to him. I really enjoyed                                           85          93   
  

Мой текущий код:

 grp = (df['NAME'] != df['NAME'].shift()).cumsum().rename('group')
df.groupby(['NAME', grp], sort=False)['TEXT','START','END']
  .agg({'TEXT':lambda x: ' '.join(x), 'START': 'min', 'END':'max'})
  .reset_index().drop('group', axis=1)
  

Это объединяет последние 4 строки в одну. Вместо этого я хочу объединить только 2 строки (скажем, любые n строк), даже если ‘NAME’ имеет то же значение.

Ценю вашу помощь в этом.

Спасибо

Ответ №1:

Вы можете grp сгруппировать, чтобы получить относительные блоки внутри группы:

 blocks = df.NAME.ne(df.NAME.shift()).cumsum()

(df.groupby([blocks, df.groupby(blocks).cumcount()//2])
   .agg({'NAME':'first', 'TEXT':' '.join,
         'START':'min', 'END':'max'})
)
  

Вывод:

          NAME                                               TEXT  START   END
NAME                                                                         
1    0    Tim  Tim Wagner is a teacher. He is from Cleveland,...   10.0  40.0
2    0  Frank                               Frank is a musician.   40.0  50.0
3    0    Tim                  He like to travel with his family   50.0  62.0
4    0  Frank  He is a performing artist who plays the cello....   62.0  85.0
     1  Frank  It was fantastic listening to him. I really en...   85.0  93.0