问答中心分类: DATABASE如何删除某一列中值为 NaN 的 Pandas DataFrame 行
0
匿名用户 提问 2小时 前

我有这个DataFrame并且只想要其记录EPS列不是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

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

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

我怎么做?

Wouter Overmeire 回复 2小时 前

df.dropna(subset = ['column1_name', 'column2_name', 'column3_name'])

Wouter Overmeire 回复 2小时 前

df.dropna(subset = ['EPS'])

Wouter Overmeire 回复 2小时 前

如果你非常讨厌NaN,另一种无情的方式df = df.dropna(subset=df.columns.values)你发现任何地方都没有 NaN

13 Answers
0
Aman 回答 2小时 前

这个问题已经解决了,但是…
…还要考虑 Wouter 在他原来的评论.处理缺失数据的能力,包括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),包括删除列而不是行。
很方便!

James Tobin 回复 2小时 前

你也可以使用df.dropna(subset = ['column_name']).希望至少可以为一个人节省额外的 5 秒“我做错了什么”。很好的答案,+1

Sergey Orshanskiy 回复 2小时 前

@JamesTobin,我只花了 20 分钟为此编写了一个函数!官方文档非常神秘:“要考虑的沿其他轴的标签,例如,如果您要删除行,这些将是要包含的列列表”。我无法理解,他们的意思是什么……

amalik2205 回复 2小时 前

df.dropna(subset = ['column_name'])正是我想要的!谢谢!

cs95 回复 2小时 前

这个答案非常有帮助,但如果任何人都不清楚哪些选项在哪些情况下有用,我整理了一个 dropna 常见问题解答帖子这里.希望对申请困难的人有所帮助dropna根据他们的具体需要。

cookiemonster 回复 2小时 前

+1 这个答案似乎也有助于避免SettingWithCopyWarning稍后当你使用df.dropna(subset = ['column_name'], inplace=True)

0
Kirk Hadley 回答 2小时 前

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

import pandas as pd
df = df[pd.notnull(df['EPS'])]
joris 回复 2小时 前

实际上,具体的答案是:df.dropna(subset=['EPS'])(基于Aman的一般描述,当然这也行)

fantabolous 回复 2小时 前

notnull也是 Wes(Pandas 的作者)在他对另一个答案的评论中所建议的。

Aakash Gupta 回复 2小时 前

这可能是一个菜鸟问题。但是当我执行 df[pd.notnull(…) 或 df.dropna 时,索引会被删除。因此,如果在长度为 200 的 df 中的行索引 10 中有一个空值。运行 drop 函数后的数据帧的索引值从 1 到 9,然后从 11 到 200。无论如何要“重新索引”它

ocean800 回复 2小时 前

你也可以df[pd.notnull(df[df.columns[INDEX]])]在哪里INDEX如果您不知道名称,将是编号列

Mian Asbat Ahmad 回复 2小时 前

出于某种原因,这个答案对我和df.dropna(subset=['column name']没有。

0
Joe 回答 2小时 前

你可以使用这个:

df.dropna(subset=['EPS'], how='all', inplace=True)
Anton Protopopov 回复 2小时 前

how='all'在这里是多余的,因为你只用一个字段对数据框进行子集,所以两者'all''any'会有同样的效果。

Enrique Ortiz Casillas 回复 2小时 前

@AntonProtopopov重要的: how='all'不是多余的。定义一个简单的数据框:df = pd.DataFrame({"a": [10, None], "b": [None, 10]})正在做df.dropna(subset=['a', 'b'], how='all')保持数据框完整(因为没有两列都在的行Nan,同时删除该参数会返回一个空数据帧。

0
cs95 回答 2小时 前

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

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

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

DataFrame.dropna: 用法和例子
已经说过了df.dropna是从 DataFrame 中删除 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

以下是最重要的论点及其工作原理的详细信息,以常见问题解答格式排列。

如果行的任何值具有 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)告诉熊猫你只想看这些列(或行axis=1) 删除行(或列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

我可以删除具有特定 NaN 值计数的行吗?
这是一个用例thresh=...争论。将 NON-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

这里要注意的是你需要指定你想要多少个 NON-NULL 值保持,而不是你想要多少 NULL 值降低.这是新用户的痛点。
幸运的是,修复很简单:如果您有 NULL 值的计数,只需从列大小中减去它即可获得函数的正确 thresh 参数。

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

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

我尝试了上述所有选项,但我的 DataFrame 不会更新!
dropna,与 pandas API 中的大多数其他函数一样,返回一个新的 DataFrame(带有更改的原始副本)作为结果,因此如果您想查看更改,应该将其分配回去。

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

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

在此处输入图像描述

0
Gil Baggio 回答 2小时 前

最简单的解决方案:

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

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