Qual é a diferença entre NaN e None?

94

Estou lendo duas colunas de um arquivo csv usando o pandas readcsv()e, em seguida, atribuindo os valores a um dicionário. As colunas contêm sequências de números e letras. Ocasionalmente, há casos em que uma célula está vazia. Em minha opinião, o valor lido para essa entrada do dicionário deveria ser, Nonemas em vez disso nané atribuído. Certamente Noneé mais descritivo de uma célula vazia, pois tem um valor nulo, enquanto nanapenas diz que o valor lido não é um número.

O meu entendimento está correto, qual é a diferença entre Nonee nan? Por que é nanatribuído em vez de None?

Além disso, minha verificação de dicionário para quaisquer células vazias tem usado numpy.isnan():

for k, v in my_dict.iteritems():
    if np.isnan(v):

Mas isso me dá um erro dizendo que não posso usar esse cheque para v. Eu acho que é porque uma variável inteira ou flutuante, não uma string, deve ser usada. Se isso for verdade, como posso verificar se vhá uma "célula vazia" / nancaso?

user1083734
fonte
O texto qwertynão é um número.
Robert Harvey
1
@RobertHarvey eu sei, então certamente Noneseria uma descrição melhor do valor de uma célula vazia.
user1083734

Respostas:

107

NaN é usado como um espaço reservado para dados ausentes de forma consistente em pandas , a consistência é boa. Eu geralmente leio / traduzo NaN como "ausente" . Consulte também a seção 'trabalhando com dados ausentes' nos documentos.

Wes escreve nos documentos 'escolha da representação de NA' :

Após anos de produção, o uso [NaN] provou, pelo menos na minha opinião, ser a melhor decisão considerando o estado das coisas em NumPy e Python em geral. O valor especial NaN (Not-A-Number) é usado em todos os lugares como o valor NA, e há funções API isnulle notnullque podem ser usadas entre os dtypes para detectar valores NA.
...
Assim, eu escolhi a abordagem Pythônica "praticidade bate pureza" e negociei a capacidade de NA inteiros para uma abordagem muito mais simples de usar um valor especial em matrizes flutuantes e de objetos para denotar NA, e promover matrizes inteiras para flutuantes quando NAs devem ser introduzido.

Nota: o "pegadinho" de que Séries inteiras contendo dados ausentes são convertidas em flutuantes .

Na minha opinião, a principal razão para usar NaN (em vez de None) é que ele pode ser armazenado com o dtype float64 de numpy, em vez do dtype de objeto menos eficiente, consulte as promoções de tipo NA .

#  without forcing dtype it changes None to NaN!
s_bad = pd.Series([1, None], dtype=object)
s_good = pd.Series([1, np.nan])

In [13]: s_bad.dtype
Out[13]: dtype('O')

In [14]: s_good.dtype
Out[14]: dtype('float64')

Jeff comenta (abaixo) sobre isso:

np.nanpermite operações vetorizadas; é um valor flutuante, enquanto None, por definição, força o tipo de objeto, o que basicamente desativa toda a eficiência em numpy.

Portanto, repita 3 vezes rápido: objeto == ruim, flutuante == bom

Dizendo isso, muitas operações ainda podem funcionar tão bem com None vs NaN (mas talvez não sejam suportadas, ou seja, às vezes podem dar resultados surpreendentes ):

In [15]: s_bad.sum()
Out[15]: 1

In [16]: s_good.sum()
Out[16]: 1.0

Para responder à segunda pergunta:
Você deve estar usando pd.isnulle pd.notnullpara testar se há dados ausentes (NaN).

Andy Hayden
fonte
19
apenas adicionar 2c aqui .... np.nanpermite operações vetorizadas; é um valor flutuante, enquanto Nonepor definição força o objecttipo e basicamente desativa toda a eficiência em numpy, então repita 3 vezes rápido:object==bad, float==good
Jeff
1
<NA>Também é um np.nan?
Gathide
18

NaNpode ser usado como um valor numérico em operações matemáticas, enquanto Nonenão pode (ou pelo menos não deveria).

NaNé um valor numérico, conforme definido no padrão de ponto flutuante IEEE 754 . Noneé um tipo interno do Python ( NoneType) e seria mais "inexistente" ou "vazio" do que "numericamente inválido" neste contexto.

O principal "sintoma" disso é que, se você executar, digamos, uma média ou uma soma em uma matriz contendo NaN, mesmo que seja um único, você obtém NaN como resultado ...

Por outro lado, você não pode realizar operações matemáticas usando Nonecomo operando.

Então, dependendo do caso, você pode usar Nonecomo uma forma de dizer ao seu algoritmo para não considerar valores inválidos ou inexistentes nos cálculos. Isso significa que o algoritmo deve testar cada valor para ver se é None.

Numpy tem algumas funções para evitar que valores NaN contaminem seus resultados, como nansume nan_to_numpor exemplo.

Heltonbiker
fonte
Eu concordo com você que Nenhum deve ser usado para entradas inexistentes, então por que df=pd.readcsv('file.csv')me dá NaNvalores para as células vazias e não None? Pelo que eu sei, pd.DataFrames não são exclusivos para números.
user1083734
Bem, provavelmente é uma escolha de design. Suponho que DataFrames e Series tenham um dtype, portanto, valores inválidos de dtype=floatdevem ser representados por valores numéricos, que NaNé e Nonenão Noneé ( é de NoneType).
Heltonbiker
Além disso, muitos métodos do Pandas têm um naargumento, que permite que você decida qual valor usará para substituir os valores não disponíveis
heltonbiker
Ok, obrigado. Portanto, não estou realmente lendo números em meu DataFrame, mas cadeias de números e letras. Que tipo de verificação devo usar para detectar células vazias? Um cheque como; if dtype == float: ??
user1083734
Talvez postar uma amostra de seus dados CSV ajude. Posso imaginar que, se houver strings, então dtype seria string para toda a coluna (Série). Mas talvez, se nem todas as linhas tiverem o mesmo número de colunas, você acabará com dados indisponíveis. Acho que você terá que verificar isso.
heltonbiker
3

A função isnan()verifica se algo é "Não é um número" e retornará se uma variável é ou não um número, por exemplo isnan(2), retornaria falso

O condicional myVar is not Noneretorna independentemente de a variável estar ou não definida

Seu numpy array usa isnan()porque se destina a ser um array de números e inicializa todos os elementos do array para que NaNesses elementos sejam considerados "vazios"

Stephan
fonte
1
Acho isnan(2)que voltaria False, já que 2 não é um NaN.
heltonbiker
Além disso, numpy.emptynão inicializa valores de array para NaN. Ele simplesmente não inicializa os valores.
heltonbiker
5
A verificação apropriada de None-ness é myVar is not None, não myVar != None.
Jaime
3
Observe que np.isnan()não é implementado para variáveis ​​de string, então se você passar uma string, ele irá travar. Melhor usar o pd.isnullque funciona com cordas.
Michael
-1

Abaixo estão as diferenças:

  • nan pertence à classe float
  • None pertence à classe NoneType

Achei o artigo abaixo muito útil: https://medium.com/analytics-vidhya/dealing-with-missing-values-nan-and-none-in-python-6fc9b8fb4f31

Eswara Amirthan s
fonte
Embora este link possa responder à pergunta, é melhor incluir as partes essenciais da resposta aqui e fornecer o link para referência. As respostas somente com link podem se tornar inválidas se a página vinculada mudar. - Da avaliação
A. Kootstra
@ A.Kootstra eu entendo
eswara amirthan s
-3

NaNstants para NÃO um número .
Nonepode significar qualquer .

diegoaguilar
fonte