Как преобразовать столбец dataframe в строку и заменить nans (fillna не работает)

У меня есть фреймворк pandas со столбцом целых чисел, который содержит некоторые nans. Я хочу преобразовать их из целого числа в строку и заменить nans описанием типа «недоступно».

Основная причина в том, что мне нужно запустить groupbys для этого столбца, и, если я не конвертирую nans, groupby избавится от них! Почему это вообще происходит, и как все сообщество панд не поднялось с оружием в руках, - это совершенно отдельная дискуссия (когда я впервые узнал об этом, я не мог в это поверить ...).

Я пробовал приведенный ниже код, но он не работает. Обратите внимание, что я пробовал и astype(str), и astype('str'). В обоих случаях столбец преобразуется в объект, а не в строку; возможно, потому что Python предполагает (ошибочно, все они имеют одинаковую длину в моем фрейме данных), что длина строк варьируется? Но, что самое главное, функция fillna () не работает, и наны остаются нансами! Почему?

import numpy as np
import pandas as pd

df= pd.DataFrame(np.random.randint(1,10,(10000,5)), columns=['a','b','c','d','e'])
df.iloc[0,0]=np.nan
df['a']=df['a'].astype(str)
df['a']=df['a'].fillna('not available')
print(df.dtypes)
print(df.head())

person Pythonista anonymous    schedule 31.10.2017    source источник
comment
строки хранятся в объекте dtype, вы не можете это изменить. .   -  person Bharath    schedule 31.10.2017
comment
О, мой ### @@@ !!! ## ... Я только что заметил, что если я использую astype (объект), то работает fillna. Но почему на Земле? astype (str) уже преобразует его в объект. Я не понимаю!   -  person Pythonista anonymous    schedule 31.10.2017
comment
Добавьте, какую версию pandas вы используете. Это отлично работает для меня.   -  person Bharath    schedule 31.10.2017
comment
Я использую панды 0.20.1   -  person Pythonista anonymous    schedule 31.10.2017
comment
Astype (str) здесь виноват. Об этом говорится в ответе ниже.   -  person Bharath    schedule 31.10.2017


Ответы (2)


fillna не будет работать после того, как вы приведете эти значения к 'str', у вас больше не np.nan в этом столбце, а строковое значение 'nan':

df= pd.DataFrame(np.random.randint(1,10,(10000,5)), columns=['a','b','c','d','e'])
df.iloc[0,0]=np.nan
#df['a']=df['a'].astype(str) <-- You don't need this line.
df['a']=df['a'].fillna('not available')
print(df.dtypes)
print(df.head())

Вывод:

a    object
b     int32
c     int32
d     int32
e     int32
dtype: object
               a  b  c  d  e
0  not available  6  3  9  7
1              5  4  5  5  3
2              4  2  5  3  2
3              4  9  2  8  3
4              2  6  5  9  1
person Scott Boston    schedule 31.10.2017
comment
О да, я думал, что OP поставил этот .astype (str) как вариант. Так что не придайте этому особого значения, но ответ лежит там. - person Bharath; 31.10.2017
comment
2 вопроса: 1) Почему после приведения в строку не работает fillna? 2) Мой крошечный мозг, привыкший к SQL, привык иметь столбцы, которые являются строками, числами, датами и т. Д. Он не понимает, почему числа не могут быть преобразованы в строки, и не понимает, что такое «объект» на самом деле. .. - person Pythonista anonymous; 31.10.2017
comment
fillna предназначена для заполнения floating nans, а не строк. - person Bharath; 31.10.2017
comment
@Pythonistaanonymous сначала у вас есть истинный np.nan, а затем, когда вы приводите его как строку, это значение преобразуется в строку 'nan'. Следовательно, это значение больше не np.nan, а строка 'nan', поэтому fillna не заменит эту строку. Pandas рассматривает всю строку как объект типа данных. - person Scott Boston; 31.10.2017
comment
Может ли строковый столбец иметь nan (эквивалент NULL в SQL), или в строке будет только строка «nan»? - person Pythonista anonymous; 31.10.2017
comment
Для струн нет эквивалента нанометров. Если вы хотите преобразовать его в nan, используйте df['a'].astype(float) - person Bharath; 31.10.2017
comment
df = pd.DataFrame([np.nan],index=[0], dtype='object') df.info() Да, но представление выглядит как «NaN» - person Scott Boston; 31.10.2017
comment
Хотя type(df[0][0]) все еще плавает. Итак, нет специального представления nan для строк - person Bharath; 31.10.2017

df= pd.DataFrame(np.random.randint(1,10,(10,5)), columns=['a','b','c','d','e'])
df.iloc[0,0]=np.nan

df.isnull()
Out[329]: 
       a      b      c      d      e
0   True  False  False  False  False
1  False  False  False  False  False
2  False  False  False  False  False
3  False  False  False  False  False
4  False  False  False  False  False
5  False  False  False  False  False
6  False  False  False  False  False
7  False  False  False  False  False
8  False  False  False  False  False
9  False  False  False  False  False

После перехода на str

df['a']=df['a'].astype(str)

df.isnull()
Out[332]: 
       a      b      c      d      e
0  False  False  False  False  False
1  False  False  False  False  False
2  False  False  False  False  False
3  False  False  False  False  False
4  False  False  False  False  False
5  False  False  False  False  False
6  False  False  False  False  False
7  False  False  False  False  False
8  False  False  False  False  False
9  False  False  False  False  False

Вы меняете нулевое значение, равное np.nan, на строку 'nan'

df.iloc[0,0]
Out[334]: 'nan'
person BENY    schedule 31.10.2017