#python #python-3.x #pandas #dataframe #isnull
#python #панды
Вопрос:
Я пытаюсь приписать / заполнить значения, используя строки с аналогичными значениями столбцов.
Например, у меня есть этот фрейм данных:
one | two | three
1 1 10
1 1 nan
1 1 nan
1 2 nan
1 2 20
1 2 nan
1 3 nan
1 3 nan
Я хотел использовать ключи столбца one
и two
который похож, и если столбец three
не полностью nan, то вменить существующее значение из строки похожих ключей со значением в столбце ‘3’.
Вот мой желаемый результат:
one | two | three
1 1 10
1 1 10
1 1 10
1 2 20
1 2 20
1 2 20
1 3 nan
1 3 nan
Вы можете видеть, что ключи 1 и 3 не содержат никакого значения, потому что существующее значение не существует.
Я пытался использовать groupby
fillna()
:
df['three'] = df.groupby(['one','two'])['three'].fillna()
что выдало мне ошибку.
Я попробовал прямое заполнение, которое дало мне довольно странный результат, когда вместо этого оно перенаправляет заполнение столбца 2. Я использую этот код для прямого заполнения.
df['three'] = df.groupby(['one','two'], sort=False)['three'].ffill()
Ответ №1:
Если для каждой группы используется только одно значение, отличное от NaN ffill
(прямое заполнение) и bfill
(обратное заполнение) для каждой группы, поэтому необходимо apply
с lambda
:
df['three'] = df.groupby(['one','two'], sort=False)['three']
.apply(lambda x: x.ffill().bfill())
print (df)
one two three
0 1 1 10.0
1 1 1 10.0
2 1 1 10.0
3 1 2 20.0
4 1 2 20.0
5 1 2 20.0
6 1 3 NaN
7 1 3 NaN
Но если несколько значений для каждой группы и требуется заменить NaN
на некоторую константу — например mean
, по группе:
print (df)
one two three
0 1 1 10.0
1 1 1 40.0
2 1 1 NaN
3 1 2 NaN
4 1 2 20.0
5 1 2 NaN
6 1 3 NaN
7 1 3 NaN
df['three'] = df.groupby(['one','two'], sort=False)['three']
.apply(lambda x: x.fillna(x.mean()))
print (df)
one two three
0 1 1 10.0
1 1 1 40.0
2 1 1 25.0
3 1 2 20.0
4 1 2 20.0
5 1 2 20.0
6 1 3 NaN
7 1 3 NaN
Комментарии:
1. @jezrael: есть ли какая-либо причина, по которой force использовать
apply
в вашем ответе? Я спрашиваю, потому что я попробовал directffill
иbfill
, и он возвращает правильный результат:df['three'] = df.groupby(['one', 'two'])['three'].ffill().bfill()
2. @Andy L. Это работает правильно, потому что последняя группа — это только NaN-группа. Если изменить образец данных для первой только NaN-группы (от 10 до NaN), ваше решение не удалось. Причина в том, что последнее заполнение работает не для групп, а для серии, возвращаемой groupby ffill .
3. ах, я забыл, что
bfill
обратное заполнение выходных рядовffill
, а неgroupby
. Спасибо за ответы4. Могу ли я спросить, как я могу применить
df['three'] = df.groupby(['one','two'], sort=False)['three'].apply(lambda x: x.ffill().bfill())
к нескольким столбцамthree, four, five, etc
, а не толькоthree
к тем, которые нуждаются в groupbyone
иtwo
и fillna?5. @ahbon — Использовать
cols = ['three','four','five']
иdf[cols] = df.groupby(['one','two'], sort=False)[cols].apply(lambda x: x.ffill().bfill())
Ответ №2:
Вы можете сортировать данные по столбцу с пропущенными значениями, затем groupby и forwardfill:
df.sort_values('three', inplace=True)
df['three'] = df.groupby(['one','two'])['three'].ffill()