Trouver un index entier de lignes avec NaN dans pandas dataframe

94

J'ai un DataFrame pandas comme celui-ci:

                    a         b
2011-01-01 00:00:00 1.883381  -0.416629
2011-01-01 01:00:00 0.149948  -1.782170
2011-01-01 02:00:00 -0.407604 0.314168
2011-01-01 03:00:00 1.452354  NaN
2011-01-01 04:00:00 -1.224869 -0.947457
2011-01-01 05:00:00 0.498326  0.070416
2011-01-01 06:00:00 0.401665  NaN
2011-01-01 07:00:00 -0.019766 0.533641
2011-01-01 08:00:00 -1.101303 -1.408561
2011-01-01 09:00:00 1.671795  -0.764629

Existe-t-il un moyen efficace de trouver l'index "entier" des lignes avec NaN? Dans ce cas, la sortie souhaitée doit être [3, 6].

Jean-François Corbett
la source
12
Si vous voulez simplement sélectionner les lignes avec nan, vous pouvez le fairedf[np.isnan(df['b'])]
paresseux1
4
Suite de @ lazy1 - au lieu d'utiliser numpys, isnanvous pouvez également utiliserdf['b'].isnull()
jmetz

Réponses:

46

Pour DataFrame df:

import numpy as np
index = df['b'].index[df['b'].apply(np.isnan)]

vous rendra le MultiIndexque vous pouvez utiliser pour indexer df, par exemple:

df['a'].ix[index[0]]
>>> 1.452354

Pour l'index entier:

df_index = df.index.values.tolist()
[df_index.index(i) for i in index]
>>> [3, 6]
diliop
la source
1
Aussi intuitif que cela puisse ixparaître, pour certaines raisons, il semble qu'il ait été déconseillé en faveur deiloc
cardamome
144

Voici une solution plus simple:

inds = pd.isnull(df).any(1).nonzero()[0]

In [9]: df
Out[9]: 
          0         1
0  0.450319  0.062595
1 -0.673058  0.156073
2 -0.871179 -0.118575
3  0.594188       NaN
4 -1.017903 -0.484744
5  0.860375  0.239265
6 -0.640070       NaN
7 -0.535802  1.632932
8  0.876523 -0.153634
9 -0.686914  0.131185

In [10]: pd.isnull(df).any(1).nonzero()[0]
Out[10]: array([3, 6])
Wes McKinney
la source
29
J'ai fini par utiliser ceci:np.where(df['b'].notnull())[0]
merci, .nonzero()[0]c'est mieux que [i for i, k in enumerate(mask) if k].)
Winand
2
Vous pourriez probablement simplifier cela davantage:r, _ = np.where(df.isna())
cs95
2
ajouter d'abord .to_numpy()pour convertir dans le tableau numpy -pd.isnull(df).any(1).to_numpy().nonzero()
7bStan
13

Solution en une seule ligne. Cependant, cela fonctionne pour une seule colonne.

df.loc[pandas.isna(df["b"]), :].index
Vasyl Vaskivskyi
la source
C'est ce que je cherchais. Je l'ai fait dans une liste en l'enveloppant dans un list(...)comme ceci:list(df.loc[pandas.isna(df["b"]), :].index)
Daniel Butler le
9

Et juste au cas où, si vous voulez trouver les coordonnées de `` nan '' pour toutes les colonnes à la place (en supposant qu'elles soient toutes numériques), allez-y:

df = pd.DataFrame([[0,1,3,4,np.nan,2],[3,5,6,np.nan,3,3]])

df
   0  1  2    3    4  5
0  0  1  3  4.0  NaN  2
1  3  5  6  NaN  3.0  3

np.where(np.asanyarray(np.isnan(df)))
(array([0, 1]), array([4, 3]))
Filippo Mazza
la source
9

Je ne sais pas si c'est trop tard mais vous pouvez utiliser np.where pour trouver les indices des non valeurs en tant que telles:

indices = list(np.where(df['b'].isna()[0]))
naturesenshi
la source
4

Voici des tests pour quelques méthodes:

%timeit np.where(np.isnan(df['b']))[0]
%timeit pd.isnull(df['b']).nonzero()[0]
%timeit np.where(df['b'].isna())[0]
%timeit df.loc[pd.isna(df['b']), :].index

Et leurs horaires correspondants:

333 µs ± 9.95 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
280 µs ± 220 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
313 µs ± 128 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)
6.84 ms ± 1.59 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Il semblerait que cela pd.isnull(df['DRGWeight']).nonzero()[0]gagne la journée en termes de timing, mais que l'une des trois meilleures méthodes a des performances comparables.

Adam Erickson
la source
3

dans le cas où vous avez un index datetime et que vous souhaitez avoir les valeurs:

df.loc[pd.isnull(df).any(1), :].index.values
Amirkhm
la source
2

Une autre solution simple est list(np.where(df['b'].isnull())[0])

karthikeyan
la source
1

Voici une autre prise plus simple:

df = pd.DataFrame([[0,1,3,4,np.nan,2],[3,5,6,np.nan,3,3]])

inds = np.asarray(df.isnull()).nonzero()

(array([0, 1], dtype=int64), array([4, 3], dtype=int64))
cire d'abeille nonya
la source
1

Je cherchais tous les index de lignes avec des valeurs NaN.
Ma solution de travail:

def get_nan_indexes(data_frame):
    indexes = []
    print(data_frame)
    for column in data_frame:
        index = data_frame[column].index[data_frame[column].apply(np.isnan)]
        if len(index):
            indexes.append(index[0])
    df_index = data_frame.index.values.tolist()
    return [df_index.index(i) for i in set(indexes)]
murthy10
la source
0

Soit le dataframe nommé df et la colonne d'intérêt (c'est-à - dire la colonne dans laquelle nous essayons de trouver des valeurs nulles ) est «b» . Ensuite, l'extrait de code suivant donne l'index souhaité de null dans le dataframe:

   for i in range(df.shape[0]):
       if df['b'].isnull().iloc[i]:
           print(i)
Pierre Austin
la source