Pandas dataframe fillna () только некоторые столбцы на месте

155

Я пытаюсь заполнить никакие значения в кадре данных Pandas с 0 только для некоторого подмножества столбцов.

Когда я делаю:

import pandas as pd
df = pd.DataFrame(data={'a':[1,2,3,None],'b':[4,5,None,6],'c':[None,None,7,8]})
print df
df.fillna(value=0, inplace=True)
print df

Выход:

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  NaN  7.0
3  NaN  6.0  8.0
     a    b    c
0  1.0  4.0  0.0
1  2.0  5.0  0.0
2  3.0  0.0  7.0
3  0.0  6.0  8.0

Он заменяет каждый Noneна 0's. Я хочу только заменить Nones в столбцах aи b, но не c.

Как лучше всего это сделать?

Саит
источник

Ответы:

239

Вы можете выбрать нужные столбцы и сделать это по назначению:

df[['a', 'b']] = df[['a','b']].fillna(value=0)

Результат ожидаемый:

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0
корень
источник
Да, именно этого я и хочу! Спасибо. Есть ли способы сделать это на месте? Мой исходный фрейм данных довольно большой.
Sait
1
Я не думаю, что это
даст
4
df[['a', 'b']] = df[['a','b']].fillna(value=0)
Локация
2
@EdChum Разве он не создает временный фрейм данных и, следовательно, для этого требуется больше памяти? (Меня больше беспокоит память, чем сложность времени.)
Sait
7
Для многих операций по- inplaceпрежнему будет работать с копией. Не знаю, так это fillnaили нет. Посмотрите этот ответ от одного из разработчиков ядра pandas.
root
94

Вы можете с помощью dict, fillnaс разным значением для другого столбца

df.fillna({'a':0,'b':0})
Out[829]: 
     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0

После назначить обратно

df=df.fillna({'a':0,'b':0})
df
Out[831]: 
     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0
BEN_YO
источник
2
действительно круто, кстати, для слова, которое вы можете использовать, fromkeysесли хотите, +1
U10-Forward
1
Ответ / пример был бы более ясным, если бы он действительно показывал разные значения для разных столбцов.
RufusVS
@RufusVS, это верно, но все же попытайтесь соответствовать ожидаемому результату
операции
2
Это лучшее решение, чем принятый ответ, поскольку оно позволяет избежать проблем с цепочкой индексации, например, если используется сdf.fillna({'a':0,'b':0}, inplace=True)
Alex
20

Вы можете избежать копирования объекта, используя решение Вена и inplace = True:

df.fillna({'a':0, 'b':0}, inplace=True)
print(df)

Что дает:

     a    b    c
0  1.0  4.0  NaN
1  2.0  5.0  NaN
2  3.0  0.0  7.0
3  0.0  6.0  8.0
Лиза Х.
источник
1
Хотя это правильно, избегать копирования не обязательно лучше .
jpp
9

использование верхнего ответа вызывает предупреждение о внесении изменений в копию фрагмента df. Предполагая, что у вас есть другие столбцы, лучший способ сделать это - передать словарь:
df.fillna({'A': 'NA', 'B': 'NA'}, inplace=True)

Джонатан
источник
6

Вот как можно сделать все в одной строке:

df[['a', 'b']].fillna(value=0, inplace=True)

Разбивка: df[['a', 'b']]выбирает столбцы, для которых вы хотите заполнить значения NaN, value=0сообщает ему заполнить NaN нулями и inplace=Trueделает изменения постоянными, без необходимости делать копию объекта.

Жозефина М. Хо
источник
Каким-то образом это дает SettingWithCopyWarning, и изменение не отражается в df.
Майкл
3

Или что-то вроде:

df.loc[df['a'].isnull(),'a']=0
df.loc[df['b'].isnull(),'b']=0

и если есть еще:

for i in your_list:
    df.loc[df[i].isnull(),i]=0
U10-Нападающий
источник
0

Иногда этот синтаксис не работает:

df[['col1','col2']] = df[['col1','col2']].fillna()

Вместо этого используйте следующее:

df['col1','col2']
Сарат Бэби
источник