198

是否有一种首选方法可以将numpy数组的数据类型固定为intint64或其他),同时仍将内部元素列为numpy.NaN

特别是,我正在将内部数据结构转换为 Pandas DataFrame。在我们的结构中,我们有仍然有 NaN 的整数类型列(但列的 dtype 是 int)。如果我们将其设为 DataFrame,似乎会将所有内容重铸为浮点数,但我们真的很想成为int.

想法?

尝试的事情:

我尝试使用from_records()pandas.DataFrame 下的函数,coerce_float=False但这并没有帮助。我还尝试使用 NumPy 掩码数组和 NaN fill_value,这也不起作用。所有这些都导致列数据类型变为浮点数。

4

9 回答 9

111

NaN不能存储在整数数组中。这是目前 pandas 的一个已知限制;我一直在等待 NumPy 中的 NA 值(类似于 R 中的 NA)取得进展,但 NumPy 获得这些功能至少需要 6 个月到一年,看来:

http://pandas.pydata.org/pandas-docs/stable/gotchas.html#support-for-integer-na

(此功能已从 pandas 0.24 版本开始添加,但请注意,它需要使用扩展 dtype Int64(大写),而不是默认的 dtype int64(小写): https ://pandas.pydata.org/pandas- docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na-support

于 2012-07-18T18:43:27.740 回答
100

此功能已添加到 pandas(从版本 0.24 开始): https ://pandas.pydata.org/pandas-docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na-support

此时,它需要使用扩展 dtype Int64(大写),而不是默认的 dtype int64(小写)。

于 2018-08-24T03:36:20.830 回答
8

如果性能不是主要问题,您可以改为存储字符串。

df.col = df.col.dropna().apply(lambda x: str(int(x)) )

然后你可以NaN随心所欲地混合。如果您真的想要整数,根据您的应用程序,您可以使用-1, 或0, or1234567890或其他一些专用值来表示NaN.

您还可以临时复制列:一个像您一样,带有浮动;另一个是实验性的,带有整数或字符串。然后在每个合理的地方插入asserts,检查两者是否同步。经过足够的测试后,您可以放开浮动。

于 2014-12-08T23:40:59.973 回答
8

这不是适用于所有情况的解决方案,但我的(基因组坐标)我已经使用 0 作为 NaN

a3['MapInfo'] = a3['MapInfo'].fillna(0).astype(int)

这至少允许使用正确的“本机”列类型,减法、比较等操作按预期工作

于 2018-01-12T13:08:53.080 回答
6

熊猫 v0.24+

支持NaN整数系列的功能将在 v0.24 及更高版本中可用。v0.24“新增功能”部分中有相关信息,可空整数数据类型下有更多详细信息

Pandas v0.23 及更早版本

一般来说,最好float尽可能使用系列,即使系列由于包含值而被向上int转换。这启用了基于向量化 NumPy 的计算,否则将处理 Python 级循环。floatNaN

文档确实建议:“一种可能性是改用dtype=object数组。” 例如:

s = pd.Series([1, 2, 3, np.nan])

print(s.astype(object))

0      1
1      2
2      3
3    NaN
dtype: object

出于美观的原因,例如输出到文件,这可能是更可取的。

Pandas v0.23 及更早版本:背景

NaN被认为是一个float当前(从 v0.23 开始)的文档指定了整数系列向上转换为的原因float

由于 NumPy 没有从头开始构建高性能 NA 支持,因此主要的损失是在整数数组中表示 NA 的能力。

这种权衡主要是出于内存和性能的原因,而且结果系列仍然是“数字的”。

由于包含,文档还提供了向上转换的规则NaN

Typeclass   Promotion dtype for storing NAs
floating    no change
object      no change
integer     cast to float64
boolean     cast to object
于 2018-12-19T14:31:10.853 回答
2

熊猫新版 v1.00 +

您不再(也不能)使用numpy.nan任何东西。现在你有pandas.NA.

请阅读:https ://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html

IntegerArray 目前是实验性的。它的 API 或实现可能会在没有警告的情况下更改。

在 1.0.0 版更改: 现在使用 pandas.NA 作为缺失值而不是 numpy.nan。

在处理缺失数据中,我们看到 pandas 主要使用 NaN 来表示缺失数据。因为 NaN 是浮点数,这会强制具有任何缺失值的整数数组变为浮点数。在某些情况下,这可能无关紧要。但是,如果您的整数列是一个标识符,那么转换为浮点数可能会出现问题。有些整数甚至不能表示为浮点数。

于 2021-04-26T16:35:03.263 回答
1

这现在是可能的,因为 pandas v 0.24.0

pandas 0.24.x 发行说明 引用:“ Pandas 已经获得了保存具有缺失值的整数 dtype 的能力。

于 2019-01-25T17:08:08.700 回答
1

只是想补充一点,如果您尝试将浮点 (1.143) 向量转换为整数 (1),而 NA 转换为新的 'Int64' dtype 会给您一个错误。为了解决这个问题,您必须对数字进行四舍五入,然后执行“.astype('Int64')”

s1 = pd.Series([1.434, 2.343, np.nan])
#without round() the next line returns an error 
s1.astype('Int64')
#cannot safely cast non-equivalent float64 to int64
##with round() it works
s1.round().astype('Int64')
0      1
1      2
2    NaN
dtype: Int64

我的用例是我有一个浮点数系列,我想四舍五入到整数,但是当你做 .round() 时,数字末尾的 '*.0' 仍然存在,所以你可以从最后删除那个 0转换为 int。

于 2019-07-01T18:53:35.920 回答
1

如果文本数据中有空格,通常为整数的列将作为 float64 dtype 转换为浮点数,因为 int64 dtype 无法处理空值。如果您正在加载多个带有空格的文件(最终会以 float64 结尾,而没有空格的其他文件将以 int64 结尾),这可能会导致架构不一致

此代码将尝试将任何数字类型列转换为 Int64(而不是 int64),因为 Int64 可以处理空值

import pandas as pd
import numpy as np

#show datatypes before transformation
mydf.dtypes

for c in mydf.select_dtypes(np.number).columns:
    try:
        mydf[c] = mydf[c].astype('Int64')
        print('casted {} as Int64'.format(c))
    except:
        print('could not cast {} to Int64'.format(c))

#show datatypes after transformation
mydf.dtypes
于 2020-06-17T14:33:46.417 回答