Jak upuścić wiersze ramki danych Pandy, których wartością w określonej kolumnie jest NaN

Mam to DataFrame i chcę tylko te rekordy, których EPS kolumna nie jest NaN:

>>> df
                 STK_ID  EPS  cash
STK_ID RPT_Date                   
601166 20111231  601166  NaN   NaN
600036 20111231  600036  NaN    12
600016 20111231  600016  4.3   NaN
601009 20111231  601009  NaN   NaN
601939 20111231  601939  2.5   NaN
000001 20111231  000001  NaN   NaN

...tj. coś w rodzaju df.drop(....), aby uzyskać ten wynikowy dataframe:

                  STK_ID  EPS  cash
STK_ID RPT_Date                   
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN
Jak mam to zrobić?
Author: smci, 2012-11-16

12 answers

Nie upuszczaj, po prostu weź wiersze, w których EPS nie jest NA:

df = df[df['EPS'].notna()]
 890
Author: eumiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-16 07:46:41

To pytanie jest już rozwiązane, ale...

...rozważ również rozwiązanie zaproponowane przez Woutera w jego oryginalnym komentarzu . Możliwość obsługi brakujących danych, w tym dropna(), jest wbudowana w pandy jawnie. Oprócz potencjalnie zwiększonej wydajności wykonywania tego ręcznie, funkcje te są również wyposażone w wiele opcji, które mogą być przydatne.

In [24]: df = pd.DataFrame(np.random.randn(10,3))

In [25]: df.iloc[::2,0] = np.nan; df.iloc[::4,1] = np.nan; df.iloc[::3,2] = np.nan;

In [26]: df
Out[26]:
          0         1         2
0       NaN       NaN       NaN
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
4       NaN       NaN  0.050742
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
8       NaN       NaN  0.637482
9 -0.310130  0.078891       NaN

In [27]: df.dropna()     #drop all rows that have any NaN values
Out[27]:
          0         1         2
1  2.677677 -1.466923 -0.750366
5 -1.250970  0.030561 -2.678622
7  0.049896 -0.308003  0.823295

In [28]: df.dropna(how='all')     #drop only if ALL columns are NaN
Out[28]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
4       NaN       NaN  0.050742
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
8       NaN       NaN  0.637482
9 -0.310130  0.078891       NaN

In [29]: df.dropna(thresh=2)   #Drop row if it does not have at least two values that are **not** NaN
Out[29]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
5 -1.250970  0.030561 -2.678622
7  0.049896 -0.308003  0.823295
9 -0.310130  0.078891       NaN

In [30]: df.dropna(subset=[1])   #Drop only if NaN in specific column (as asked in the question)
Out[30]:
          0         1         2
1  2.677677 -1.466923 -0.750366
2       NaN  0.798002 -0.906038
3  0.672201  0.964789       NaN
5 -1.250970  0.030561 -2.678622
6       NaN  1.036043       NaN
7  0.049896 -0.308003  0.823295
9 -0.310130  0.078891       NaN

Istnieją również inne opcje (patrz dokumenty na http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html ), w tym zrzucanie kolumn zamiast wierszy.

Bardzo poręczne!
 991
Author: Aman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-14 00:04:56

Wiem, że już na to odpowiedziano, ale tylko ze względu na czysto pandowe rozwiązanie tego konkretnego pytania, w przeciwieństwie do ogólnego opisu z Aman (co było wspaniałe) i na wypadek, gdyby ktoś inny się na to zdarzył: {]}

import pandas as pd
df = df[pd.notnull(df['EPS'])]
 129
Author: Kirk Hadley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-23 05:37:45

Możesz użyć tego:

df.dropna(subset=['EPS'], how='all', inplace=True)
 68
Author: Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-22 08:04:53

Najprostsze ze wszystkich rozwiązań:

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

Powyższe rozwiązanie jest o wiele lepsze niż użycie np.isfinite ()

 39
Author: Gil Baggio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-08 15:17:20

Możesz użyć metody dataframe notnull lub odwrotności isnull , lub numpy.isnan :

In [332]: df[df.EPS.notnull()]
Out[332]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN


In [334]: df[~df.EPS.isnull()]
Out[334]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN


In [347]: df[~np.isnan(df.EPS)]
Out[347]:
   STK_ID  RPT_Date  STK_ID.1  EPS  cash
2  600016  20111231    600016  4.3   NaN
4  601939  20111231    601939  2.5   NaN
 23
Author: Anton Protopopov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-04 07:01:56

Prosty i łatwy sposób

df.dropna(subset=['EPS'],inplace=True)

Źródło: https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html

 20
Author: Nursnaaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-23 10:13:13

Jak upuścić wiersze ramki danych pand, których wartością w określonej kolumnie jest NaN

To stare pytanie, które zostało pobite na śmierć, ale wierzę, że jest więcej przydatnych informacji, które można znaleźć w tym wątku. Czytaj dalej, Jeśli szukasz odpowiedzi na jedno z następujących pytań:

  • Czy Mogę upuścić wiersze, jeśli którakolwiek z jego wartości ma Nan? A jeśli wszyscy to NaN?
  • Czy mogę patrzeć tylko na Nan w określonych kolumnach podczas upuszczania wiersze?
  • Czy Mogę upuścić wiersze z określoną liczbą wartości NaN?
  • jak zrzucić kolumny zamiast wierszy?
  • wypróbowałem wszystkie powyższe opcje, ale moja ramka danych po prostu nie chce się zaktualizować!

DataFrame.dropna: użycie i przykłady

Mówi się już, że df.dropna jest kanoniczną metodą usuwania Nan z ramek danych, ale nie ma to jak kilka wizualnych wskazówek, które pomogą po drodze.

# Setup
df = pd.DataFrame({
    'A': [np.nan, 2, 3, 4],  
    'B': [np.nan, np.nan, 2, 3], 
    'C': [np.nan]*3 + [3]}) 

df                      
     A    B    C
0  NaN  NaN  NaN
1  2.0  NaN  NaN
2  3.0  2.0  NaN
3  4.0  3.0  3.0

Poniżej szczegóły najważniejszych argumenty i sposób ich działania, ułożone w formacie FAQ.


Czy Mogę upuścić wiersze, jeśli którakolwiek z jego wartości ma Nan? A jeśli wszyscy to NaN?

Tutaj przydaje się argument how=.... Może to być jeden z

  • 'any' (domyślnie) - usuwa wiersze, jeśli co najmniej jedna kolumna ma NaN
  • 'all' - usuwa wiersze tylko wtedy, gdy wszystkie jego kolumny mają Nan

# Removes all but the last row since there are no NaNs 
df.dropna()

     A    B    C
3  4.0  3.0  3.0

# Removes the first row only
df.dropna(how='all')

     A    B    C
1  2.0  NaN  NaN
2  3.0  2.0  NaN
3  4.0  3.0  3.0

Uwaga
Jeśli chcesz tylko zobaczyć, które wiersze are null( IOW, if you want a boolean mask of rows), użyj isna:

df.isna()

       A      B      C
0   True   True   True
1  False   True   True
2  False  False   True
3  False  False  False

df.isna().any(axis=1)

0     True
1     True
2     True
3    False
dtype: bool

Aby uzyskać inwersję tego wyniku, użyj notna zamiast tego.


Czy mogę patrzeć tylko na Nan w określonych kolumnach podczas upuszczania wierszy?

Jest to przypadek użycia argumentu subset=[...].

Określ listę kolumn (lub indeksów z axis=1), aby powiedzieć, że chcesz patrzeć tylko na te kolumny (lub wiersze z axis=1) podczas upuszczania wierszy (lub kolumn z axis=1.

# Drop all rows with NaNs in A
df.dropna(subset=['A'])

     A    B    C
1  2.0  NaN  NaN
2  3.0  2.0  NaN
3  4.0  3.0  3.0

# Drop all rows with NaNs in A OR B
df.dropna(subset=['A', 'B'])

     A    B    C
2  3.0  2.0  NaN
3  4.0  3.0  3.0

Czy Mogę upuścić wiersze z określoną liczbą wartości NaN?

Jest to przypadek użycia argumentu thresh=.... Określ minimalną liczbę wartości innych niż NULL jako liczbę całkowitą.

df.dropna(thresh=1)  

     A    B    C
1  2.0  NaN  NaN
2  3.0  2.0  NaN
3  4.0  3.0  3.0

df.dropna(thresh=2)

     A    B    C
2  3.0  2.0  NaN
3  4.0  3.0  3.0

df.dropna(thresh=3)

     A    B    C
3  4.0  3.0  3.0

Należy tutaj zwrócić uwagę na to, ile wartości innych niż NULL chcesz zachować, a nie ile wartości NULL chcesz upuścić. To problem dla nowych użytkowników.

Na szczęście poprawka jest łatwa: jeśli masz liczbę wartości NULL, po prostu odejmij go od rozmiaru kolumny, aby uzyskać prawidłowy argument progu dla funkcji.

required_min_null_values_to_drop = 2 # drop rows with at least 2 NaN
df.dropna(thresh=df.shape[1] - required_min_null_values_to_drop + 1)

     A    B    C
2  3.0  2.0  NaN
3  4.0  3.0  3.0

Jak zrzucić kolumny zamiast wierszy?

Użyj argumentu axis=..., Może to być axis=0 lub axis=1.

Mówi funkcji, czy chcesz upuścić wiersze (axis=0) czy upuścić kolumny (axis=1).

df.dropna()

     A    B    C
3  4.0  3.0  3.0

# All columns have rows, so the result is empty.
df.dropna(axis=1)

Empty DataFrame
Columns: []
Index: [0, 1, 2, 3]

# Here's a different example requiring the column to have all NaN rows
# to be dropped. In this case no columns satisfy the condition.
df.dropna(axis=1, how='all')

     A    B    C
0  NaN  NaN  NaN
1  2.0  NaN  NaN
2  3.0  2.0  NaN
3  4.0  3.0  3.0

# Here's a different example requiring a column to have at least 2 NON-NULL
# values. Column C has less than 2 NON-NULL values, so it should be dropped.
df.dropna(axis=1, thresh=2)

     A    B
0  NaN  NaN
1  2.0  NaN
2  3.0  2.0
3  4.0  3.0

Próbowałem wszystkich opcji powyżej, ale moja ramka danych po prostu nie chce się zaktualizować!

dropna, podobnie jak większość innych funkcji w pandas API zwraca nową DataFrame (kopia oryginału ze zmianami) jako wynik, więc należy przypisać go z powrotem, jeśli chcesz zobaczyć zmiany.

df.dropna(...) # wrong
df.dropna(..., inplace=True) # right, but not recommended
df = df.dropna(...) # right

Odniesienie

Https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.dropna.html

DataFrame.dropna(
    self, axis=0, how='any', thresh=None, subset=None, inplace=False)

Tutaj wpisz opis obrazka

 15
Author: cs95,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-03 22:07:23

Jeszcze jedno rozwiązanie, które wykorzystuje fakt, że np.nan != np.nan:

In [149]: df.query("EPS == EPS")
Out[149]:
                 STK_ID  EPS  cash
STK_ID RPT_Date
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN
 12
Author: MaxU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-20 21:15:56

Inna wersja:

df[~df['EPS'].isna()]
 3
Author: keramat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-10 09:19:10

Można dodać, że ' & ' może być użyte do dodania dodatkowych warunków np.

df = df[(df.EPS > 2.0) & (df.EPS <4.0)]

Zauważ, że przy ocenie wypowiedzi pandy potrzebują nawiasu.

 1
Author: David,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-26 23:12:08

W zestawach danych o dużej liczbie kolumn jeszcze lepiej jest sprawdzić, ile kolumn zawiera wartości null, a ile nie.

print("No. of columns containing null values")
print(len(df.columns[df.isna().any()]))

print("No. of columns not containing null values")
print(len(df.columns[df.notna().all()]))

print("Total no. of columns in the dataframe")
print(len(df.columns))

Na przykład w moim dataframe zawierała ona 82 kolumny, z czego 19 zawierało co najmniej jedną wartość null.

Ponadto możesz również automatycznie usunąć cols i rows w zależności od tego, który ma więcej wartości null
Oto kod, który robi to inteligentnie:

df = df.drop(df.columns[df.isna().sum()>len(df.columns)],axis = 1)
df = df.dropna(axis = 0).reset_index(drop=True)

Uwaga: powyższy kod usuwa wszystkie Twoje null wartości. Jeśli chcesz wartości null, przetworz je wcześniej.

 1
Author: Pradeep Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-02-17 11:00:16