Pandas:ValueError:无法将浮点NaN转换为整数

107

以下代码出现ValueError: cannot convert float NaN to integer

df = pandas.read_csv('zoom11.csv')
df[['x']] = df[['x']].astype(int)
  • “x”是csv文件中的一列,我无法在文件中找到任何float NaN,而且我不明白出现了什么错误或为什么会出现这种错误。
  • 当我读取该列为字符串时,它具有像-1、0、1...2000这样的值,对我来说所有值看起来都很好。
  • 当我将该列读取为浮点数时,就可以加载。然后它显示的值为-1.0、0.0等,但没有任何NaN。
  • 我尝试了使用error_bad_lines = False和read_csv中的dtype参数,但都无济于事。它只是用相同的异常取消了加载。
  • 该文件不小(10多M行),因此无法手动检查它。当我提取一个小标题部分时,就不会出现错误,但是完整文件会出现错误。因此,其中有些内容可能存在问题,但我无法确定是什么问题。
  • 逻辑上讲,csv文件不应该有丢失的值,但即使出现一些垃圾数据,我也愿意跳过这些行。或者至少识别它们,但我不知道如何扫描文件并报告转换错误。

更新:使用评论/答案中的提示,我成功地清理了我的数据:

# x contained NaN
df = df[~df['x'].isnull()]

# Y contained some other garbage, so null check was not enough
df = df[df['y'].str.isnumeric()]

# final conversion now worked
df[['x']] = df[['x']].astype(int)
df[['y']] = df[['y']].astype(int)

1
尝试使用 df[df['x'].isnull()] 进行检查。 - jezrael
1
你需要弄清楚你想对任何NaN值做什么,然后去做。 - cs95
谢谢@jezrael,现在df[df['x'].isnull()]已经识别出了一个带有“NaN”的行,我可以将其删除!现在又有一个类似的字段 - 这似乎有一些其他不是int类型的垃圾。是否有通用方法来查找无法转换为给定数据类型的行,以便我可以识别并清除它们所有? - JaakL
使用 pd.to_numericerrors=coerce,而不是使用 astype int,然后通过 fillna 来填充任何你想要的值。 - Bharath M Shetty
我来到这篇文章是因为遇到了同样的错误,但在我的情况下,当我将数据框重置为df = df.reset_index(drop=True)时,问题得到了解决... 只是在这里评论,如果有人遇到类似的问题阅读这篇文章。 - DOT
显示剩余2条评论
5个回答

103

使用布尔索引来识别NaN值:

print(df[df['x'].isnull()])

然后要删除所有非数字值,使用带有参数errors='coerce'to_numeric 函数 - 将非数字值替换为 NaN

df['x'] = pd.to_numeric(df['x'], errors='coerce')

要删除列x中所有包含NaN的行,请使用dropna函数:

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

将值转换为int

df['x'] = df['x'].astype(int)

谢谢,这还可以。我已经更新了我的问题并附上了我的代码。最后一个我不明白的是为什么负数会返回False:'-1'.isnumeric()?虽然对于我的数据x和y >=0没有问题,但这是一个普遍的问题,因为我在官方文档中没有看到相关说明。 - JaakL
4
你看到这个可能是因为Python将'-1'解释为字符串,而不是数字。 - Ben
我在一个空的df上使用了df.max(),感谢您的建议。 - Vzzarr

38

数值错误:无法将浮点数NaN转换为整数

从v0.24版本开始,实际上是可以的。Pandas引入了可空整数数据类型,允许整数与NaN共存。

给定一系列具有缺失数据的浮点数整体,

s = pd.Series([1.0, 2.0, np.nan, 4.0])
s

0    1.0
1    2.0
2    NaN
3    4.0
dtype: float64

s.dtype
# dtype('float64')
你可以将其转换为可空的 int 类型(从 Int16Int32Int64 中选择一个)使用以下代码:

nullable int 类型 (选择 Int16, Int32, 或者 Int64 中的一个) 转换方法如下:

s2 = s.astype('Int32') # note the 'I' is uppercase
s2

0      1
1      2
2    NaN
3      4
dtype: Int32

s2.dtype
# Int32Dtype()

您的列需要是整数,才能进行强制类型转换。任何其他类型都会引发 TypeError 错误:

s = pd.Series([1.1, 2.0, np.nan, 4.0])

s.astype('Int32')
# TypeError: cannot safely cast non-equivalent float64 to int32

4
我遇到了一个错误,提示“TypeError: object cannot be converted to an IntegerDtype”,你有任何想法这是什么意思吗? - Ken
谢谢你指出"I"是大写的。那就是我的问题所在。 - sql_knievel
@Ken,我使用s.astype(float).astype('Int32')解决了这个问题。 - BoomBoxBoy

29

此外,即使在最新版本的pandas中,如果列是 object 类型,您仍需要先将其转换为float,例如:

df['column_name'].astype(np.float).astype("Int32")

注意:由于某些原因,您必须首先通过NumPy浮点类型,然后转为可空Int32。

如果您的变量是32位或64位的,则int的大小取决于它。请注意,如果您的数字过大,则可能会因格式不符而失去一些精度。


最好使用 df['column_name'].astype('float').astype('Int32')。 - Keith

9

我知道这个问题已经有了答案,但是我想为将来的人提供另一种解决方案:

您可以使用.loc仅对notnull()值进行数据框子集,并仅子集出'x'列。取同一个向量,并apply(int)

如果列x是浮点数:

df.loc[df['x'].notnull(), 'x'] = df.loc[df['x'].notnull(), 'x'].apply(int)

左边的部分功能正常,但在数据框中仍然以浮点格式呈现。(Python 3.6,Pandas 0.22) - InLaw

-1
如果您有空值,那么进行数学运算时就会出现错误,为了解决这个问题,请使用以下代码:df[~df['x'].isnull()]df[['x']].astype(int),如果您希望数据集不可更改。

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