Дублировать позиции из группы

#python #pandas #dataframe #group-by #pandas-groupby

#python #панды #фрейм данных #группировка по #pandas-groupby

Вопрос:

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

   col  value
0    A      1
1    A    NaN
2    B    NaN
3    B    NaN
4    B    NaN
5    B      1
6    C      3
7    C    NaN
8    C    NaN
9    D      5
10   E      6
  

Для каждой группы установлено только одно значение, остальные в Nan. Что я хочу знать, так это заполнить NaN значением группы. Если у группы нет NAN, я просто хочу ее игнорировать.
Результат должен выглядеть так:

   col  value
0    A      1
1    A      1
2    B      1
3    B      1
4    B      1
5    B      1
6    C      3
7    C      3
8    C      3
9    D      5
10   E      6
  

То, что я пробовал до сих пор, заключается в следующем:

 df["value"] = df.groupby(col).transform(lambda x: x.fillna(x.mean()))
  

Однако этот метод не только очень медленный, но и не дает мне желаемого результата.

У кого-нибудь есть идея?

Комментарии:

1. @MayankPorwal — Кажется, нет However, this method is not only super slow, but doesn't give me the wished result.

2. @jezrael отозвал мое голосование.

Ответ №1:

Это зависит от данных — если всегда есть одно не пропущенное значение, которое вы можете отсортировать, а затем заменить на GroupBy.ffill , оно работает хорошо, если в некоторых группах есть NAN только s:

 df = df.sort_values(['col','value'])
df["value"] = df.groupby('col')["value"].ffill()
#if always only one non missing value per group, fail if all NaNs of some group
#df["value"] = df["value"].ffill()
print (df)
   col  value
0    A    1.0
1    A    1.0
5    B    1.0
2    B    1.0
3    B    1.0
4    B    1.0
6    C    3.0
7    C    3.0
8    C    3.0
9    D    5.0
10   E    6.0
  

Или, если имеется несколько значений и требуется заменить на среднее, для улучшения производительности измените свое решение GroupBy.transform mean , передав только Series.fillna :

 df["value"] = df["value"].fillna(df.groupby('col')["value"].transform('mean'))
print (df)
   col  value
0    A    1.0
1    A    1.0
5    B    1.0
2    B    1.0
3    B    1.0
4    B    1.0
6    C    3.0
7    C    3.0
8    C    3.0
9    D    5.0
10   E    6.0
  

Ответ №2:

Вы можете использовать ffill то же fillna() самое, что и с method=ffill (см. Документы)

 df["value"] = df["value"].ffill()