问题:NumPy或Pandas:具有NaN值时,将数组类型保持为整数
有没有一种首选的方法来将numpy
数组的数据类型固定为int
(int64
或其他),同时仍将元素内部列出为numpy.NaN
?
特别是,我正在将内部数据结构转换为Pandas DataFrame。在我们的结构中,我们有仍然具有NaN的整数类型的列(但该列的dtype是int)。如果我们将其设为DataFrame,似乎将所有内容重播为浮点数,但我们真的很希望成为int
。
有什么想法吗?
尝试过的事情:
我尝试from_records()
在pandas.DataFrame下使用该功能coerce_float=False
,但这并没有帮助。我还尝试使用带有NaN fill_value的NumPy蒙版数组,该数组也无法正常工作。所有这些导致列数据类型变为浮点型。
回答 0
此功能已添加到熊猫(从0.24版开始):https : //pandas.pydata.org/pandas-docs/version/0.24/whatsnew/v0.24.0.html#optional-integer-na-support
此时,它需要使用扩展名dtype Int64(大写),而不是默认的dtype int64(小写)。
回答 1
NaN
不能存储在整数数组中。目前,这是熊猫的已知限制;我一直在等待NumPy中的NA值(与R中的NA相似)取得进展,但是至少要等6个月到一年的时间,NumPy才能获得这些功能,这似乎是:
http://pandas.pydata.org/pandas-docs/stable/gotchas.html#support-for-integer-na
(此功能是从熊猫0.24版开始添加的,但请注意,它需要使用扩展名dtype Int64(大写),而不是默认的dtype int64(小写):https : //pandas.pydata.org/pandas- docs / version / 0.24 / whatsnew / v0.24.0.html#optional-integer-na-support )
回答 2
如果性能不是主要问题,则可以存储字符串。
df.col = df.col.dropna().apply(lambda x: str(int(x)) )
然后,您可以NaN
根据需要随意混合。如果您确实希望拥有整数,则可以根据您的应用程序使用-1
,或0
,或1234567890
或一些其他专用值来表示NaN
。
您也可以临时复制这些列:一列,有浮点数;另一个是实验型,带有整数或字符串。然后将其插入asserts
每个合理的位置,以检查两者是否同步。经过足够的测试后,您可以放开浮子。
回答 3
这并不是对所有情况都适用的解决方案,但我使用的是(基因座标)(NaO)
a3['MapInfo'] = a3['MapInfo'].fillna(0).astype(int)
这至少允许使用正确的“本机”列类型,如减法,比较等操作均按预期工作
回答 4
熊猫v0.24 +
支持功能 NaN
v0.24或更高版本将提供整数系列。有这些信息在v0.24部分,并在更多的细节“新什么是” 空整数数据类型。
Pandas v0.23及更早版本
通常,最好float
在可能的情况下使用系列,即使该系列是从int
于float
由于包含的NaN
值。这将启用基于矢量的基于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及更早版本:背景
float
:
在没有从根本上将高性能NA支持内置到NumPy中的情况下,主要的受害者是能够以整数数组表示NA。
这种权衡主要是出于内存和性能方面的考虑,并且也使得最终的Series仍然是“数字”。
Typeclass Promotion dtype for storing NAs
floating no change
object no change
integer cast to float64
boolean cast to object
回答 5
现在这是可能的,因为pandas v 0.24.0
pandas 0.24.x发行说明 Quote:“ Pandas已具备保存具有缺失值的整数dtypes的能力。
回答 6
只是想补充一下,以防您尝试将浮点数(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。
回答 7
如果文本数据中有空格,则通常为整数的列将转换为float64 dtype,因为int64 dtype无法处理null。如果您要加载多个文件,其中一些带有空白(最终将以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