如何删除某些列中的值为NaN的Pandas DataFrame行

时间:2012-11-16 09:17:23

标签: python pandas dataframe

我有DataFrame

>>> 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

然后我只想要EPS不是NaN的记录,即df.drop(....)将返回如下数据框:

                  STK_ID  EPS  cash
STK_ID RPT_Date                   
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN

我该怎么做?

17 个答案:

答案 0 :(得分:735)

这个问题已经解决了,但是......

...还考虑了Wouter在his original comment中提出的解决方案。处理丢失数据的能力(包括dropna())明确地构建在pandas中。除了手动改进的性能之外,这些功能还提供了许多可能有用的选项。

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

还有其他选项(请参阅http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html处的文档),包括删除列而不是行。

非常方便!

答案 1 :(得分:448)

不要drop。只需获取EPS 有限的行:

df = df[np.isfinite(df['EPS'])]

答案 2 :(得分:96)

我知道这已经得到了解答,但仅仅是为了解决这个特定问题的纯粹熊猫解决方案而不是Aman的一般描述(这很精彩)以及其他任何事情发生在这个问题上:

import pandas as pd
df = df[pd.notnull(df['EPS'])]

答案 3 :(得分:34)

您可以使用:

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

答案 4 :(得分:26)

最简单的解决方案:

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

上述解决方案比使用np.isfinite()

更好

答案 5 :(得分:21)

您可以使用数据框方法notnullisnull的倒数,或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

答案 6 :(得分:12)

如何删除在特定列中值为NaN的Pandas DataFrame行

这是一个老问题,已经被打死了,但我确实相信在此线程上还有一些更有用的信息。如果您正在寻找以下任何问题的答案,请继续阅读:

  • 如果其任何值具有NaN都可以删除行吗?如果所有人都是NaN怎么办?
  • 删除行时只能查看特定列中的NaN吗?
  • 我可以删除具有特定数量的NaN值的行吗?
  • 如何删除列而不是行?
  • 我尝试了上述所有选项,但我的DataFrame不会更新!

DataFrame.dropna:用法和示例

已经有人说过df.dropna是从DataFrames中删除NaN的规范方法,但是在此过程中并没有什么视觉提示可以提供帮助。

# 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

下面以FAQ格式详细介绍了最重要的参数及其工作方式。


如果其任何值具有NaN都可以删除行吗?如果所有人都是NaN怎么办?

这是how=...参数派上用场的地方。可以是

之一
  • 'any'(默认)-如果至少一列具有NaN,则删除行
  • 'all'-仅在其所有列均具有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

注意
如果您只想查看哪些行为空(IOW,如果您想 行的布尔掩码),使用 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

要获得该结果的倒数,请使用 notna 代替。


删除行时只能查看特定列中的NaN吗?

这是subset=[...]参数的用例。

指定列列表(或带有axis=1的索引)以告诉熊猫在删除行(或带有{{1}的列)时只希望查看这些列(或带有axis=1的行) }。

axis=1

我可以删除具有特定NaN值计数的行吗?

这是# 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 参数的用例。将NON-NULL值的最小数目指定为整数。

thresh=...

这里要注意的事情是,您需要指定要保留的多少个NON-NULL值,而不是要丢弃的多少个NULL值。这是新用户的痛点。

幸运的是,此修复很容易:如果您有NULL值计数,只需从列大小中减去它即可获得该函数的正确脱粒参数。

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

如何删除列而不是行?

使用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 参数,它可以是axis=...axis=0

告诉函数是要删除行(axis=1)还是删除列(axis=0)。

axis=1

我尝试了上述所有选项,但我的DataFrame不会更新!

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 与pandas API中的大多数其他函数一样,将返回一个新的DataFrame(带有更改的原始数据副本)作为结果,因此,如果要查看更改,则应将其分配回去。

dropna

参考

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

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

enter image description here

答案 7 :(得分:10)

另一个使用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

答案 8 :(得分:9)

您可以使用dropna

示例

删除至少缺少一个元素的行。

df=df.dropna()

定义在哪些列中查找缺失值。

df=df.dropna(subset=['column1', 'column1'])

有关更多示例,请参见this

  

注意:dropna的轴参数自版本0.23.0起已弃用:

答案 9 :(得分:7)

或者((用isnull检查NaN,然后​​使用~来代替没有NaN):

df=df[~df['EPS'].isnull()]

现在:

print(df)

是:

                 STK_ID  EPS  cash
STK_ID RPT_Date
600016 20111231  600016  4.3   NaN
601939 20111231  601939  2.5   NaN

答案 10 :(得分:2)

简单易用的方法

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

来源:https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.dropna.html

答案 11 :(得分:2)

这个答案比上面的答案要简单得多:)

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

答案 12 :(得分:2)

另一个版本:

df[~df['EPS'].isna()]

答案 13 :(得分:1)

可以在'&amp;'处添加可用于添加其他条件,例如

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

请注意,在评估语句时,pandas需要括号。

答案 14 :(得分:0)

由于某些原因,以前提交的答案都没有为我工作。这个基本的解决方案确实:

public void assignName()
{
  //assign button names
}

虽然当然会删除带有负数的行。所以,如果你想要那些可能也很聪明,也可以添加它。

df = df[df.EPS >= 0]

答案 15 :(得分:0)

在具有大量列的数据集中,最好查看有多少列包含空值而有多少列不包含空值。

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))

例如,在我的数据框中,它包含82列,其中19列至少包含一个空值。

此外,您还可以自动删除列和行,具体取决于哪个列具有更多的空值
这是执行此操作的代码:

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

注意:上面的代码删除了所有空值。如果需要空值,请先处理它们。

答案 16 :(得分:-1)

一种解决方案可以是

df = df[df.isnull().sum(axis=1) <= Cutoff Value]

另一种方式可以

df= df.dropna(thresh=(df.shape[1] - Cutoff_value))

我希望这些有用。