Объединить несколько значений столбца после группы в один столбец в python pandas

Я хочу выполнить аналогичную задачу, как в этой теме: Объединить значения нескольких столбцов в один столбец в python pandas

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

df= pd.DataFrame({'ID1' : [1,1,2,2,3,3,3],'ID2' : ['a','a','b','b','c','c','c'],
             'Status' : pd.Series([np.nan,'1', np.nan,'1','2',np.nan,'1'], 
                                  dtype="category")})

 df
Out[74]: 
     ID1 ID2 Status
 0    1   a    NaN
 1    1   a      1
 2    2   b    NaN
 3    2   b      1
 4    3   c      2
 5    3   c    NaN
 6    3   c      1

Затем я хочу groupby ID1 и ID2:

gr = df.groupby(['ID1','ID2'])

Затем я хотел бы, чтобы мой результат выглядел так:

Out:
   NewCol
0   1
1   1
2   2,1

Таким образом, это новый DataFrame, который содержит non-null значений столбца Status, сгруппированных по ID1 и ID2.

Заранее спасибо.


person H_A    schedule 21.03.2020    source источник


Ответы (1)


Используйте GroupBy.agg. с лямбда-функцией является наиболее общим решением:

df1 = df.groupby(['ID1','ID2'])['Status'].agg(lambda x: ','.join(x.dropna())).reset_index()
print (df1)
   ID1 ID2 Status
0    1   a      1
1    2   b      1
2    3   c    2,1

Другая идея состоит в том, чтобы удалить дубликаты на первом шаге, но если какая-то группа содержит только отсутствующие значения, она удаляется из вывода, поэтому необходима следующая обработка, например merge:

#first group with only NaNs
df= pd.DataFrame({'ID1' : [1,1,2,2,3,3,3],'ID2' : ['a','a','b','b','c','c','c'],
             'Status' : pd.Series([np.nan,np.nan, np.nan,'1','2',np.nan,'1'], 
                                  dtype="category")})


#first group is dropped
df11 = (df.dropna(subset=['Status'])
          .groupby(['ID1','ID2'])['Status']
          .agg(','.join)
          .reset_index())
print (df11)
   ID1 ID2 Status
0    2   b      1
1    3   c    2,1

#added missing pairs and `NaN`s converted to empty strings:
df2 = df.drop_duplicates(['ID1','ID2'])[['ID1','ID2']].merge(df11, how='left').fillna('')
print (df2)
   ID1 ID2 Status
0    1   a       
1    2   b      1
2    3   c    2,1

Первое решение:

df1 = df.groupby(['ID1','ID2'])['Status'].agg(lambda x: ','.join(x.dropna())).reset_index()
print (df1)
   ID1 ID2 Status
0    1   a       
1    2   b      1
2    3   c    2,1
person jezrael    schedule 21.03.2020
comment
Да, точно. Большое спасибо. - person H_A; 21.03.2020