将包含NaN的Pandas列转换为dtype`int`

时间:2014-01-22 15:51:28

标签: python pandas na

我将.csv文件中的数据读取到Pandas数据帧,如下所示。对于其中一列,即id,我想将列类型指定为int。问题是id系列缺少/空值。

当我尝试在读取.csv时将id列强制转换为整数时,我得到:

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

我该如何解决这个问题?

24 个答案:

答案 0 :(得分:117)

整数列中缺少NaN rep是pandas "gotcha"

通常的解决方法是简单地使用花车。

答案 1 :(得分:24)

我的用例是在加载到数据库表之前重复数据:

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)

删除NaNs,转换为int,转换为str,然后重新插入NAN。

它不漂亮,但它完成了工作!

答案 2 :(得分:15)

在0.24版或更高版本中,pandas具有保留具有缺失值的整数dtypes的功能。

Nullable Integer Data Type

大熊猫可以使用arrays.IntegerArray表示可能缺少值的整数数据。这是在熊猫中实现的扩展类型。它不是整数的默认dtype,因此不会进行推断。您必须将dtype明确传递给array()import React from 'react'; import { createStackNavigator, createAppContainer } from 'react-navigation'; import LoginScreen from './screens/LoginScreen'; import ValidationScreen from './screens/ValidationScreen'; export default createAppContainer( createStackNavigator ( { Login: { screen: LoginScreen}, Validation: { screen: ValidationScreen}, }, { headerMode: 'none' } ));

Series

答案 3 :(得分:3)

如果您可以修改存储的数据,请使用缺少id的标记值。由列名称推断的一个常见用例是id是一个整数,严格大于零,您可以使用0作为标记值,​​以便您可以编写

if row['id']:
   regular_process(row)
else:
   special_process(row)

答案 4 :(得分:2)

如果可以的话,可以使用.dropna()删除带有NaN值的行。

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

或者, 使用.fillna().astype()将NaN替换为值并将其转换为int。

当处理带有大整数的CSV文件时,我遇到了这个问题,而其中的一些整数则丢失了(NaN)。不能选择使用float作为类型,因为这样可能会降低精度。

我的解决方案是使用str作为中间类型。 然后,您可以稍后在代码中将字符串转换为int。我将NaN替换为0,但是您可以选择任何值。

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

答案 5 :(得分:2)

现在可以创建一个包含NaNs作为dtype int的pandas列,因为它已正式添加到pandas 0.24.0中。

pandas 0.24.x release notes Quote:“ Pandas已具备保留具有缺失值的整数dtypes的功能

答案 6 :(得分:2)

对于需要在包含 NULL/NaN 的列中具有 int 值的任何人,但在无法使用其他答案中提到的 Pandas 0.24.0 版可空整数功能的约束下工作,我建议使用将列转换为对象类型pd.where:

df = df.where(pd.notnull(df), None)

这会将数据框中的所有 NaN 转换为 None,将混合类型的列视为对象,但将 int 值保留为 int,而不是 float。

答案 7 :(得分:1)

首先需要指定较新的整数类型,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) 如果您不介意将每个列的数据类型更改为 object(单独地,每个值的类型仍然保留)...或 df = df.astype({"col1": object,"col2": object}) 如果您更喜欢定位单个列。

这应该有助于强制与空值混合的整数列保持整数格式并将空值更改为您喜欢的任何值。我无法评价这种方法的效率,但它适用于我的格式化和打印目的。

答案 8 :(得分:1)

import pandas as pd

df= pd.read_csv("data.csv")
df['id'] = pd.to_numeric(df['id'])

答案 9 :(得分:1)

尝试一下:

df[['id']] = df[['id']].astype(pd.Int64Dtype())

如果打印的是dtypes,则会得到id Int64而不是普通的one int64

答案 10 :(得分:1)

几周前,我遇到了一个问题,它具有一些离散的功能,这些功能被格式化为“对象”。此解决方案似乎有效。

for col in discrete:
df[col] = pd.to_numeric(df[col], errors='coerce').astype(pd.Int64Dtype())

答案 11 :(得分:0)

这里没有看到答案,我不妨补充一下:

One-liner 将 NAN 转换为空字符串,如果您由于某种原因仍然无法像我一样在依赖具有旧版 Pandas 的库时处理 np.na 或 pd.NA:

df.select_dtypes('number').fillna(-1).astype(str).replace('-1', '')

答案 12 :(得分:0)

无论您的熊猫系列是 object 数据类型还是简单的 float 数据类型,以下方法都可以使用

df = pd.read_csv("data.csv") 
df['id'] = df['id'].astype(float).astype('Int64')

答案 13 :(得分:0)

我认为@Digestible1010101 的方法更适合熊猫 1.2.+ 版本,这样的事情应该可以:

y

答案 14 :(得分:0)

遇到了类似的问题。那是我的解决方案:

def toint(zahl = 1.1):
    try:
        zahl = int(zahl)
    except:
        zahl = np.nan
    return zahl

print(toint(4.776655), toint(np.nan), toint('test'))
<块引用>

4 楠楠

df = pd.read_csv("data.csv") 
df['id'] = df['id'].astype(float)
df['id'] = toint(df['id'])

答案 15 :(得分:0)

使用 { "compileOnSave": false, "compilerOptions": { "baseUrl": "./", "outDir": "./dist/out-tsc", "forceConsistentCasingInFileNames": true, "strict": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "sourceMap": true, "declaration": false, "downlevelIteration": true, "experimentalDecorators": true, "moduleResolution": "node", "importHelpers": true, "target": "es2015", "module": "es2020", "lib": [ "es2018", "dom" ] }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, "strictInputAccessModifiers": true, "strictTemplates": true, "strictPropertyInitialization": false } } 将所有 .fillna() 值替换为 NaN,然后使用 0 将其转换为 int

astype(int)

答案 16 :(得分:0)

与许多其他解决方案一样,Int64 的问题在于,如果您有 null 值,它们将被替换为 <NA> 值,这不适用于 Pandas 默认的“NaN”函数,如 isnull()fillna()。或者,如果您将值转换为 -1,您最终可能会删除您的信息。我的解决方案有点蹩脚,但会提供带有 intnp.nan 值,允许 nan 函数在不影响您的值的情况下工作。

            def to_int(x):
                try:
                    return int(x)
                except:
                    return np.nan

            df[column] = df[column].apply(to_int)

答案 17 :(得分:0)

如果要在链接方法时使用它,则可以使用assign:

df = (
     df.assign(col = lambda x: x['col'].astype('Int64'))
)

答案 18 :(得分:0)

从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')

此处的文档 https://pandas.pydata.org/pandas-docs/stable/user_guide/integer_na.html

答案 19 :(得分:0)

使用pd.to_numeric()

df["DateColumn"] = pd.to_numeric(df["DateColumn"])

简单干净

答案 20 :(得分:0)

这里的大多数解决方案都告诉您如何使用占位符整数表示空值。如果您不确定整数不会显示在源数据中,则该方法无济于事。我的方法将格式化不包含其十进制值的浮点数,并将null转换为None。结果是一个对象数据类型,当加载到CSV中时,它将看起来像一个带有空值的整数字段。

keep_df[col] = keep_df[col].apply(lambda x: None if pandas.isnull(x) else '{0:.0f}'.format(pandas.to_numeric(x)))

答案 21 :(得分:0)

如果您绝对想在列中组合整数和NaN,则可以使用“对象”数据类型:

df['col'] = (
    df['col'].fillna(0)
    .astype(int)
    .astype(object)
    .where(df['col'].notnull())
)

这将用整数(无关紧要)替换NaN,转换为int,转换为对象,最后重新插入NaN。

答案 22 :(得分:0)

首先删除包含NaN的行。然后对剩余的行进行整数转换。 最后,再次插入删除的行。 希望它能工作

答案 23 :(得分:0)

假设您的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'))