有没有一种首选方法可以将numpy
数组的数据类型固定为int
(或int64
或其他(,同时仍然将内部元素列为numpy.NaN
?
特别是,我正在将内部数据结构转换为Pandas DataFrame。在我们的结构中,我们有整数类型的列,它们仍然具有 NaN(但列的 dtype 是 int(。如果我们将其设为数据帧,它似乎会将所有内容重新转换为浮点数,但我们真的很想成为int
。
思潮?
尝试过的事情:
我尝试在熊猫下使用from_records()
函数。数据帧,带有coerce_float=False
,这没有帮助。我还尝试使用带有 NaN fill_value 的 NumPy 屏蔽数组,但也没有工作。所有这些都导致列数据类型变为浮点型。
NaN
不能存储在整数数组中。这是目前熊猫的一个已知限制;我一直在等待 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(
此功能已从 0.24 版本添加到 pandas 中。
此时,它需要使用扩展名 dtype 'Int64'
(大写(,而不是默认的 dtype 'int64'
(小写(。
如果您尝试将浮点数 (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
我的用例是我有一个浮点数系列,我想四舍五入为 int,但是当你做 .round(( 仍然有小数时,你需要转换为 int 以删除小数。
如果性能不是主要问题,则可以改为存储字符串。
df.col = df.col.dropna().apply(lambda x: str(int(x)) )
然后你可以随心所欲地与NaN
混合。如果你真的想要整数,根据你的应用程序,你可以使用 -1
、 0
或 1234567890
或其他一些专用值来表示NaN
。
你也可以暂时复制这些列:一个是你所拥有的,带有浮点数;另一个是实验性的,带有整数或字符串。然后在每个合理的位置插入asserts
,检查两者是否同步。经过足够的测试后,您可以放开浮子。
这不是适用于所有情况的解决方案,但我的(基因组坐标(我已经使用 0 作为 NaN
a3['MapInfo'] = a3['MapInfo'].fillna(0).astype(int)
这至少允许使用正确的"本机"列类型,减法、比较等操作按预期工作
熊猫 v0.24+
支持整数序列中NaN
的功能将在 v0.24 及更高版本中提供。v0.24 "新增功能"部分提供了相关信息,可空整数数据类型下提供了更多详细信息。
熊猫 v0.23 及更早
版本通常,最好尽可能使用float
系列,即使由于包含NaN
值而将系列从 int
转换为 float
。这可以实现基于 NumPy 的矢量化计算,否则将处理 Python 级别的循环。
文档确实建议:"一种可能性是改用dtype=object
数组。例如:
s = pd.Series([1, 2, 3, np.nan])
print(s.astype(object))
0 1
1 2
2 3
3 NaN
dtype: object
出于外观原因,例如输出到文件,这可能是可取的。
熊猫 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
熊猫 v1.00 + 的新功能
您不再(也不能(使用numpy.nan
。现在你有pandas.NA
.
请阅读:https://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html
IntegerArray目前处于实验阶段。其 API 或实现可能在没有警告的情况下更改。
在 1.0.0 版更改: 现在使用熊猫。NA 作为缺失值而不是麻皮楠。
在处理缺失数据中,我们看到熊猫主要使用 NaN 来表示缺失的数据。因为 NaN 是一个浮点数,所以这会强制一个数组具有任何缺失值的整数,成为浮点数。在一些在这种情况下,这可能无关紧要。但是,如果您的整数列是,例如,标识符,强制转换为浮点数可能会有问题。一些整数甚至不能表示为浮点数。
如果文本数据中有空白,则通常为整数的列将作为 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
现在这是可能的,因为熊猫 v 0.24.0
熊猫 0.24.x 发行说明引用:">熊猫已经获得了保存具有缺失值的整数dtype的能力。
我知道OP只要求NumPy或Pandas,但我认为值得一提的是极坐标作为支持所请求功能的替代方案。
Polars
整数列中的任何缺失值都只是null
值,并且该列仍然是整数列。
请参阅 极地 - 用户指南> 来自熊猫 了解更多信息。