Pandas Python Filtrando nan a partir de uma seleção de dados de uma coluna de strings

190

Sem usar, groupbycomo eu filtraria os dados sem NaN?

Digamos que eu tenha uma matriz em que os clientes preencham 'N / A', 'n / a' ou qualquer uma de suas variações e outros deixem em branco:

import pandas as pd
import numpy as np


df = pd.DataFrame({'movie': ['thg', 'thg', 'mol', 'mol', 'lob', 'lob'],
                  'rating': [3., 4., 5., np.nan, np.nan, np.nan],
                  'name': ['John', np.nan, 'N/A', 'Graham', np.nan, np.nan]})

nbs = df['name'].str.extract('^(N/A|NA|na|n/a)')
nms=df[(df['name'] != nbs) ]

resultado:

>>> nms
  movie    name  rating
0   thg    John       3
1   thg     NaN       4
3   mol  Graham     NaN
4   lob     NaN     NaN
5   lob     NaN     NaN

Como eu filtraria os valores de NaN para que eu pudesse obter resultados para trabalhar assim:

  movie    name  rating
0   thg    John       3
3   mol  Graham     NaN

Acho que preciso de algo parecido, ~np.isnanmas o tilda não funciona com strings.

ccsv
fonte

Respostas:

254

Apenas solte-os:

nms.dropna(thresh=2)

isso eliminará todas as linhas onde houver pelo menos dois não NaN.

Em seguida, você pode soltar onde está o nome NaN:

In [87]:

nms
Out[87]:
  movie    name  rating
0   thg    John       3
1   thg     NaN       4
3   mol  Graham     NaN
4   lob     NaN     NaN
5   lob     NaN     NaN

[5 rows x 3 columns]
In [89]:

nms = nms.dropna(thresh=2)
In [90]:

nms[nms.name.notnull()]
Out[90]:
  movie    name  rating
0   thg    John       3
3   mol  Graham     NaN

[2 rows x 3 columns]

EDITAR

Na verdade, olhando o que você deseja originalmente, você pode fazer exatamente isso sem a dropnachamada:

nms[nms.name.notnull()]

ATUALIZAR

Olhando para essa pergunta três anos depois, há um erro, primeiramente o thresharg procura pelo menosn não NaNvalores, portanto, a saída deve ser:

In [4]:
nms.dropna(thresh=2)

Out[4]:
  movie    name  rating
0   thg    John     3.0
1   thg     NaN     4.0
3   mol  Graham     NaN

É possível que eu tenha me enganado há 3 anos ou que a versão dos pandas que eu estava executando tenha um bug, ambos os cenários são inteiramente possíveis.

EdChum
fonte
190

Mais simples de todas as soluções:

filtered_df = df[df['name'].notnull()]

Assim, ele filtra apenas as linhas que não possuem valores de NaN na coluna 'nome'.

Para várias colunas:

filtered_df = df[df[['name', 'country', 'region']].notnull().all(1)]
Gil Baggio
fonte
2
Como você consegue isso com várias colunas, organizando-as juntas. 'name' é nulo ou 'foo' é nulo
Greg Hilston 29/03/19
3
@Greg Hilston Use os botões & ou | operador para encadear as condições durante a filtragem. filtered_df = df[df['name'].notnull() | df['foo'].notnull()]
Deepak Rajendran
2
@GregHilston Também adicionei a resposta para sua pergunta. Neste exemplo, estou filtrando valores não nulos de cols como cols = ['nome', 'região', 'país']
Gil Baggio
9
df = pd.DataFrame({'movie': ['thg', 'thg', 'mol', 'mol', 'lob', 'lob'],'rating': [3., 4., 5., np.nan, np.nan, np.nan],'name': ['John','James', np.nan, np.nan, np.nan,np.nan]})

for col in df.columns:
    df = df[~pd.isnull(df[col])]
Bashar Mohammad
fonte
5
df.dropna(subset=['columnName1', 'columnName2'])
JacoSolari
fonte