如何在pandas数据框中将所有非数字条目替换为NaN?

12

我有各种csv文件,并将它们作为DataFrame导入。问题在于许多文件使用不同的符号表示缺失值。有些使用nan,其他人使用NaN,ND,None,missing等,或者只是保持条目为空。有没有一种方法可以用np.nan替换所有这些值?换句话说,数据框中的任何非数字值都变成了np.nan。感谢您的帮助。


5
read_csv函数接受一个na_value参数,你可以传入可能的缺失值列表;否则,你可以在DataFrame上调用to_numeric(errors='coerce')来处理缺失值。 - EdChum
请参见相关链接:https://dev59.com/WWUo5IYBdhLWcg3woAqu,以获取有关后处理选项的信息。 - EdChum
谢谢EdChym,这真的很有帮助。 - user6566438
基本上,如果您知道所有可能的NaN值,那么请使用read_csv;如果它们未知但您知道某些无效,则请使用后处理选项。 - EdChum
2个回答

13

我发现了一种我认为相对优雅但也很强大的方法:

def isnumber(x):
    try:
        float(x)
        return True
    except:
        return False

df[df.applymap(isnumber)]

如果不清楚的话:你需要定义一个函数,只有当你有任何输入可以转换为浮点数时才返回True。然后,你使用该布尔数据框筛选df,自动将NaN分配给未筛选的单元格。

我尝试的另一种解决方案是将isnumber定义为

import number
def isnumber(x):
    return isinstance(x, number.Number)
但我不太喜欢这种方法的原因是,你可能会意外地将数字作为字符串处理,这样你就会错误地将它们过滤掉。这也是一个棘手的错误,因为数据框显示字符串"99"和数字99是一样的。
编辑:
在您的情况下,您可能仍然需要在过滤之后使用df = df.applymap(float),因为float适用于所有不同大小写的'nan',但在您明确进行转换之前,它们仍将被视为数据框中的字符串。

1
感谢您提供的优雅解决方案。 - user6566438

4

更易(更安全)地替换非数字输入

TL;DR:为无法转换的列设置数据类型,并提供na_values列表

# Create a custom list of values I want to cast to NaN, and explicitly 
#   define the data types of columns:
na_values = ['None', '(S)', 'S']
last_names = pd.read_csv('names_2010_census.csv', dtype={'pctapi': np.float64}, na_values=na_values)

更详细的解释

我认为在处理混乱数据时,最佳实践是:

  • 为Pandas提供那些数据类型无法正确推断的列的数据类型。
  • 显式地定义应转换为NaN的值列表。

这很容易做到。

Pandas read_csv有一个值列表,它会查找并自动将其转换为NaN,而解析数据(请参见文档read_csv的列表)。您可以使用na_values参数扩展此列表,并使用dtypes参数告诉pandas如何转换特定的列。

在上面的示例中,pctapi是一个列的名称,由于NaN值,它的类型被强制转换为对象类型而不是float64。所以,我强制pandas转换为float64,并为read_csv函数提供了一个要转换为NaN的值列表。

我遵循的过程

由于数据科学通常完全涉及流程,我想描述一下我用于创建na_values列表和调试数据集中的问题的步骤。

步骤1:尝试导入数据并让Pandas推断数据类型。检查数据类型是否如预期。如果是,则继续执行。

enter image description here

在上面的示例中,Pandas大约正确了一半的列。但是,我希望所有列都在“count”字段下方列出为float64类型。我们需要修复这个问题。

步骤2:如果数据类型与预期不符,请使用dtypes参数在读取时显式设置数据类型。默认情况下,这将对无法转换的值抛出错误。

# note: the dtypes dictionary specifying types. pandas will attempt to infer
#   the type of any column name that's not listed
last_names = pd.read_csv('names_2010_census.csv', dtype={'pctwhite': np.float64})

以下是上述代码运行出现的错误信息: enter image description here 步骤3:明确列出pandas无法转换的值并在读取时将其转换为NaN。
根据错误信息,我可以看到pandas无法将值(S)转换。将其添加到我的na_values列表中。
# note the new na_values argument provided to read_csv
last_names = pd.read_csv('names_2010_census.csv', dtype={'pctwhite': np.float64}, na_values=['(S)'])

最后,我重复步骤2和3,直到我有一个全面的dtype映射和na_values列表。

如果你正在进行业余项目,这种方法可能不是你所需要的,你可能希望使用u/instant的答案。然而,如果你在生产系统或团队中工作,花费10分钟正确地转换你的列将是非常值得的。


1
如果您想将值转换为NaN,但这些值不是单个值或少量值,而是具有相似形式,该怎么办?例如,如果我想要一个列是数字类型,但其中一些条目是不同的字符串,我该如何删除它们? - Rylan Schaeffer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接