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

我有这个DataFrame,只想要EPS列不是NaN的记录:

>>> dfSTK_ID  EPS  cashSTK_ID RPT_Date601166 20111231  601166  NaN   NaN600036 20111231  600036  NaN    12600016 20111231  600016  4.3   NaN601009 20111231  601009  NaN   NaN601939 20111231  601939  2.5   NaN000001 20111231  000001  NaN   NaN

…即类似于df.drop(....)的东西来获得这个结果数据框:

                  STK_ID  EPS  cashSTK_ID RPT_Date600016 20111231  600016  4.3   NaN601939 20111231  601939  2.5   NaN

我该怎么做?

1808580 次浏览

不要掉落,只取EPS不是NA的行:

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

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

…还要考虑Wout在他最初的评论中提出的解决方案。处理缺失数据的能力,包括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]: dfOut[26]:0         1         20       NaN       NaN       NaN1  2.677677 -1.466923 -0.7503662       NaN  0.798002 -0.9060383  0.672201  0.964789       NaN4       NaN       NaN  0.0507425 -1.250970  0.030561 -2.6786226       NaN  1.036043       NaN7  0.049896 -0.308003  0.8232958       NaN       NaN  0.6374829 -0.310130  0.078891       NaN

In [27]: df.dropna()     #drop all rows that have any NaN valuesOut[27]:0         1         21  2.677677 -1.466923 -0.7503665 -1.250970  0.030561 -2.6786227  0.049896 -0.308003  0.823295

In [28]: df.dropna(how='all')     #drop only if ALL columns are NaNOut[28]:0         1         21  2.677677 -1.466923 -0.7503662       NaN  0.798002 -0.9060383  0.672201  0.964789       NaN4       NaN       NaN  0.0507425 -1.250970  0.030561 -2.6786226       NaN  1.036043       NaN7  0.049896 -0.308003  0.8232958       NaN       NaN  0.6374829 -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** NaNOut[29]:0         1         21  2.677677 -1.466923 -0.7503662       NaN  0.798002 -0.9060383  0.672201  0.964789       NaN5 -1.250970  0.030561 -2.6786227  0.049896 -0.308003  0.8232959 -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         21  2.677677 -1.466923 -0.7503662       NaN  0.798002 -0.9060383  0.672201  0.964789       NaN5 -1.250970  0.030561 -2.6786226       NaN  1.036043       NaN7  0.049896 -0.308003  0.8232959 -0.310130  0.078891       NaN

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

非常方便!

我知道这已经得到了回答,但只是为了对这个特定问题的纯粹熊猫解决方案,而不是阿曼的一般描述(这太棒了),以防其他人发生这种情况:

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

您可以使用dataframe方法Notnullisnullnumpy.isnan的逆:

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

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

In [347]: df[~np.isnan(df.EPS)]Out[347]:STK_ID  RPT_Date  STK_ID.1  EPS  cash2  600016  20111231    600016  4.3   NaN4  601939  20111231    601939  2.5   NaN

可以添加的是,'&'可以用于添加附加条件例如。

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

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

另一个解决方案使用np.nan != np.nan的事实:

In [149]: df.query("EPS == EPS")Out[149]:STK_ID  EPS  cashSTK_ID RPT_Date600016 20111231  600016  4.3   NaN601939 20111231  601939  2.5   NaN

你可以使用这个:

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

最简单的解决方案:

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

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

简单易行的方法

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

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

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

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 = df.drop(df.columns[df.isna().sum()>len(df.columns)],axis = 1)df = df.dropna(axis = 0).reset_index(drop=True)

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

另一个版本:

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

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

这是一个被殴打致死的老问题,但我相信在这个线程上有一些更有用的信息可以浮出水面。如果您正在寻找以下任何问题的答案,请继续阅读:

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

#0:用法和示例

已经说过df.dropna是从DataFrames中删除NaN的规范方法,但是没有什么比一些视觉提示更有帮助的了。

# Setupdf = pd.DataFrame({'A': [np.nan, 2, 3, 4],'B': [np.nan, np.nan, 2, 3],'C': [np.nan]*3 + [3]})
dfA    B    C0  NaN  NaN  NaN1  2.0  NaN  NaN2  3.0  2.0  NaN3  4.0  3.0  3.0

以下是最重要的参数及其工作原理的详细信息,以FAQ格式排列。


如果它的任何值都有NaN,我可以删除行吗?如果它们都是NaN怎么办?

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

  • 'any'(默认)-如果至少有一列具有NaN,则删除行
  • 'all'-仅当其所有列都具有NaN时才删除行

_->

# Removes all but the last row since there are no NaNsdf.dropna()
A    B    C3  4.0  3.0  3.0
# Removes the first row onlydf.dropna(how='all')
A    B    C1  2.0  NaN  NaN2  3.0  2.0  NaN3  4.0  3.0  3.0

说明
如果您只想查看哪些行为空(IOW,如果您想要行的布尔掩码),使用#0

df.isna()
A      B      C0   True   True   True1  False   True   True2  False  False   True3  False  False  False
df.isna().any(axis=1)
0     True1     True2     True3    Falsedtype: bool

要获取此结果的反转,请使用notna


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

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

指定一个列列表(或带有axis=1的索引),以告诉熊猫您在删除行(或带有axis=1的列)时只想查看这些列(或带有axis=1的行)。

# Drop all rows with NaNs in Adf.dropna(subset=['A'])
A    B    C1  2.0  NaN  NaN2  3.0  2.0  NaN3  4.0  3.0  3.0
# Drop all rows with NaNs in A OR Bdf.dropna(subset=['A', 'B'])
A    B    C2  3.0  2.0  NaN3  4.0  3.0  3.0

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

这是thresh=...参数的用例。将NON-NULL值的最小数量指定为整数。

df.dropna(thresh=1)
A    B    C1  2.0  NaN  NaN2  3.0  2.0  NaN3  4.0  3.0  3.0
df.dropna(thresh=2)
A    B    C2  3.0  2.0  NaN3  4.0  3.0  3.0
df.dropna(thresh=3)
A    B    C3  4.0  3.0  3.0

这里要注意的是,您需要指定要保持的NON-NULL值,而不是要下降的NULL值。这是新用户的痛点。

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

required_min_null_values_to_drop = 2 # drop rows with at least 2 NaNdf.dropna(thresh=df.shape[1] - required_min_null_values_to_drop + 1)
A    B    C2  3.0  2.0  NaN3  4.0  3.0  3.0

如何删除列而不是行?

使用axis=...参数,它可以是axis=0axis=1

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

df.dropna()
A    B    C3  4.0  3.0  3.0
# All columns have rows, so the result is empty.df.dropna(axis=1)
Empty DataFrameColumns: []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    C0  NaN  NaN  NaN1  2.0  NaN  NaN2  3.0  2.0  NaN3  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    B0  NaN  NaN1  2.0  NaN2  3.0  2.03  4.0  3.0

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

dropna,像熊猫API中的大多数其他函数一样,返回一个新的DataFrame(带有更改的原始副本)作为结果,因此如果您想查看更改,应该将其分配回来。

df.dropna(...) # wrongdf.dropna(..., inplace=True) # right, but not recommendeddf = df.dropna(...) # right

参考

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)

在此处输入图片描述

以下方法对我有效。如果上述方法都不起作用,那将有所帮助:

df[df['colum_name'].str.len() >= 1]

基本思想是只有当长度强度大于1时才会拾取记录。如果您正在处理字符串数据,这尤其有用

最好的!

您可以尝试:

df['EPS'].dropna()

您也可以在#1中使用#0

In [4]: df.query('EPS.notna().values')Out[4]:STK_ID.1  EPS  cashSTK_ID RPT_Date600016 20111231    600016  4.3   NaN601939 20111231    601939  2.5   NaN