将包含 NaN 的 Pandas 列转换为 dtype `int`
- 2024-12-23 08:43:00
- admin 原创
- 83
问题描述:
我将数据从 .csv 文件读取到 Pandas 数据框中,如下所示。对于其中一列,即id
,我想将列类型指定为int
。问题是该id
系列有缺失/空值。
当我尝试id
在读取 .csv 时将列转换为整数时,我得到:
df= pd.read_csv("data.csv", dtype={'id': int})
error: Integer column has NA values
或者,我尝试在阅读以下内容后转换列类型,但这次我得到:
df= pd.read_csv("data.csv")
df[['id']] = df[['id']].astype(int)
error: Cannot convert NA to integer
我该如何解决这个问题?
解决方案 1:
在 0.24.+ 版本中,pandas 已经获得了保存具有缺失值的整数数据类型的能力。
可空整数数据类型。
Pandas 可以使用 表示可能存在缺失值的整数数据arrays.IntegerArray
。这是在 Pandas 中实现的扩展类型。它不是整数的默认数据类型,不会被推断;您必须明确将数据类型传递给array()
或Series
:
arr = pd.array([1, 2, np.nan], dtype=pd.Int64Dtype())
pd.Series(arr)
0 1
1 2
2 NaN
dtype: Int64
要将列转换为可空整数,请使用:
df['myCol'] = df['myCol'].astype('Int64')
解决方案 2:
整数列中缺少 NaN 表示,这是Pandas 的一个“陷阱”。
通常的解决方法就是简单地使用浮点数。
解决方案 3:
我的用例是在将数据加载到数据库表之前对其进行处理:
df[col] = df[col].fillna(-1)
df[col] = df[col].astype(int)
df[col] = df[col].astype(str)
df[col] = df[col].replace('-1', np.nan)
删除 NaN,转换为 int,转换为 str,然后重新插入 NAN。
虽然它不漂亮,但是却能完成工作!
解决方案 4:
无论你的 pandas 系列是object
数据类型还是简单的float
数据类型,下面的方法都可以工作
df = pd.read_csv("data.csv")
df['id'] = df['id'].astype(float).astype('Int64')
解决方案 5:
现在可以创建一个包含 NaN 作为 dtype 的 pandas 列int
,因为它现在已在 pandas 0.24.0 上正式添加
pandas 0.24.x 发布说明
Quote: “ Pandas 已经能够保存具有缺失值的整数数据类型
解决方案 6:
从 Pandas 1.0.0 开始,您现在可以使用 pandas.NA 值。这不会强制将具有缺失值的整数列强制为浮点数。
读取数据时,您只需要做的就是:
df= pd.read_csv("data.csv", dtype={'id': 'Int64'})
请注意,“Int64”被引号包围,并且“I”大写。这将 Panda 的“Int64”与 numpy 的 int64 区分开来。
附注:这也适用于 .astype()
df['id'] = df['id'].astype('Int64')
如果你确实有浮点数,那么可能必须使用圆形。
df['id'] = df['id'].round().astype('Int64')
文档在这里
https://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html
解决方案 7:
几周前,我遇到了一些问题,这些问题涉及几个被格式化为“对象”的离散特征。这个解决方案似乎有效。
for col in discrete:
df[col] = pd.to_numeric(df[col],errors='coerce').astype(pd.Int64Dtype())
解决方案 8:
如果您确实想在一列中组合整数和 NaN,则可以使用“对象”数据类型:
df['col'] = (
df['col'].fillna(0)
.astype(int)
.astype(object)
.where(df['col'].notnull())
)
这将用整数(无论哪个)替换 NaN,转换为 int,转换为对象,最后重新插入 NaN。
解决方案 9:
您可以使用.dropna()
它可以删除具有 NaN 值的行。
df = df.dropna(subset=['id'])
或者,使用.fillna()
和.astype()
将 NaN 替换为值并将其转换为 int。
我在处理包含大整数的 CSV 文件时遇到了这个问题,其中有些整数缺失(NaN)。使用浮点型作为类型不是一个选择,因为我可能会丢失精度。
我的解决方案是使用 str 作为中间类型。然后您可以在代码中根据需要将字符串转换为 int。我用 0 替换了 NaN,但您可以选择任何值。
df = pd.read_csv(filename, dtype={'id':str})
df["id"] = df["id"].fillna("0").astype(int)
为了说明起见,这里有一个浮点数如何失去精度的例子:
s = "12345678901234567890"
f = float(s)
i = int(f)
i2 = int(s)
print (f, i, i2)
输出为:
1.2345678901234567e+19 12345678901234567168 12345678901234567890
解决方案 10:
Int64
与许多其他解决方案一样, 的问题在于,如果您有null
值,它们将被替换为<NA>
不适用于 pandas 默认“NaN”函数(如isnull()
或 )的值fillna()
。或者,如果您将值转换为-1
,最终可能会删除您的信息。我的解决方案有点蹩脚,但会提供int
值np.nan
,让nan
函数在不损害您的值的情况下工作。
def to_int(x):
try:
return int(x)
except:
return np.nan
df[column] = df[column].apply(to_int)
解决方案 11:
如果您可以修改存储的数据,请使用 sentinel value 来表示缺失值id
。一个常见的用例,由列名推断,是id
一个整数,严格大于零,您可以将其用作0
sentinel value,以便您可以编写
if row['id']:
regular_process(row)
else:
special_process(row)
解决方案 12:
这里的大多数解决方案都告诉您如何使用占位符整数来表示空值。但是,如果您不确定整数不会出现在源数据中,则该方法无济于事。我的方法将格式化浮点数而不保留其小数,并将空值转换为 None。结果是一个对象数据类型,当加载到 CSV 中时,它将看起来像一个具有空值的整数字段。
keep_df[col] = keep_df[col].apply(lambda x: None if pandas.isnull(x) else '{0:.0f}'.format(pandas.to_numeric(x)))
解决方案 13:
对于需要在包含 NULL/NaN 的列中包含 int 值,但在无法使用其他答案中提到的 pandas 版本 0.24.0 可空整数功能的限制下工作的任何人,我建议使用 pd.where 将列转换为对象类型:
df = df.where(pd.notnull(df), None)
这会将数据框中的所有 NaN 转换为 None,将混合类型列视为对象,但将 int 值保留为 int,而不是浮点数。
解决方案 14:
如果你想在链接方法时使用它,你可以使用assign:
df = (
df.assign(col = lambda x: x['col'].astype('Int64'))
)
解决方案 15:
首先,您需要指定较新的整数类型 Int8(...Int64),它可以处理空整数数据(pandas 版本 >= 0.24.0)
df = df.astype('Int8')
但您可能只想针对包含 NaN / null 混合的整数数据的特定列:
df = df.astype({'col1':'Int8','col2':'Int8','col3':'Int8')
此时,NaN 被转换为<NA>
,如果您想使用 df.fillna() 更改默认空值,则需要在要更改的列上强制使用对象数据类型,否则您将看到TypeError: <U1 cannot be converted to an IntegerDtype
df = df.astype(object)
如果您不介意将每一列的数据类型更改为对象(单独地,每个值的类型仍然保留),
您可以这样做
...或者df = df.astype({"col1": object,"col2": object})
如果您更喜欢针对单个列。
这应该有助于强制将混有空值的整数列保持为整数格式,并将空值更改为您喜欢的任何值。我无法评价这种方法的效率,但它对我的格式化和打印目的很有效。
解决方案 16:
我在使用 pyspark 时遇到了这个问题。由于这是在 jvm 上运行代码的 python 前端,因此它需要类型安全,并且不能使用 float 而不是 int。我通过将 pandas 包装pd.read_csv
在一个函数中解决了这个问题,该函数将使用用户定义的填充值填充用户定义的列,然后再将它们转换为所需的类型。这是我最终使用的:
def custom_read_csv(file_path, custom_dtype = None, fill_values = None, **kwargs):
if custom_dtype is None:
return pd.read_csv(file_path, **kwargs)
else:
assert 'dtype' not in kwargs.keys()
df = pd.read_csv(file_path, dtype = {}, **kwargs)
for col, typ in custom_dtype.items():
if fill_values is None or col not in fill_values.keys():
fill_val = -1
else:
fill_val = fill_values[col]
df[col] = df[col].fillna(fill_val).astype(typ)
return df
解决方案 17:
import pandas as pd
df= pd.read_csv("data.csv")
df['id'] = pd.to_numeric(df['id'])
解决方案 18:
尝试一下:
df[['id']] = df[['id']].astype(pd.Int64Dtype())
如果你打印它 dtypes
,你将得到 id Int64
而不是正常的 one int64
解决方案 19:
df['id'] = df['id'].astype('float').astype(pd.Int64Dtype())
解决方案 20:
首先删除包含 NaN 的行。然后对剩余的行进行整数转换。最后再次插入删除的行。希望它能起作用
解决方案 21:
使用.fillna()
替换所有NaN
值0
然后将其转换为int
使用astype(int)
df['id'] = df['id'].fillna(0).astype(int)
解决方案 22:
遇到了类似的问题。这是我的解决方案:
def toint(zahl = 1.1):
try:
zahl = int(zahl)
except:
zahl = np.nan
return zahl
print(toint(4.776655), toint(np.nan), toint('test'))
四 南南
df = pd.read_csv("data.csv")
df['id'] = df['id'].astype(float)
df['id'] = toint(df['id'])
解决方案 23:
由于我在这里没有看到答案,所以我不妨添加它:
如果你出于某种原因在依赖旧版本 pandas 的库时仍然无法处理 np.na 或 pd.NA ,则可以使用一行代码将 NAN 转换为空字符串:
df.select_dtypes('number').fillna(-1).astype(str).replace('-1', '')
解决方案 24:
我认为@Digestible1010101的方法更适合 Pandas 1.2.+ 版本,类似这样的方法应该可以完成工作:
df = df.astype({
'col_1': 'Int64',
'col_2': 'Int64',
'col_3': 'Int64',
'col_4': 'Int64', })
解决方案 25:
与@hibernado 的答案类似,但将其保留为整数(而不是字符串)
df[col] = df[col].fillna(-1)
df[col] = df[col].astype(int)
df[col] = np.where(df[col] == -1, np.nan, df[col])
解决方案 26:
df.loc[~df['id'].isna(), 'id'] = df.loc[~df['id'].isna(), 'id'].astype('int')
解决方案 27:
我使用以下解决方法:
condition = (~df['mixed_column'].isnull())
df['mixed_column'] = df['mixed_column'].mask(condition, df[condition]['mixed_column'].astype(int))
解决方案 28:
假设您不需要除相等之外的任何整数运算,则文件读取时的一种解决方法是不推断 dtype 并将所有内容导入为字符串。这效率较低,但简单且更接近 CSV 文件中的实际情况,因为 CSV 文件没有任何类型概念。
pd.read_csv(path, dtype=False)
解决方案 29:
您可以尝试:
df.id = df.id.astype(int, errors = 'ignore')
除了int之外,还可以使用任何数字类型。
解决方案 30:
假设您的 DateColumn 格式为 3312018.0,应转换为字符串 03/31/2018。并且,某些记录缺失或为 0。
df['DateColumn'] = df['DateColumn'].astype(int)
df['DateColumn'] = df['DateColumn'].astype(str)
df['DateColumn'] = df['DateColumn'].apply(lambda x: x.zfill(8))
df.loc[df['DateColumn'] == '00000000','DateColumn'] = '01011980'
df['DateColumn'] = pd.to_datetime(df['DateColumn'], format="%m%d%Y")
df['DateColumn'] = df['DateColumn'].apply(lambda x: x.strftime('%m/%d/%Y'))
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)