繁体   English   中英

如何将 Pandas 字符串列转换为新的可为空的 Int64 类型?

[英]How can I cast a Pandas string column to the new nullable Int64 type?

我正在尝试将 Pandas DataFrame 中的字符串列转换为数字列。

我使用以下数据帧:

import pandas as pd
import numpy as np

d = {'col1': ['1', '2'], 'col2': ['5', str(np.nan)], 'col3': [99, str(pd.NA)]}
df = pd.DataFrame(d)
print(df)
 col1 col2 col3 0 1 5 99 1 2 nan <NA>

现在,当我将col1从转换为int并将col2float ,它工作正常:

print(df.col1.astype(int))
print(df.col2.astype(float))
 0 1 1 2 Name: col1, dtype: int64 0 5.0 1 NaN Name: col2, dtype: float64

但是当我尝试将col3strInt64 ,出现以下错误:

df.col3.astype(pd.Int64Dtype())

TypeError: object cannot be converted to an IntegerDtype

这是故意的吗?

我怎样才能克服这个限制?

编辑:我编辑了示例数据以使意图更清晰。

更新

您的示例数据的col3列具有整数99pd.NA的字符串表示pd.NA ,但您的问题标题询问字符串列。 所以,以防万一你的意思是col3有一个字符串'99'pd.NA的字符串表示,例如

In [124]: s1 = pd.Series(['99', str(pd.NA)])

In [125]: s1
Out[125]:
0      99
1    <NA>
dtype: object

In [126]: s1.map(type)
Out[126]:
0    <class 'str'>
1    <class 'str'>
dtype: object

在这种情况下,pandas 不允许使用astype将其直接转换为Int64 您需要将pd.to_numeric'coerce'一起使用并转换为Int64

In [130]: s = pd.to_numeric(s1, errors='coerce').astype('Int64')

In [131]: s
Out[131]:
0      99
1    <NA>
dtype: Int64

In [132]: s.map(type)
Out[132]:
0                            <class 'int'>
1    <class 'pandas._libs.missing.NAType'>
dtype: object

原文

在 pandas 1.0.0+ 中,引入了pd.NA来表示可为空的整数和布尔数据类型以及新的字符串数据类型的缺失值。 当您在pd.NA上调用str (即您在col3数据帧构造函数中调用str(pd.NA) )时,它返回其字符串表示。 它的字符串表示是字符串<NA>

In [84]: pd.NA.__str__()
Out[84]: '<NA>'

它与您在np.nan上调用str np.nan ,它的字符串表示是字符串nan

In [86]: np.nan.__str__()
Out[86]: 'nan'

因此, col3实际上没有pd.NA 它只包含一个整数99和一个pd.NA的字符串表示(即它只是一个普通的字符串<NA> )。 您想将字符串<NA>转换为可为空的整数类型Int64pd.Int64Dtype()的别名),因此它会出错。

解决方案

您需要将此纯字符串<NA>替换为真正的pd.NA并转换为Int64

s = df.col3.replace('<NA>', pd.NA).astype('Int64')

Out[57]:
0      99
1    <NA>
Name: col3, dtype: Int64

细节:

col3<NA>显然只是一个普通的字符串

In [64]: df.loc[1, 'col3']
Out[64]: '<NA>'

In [65]: type(df.loc[1, 'col3'])
Out[65]: str

pd.NA替换它并pd.NAInt64 ,它是真正的pd.NA

In [66]: s = df.col3.replace('<NA>', pd.NA).astype('Int64')

In [68]: s[1]
Out[68]: <NA>

In [69]: type(s[1])
Out[69]: pandas._libs.missing.NAType

pandas DataFrame 带有许多有用的属性。 在处理数字数据类型时, pandas.to_numericpandas.to_numeric脱颖而出,具有很大的灵活性和简单的语法。

import pandas as pd
import numpy as np

d  = {'col1': ['1', '2'], 'col2': ['5', str(np.nan)], 'col3': [99, str(pd.NA)]}
df = pd.DataFrame(d)

1. 基本语法

to_numeric需要一1-d arraytupleSeries

print(pd.Series(df['col1']))
# 0    1
# 1    2
# Name: col1, dtype: int64

2. 错误控制

在处理任意数据时,编写涉及数据类型转换的可靠脚本时,所需的错误处理可能会重复,这由to_numeric提供

# Looking at data
print(df['col3'].to_string())
# 0      99
# 1    <NA>
# Name: col3, dtype: object

# This line creates error
df['col3'].astype(pd.Int64Dtype())

一种。 忽略错误

这会将所有可能的值转换为numeric ,任何不可转换的值将返回input

pd.to_numeric(df['col3'], errors='ignore')
# 0      99
# 1    <NA>
# Name: col3, dtype: object

print(pd.to_numeric([1, 2, 3, 'abc'], errors='ignore'))
# array([1, 2, 3, 'abc'], dtype=object)

强制错误

将所有可能的值转换为numeric ,任何不可转换的值将作为nan返回,即( numpy.nan

pd.to_numeric(df['col3'], errors='coerce')
# 0      99
# 1     NaN
# Name: col3, dtype: object

print(pd.to_numeric([1, 2, 3, 'abc'], errors='coerce'))
# array([1, 2, 3, nan])

C。 引发错误

转换所有可能的值并在遇到任何不可转换的值时raise错误。

pd.to_numeric(df['col3'], errors='raise')
# ValueError: Unable to parse string "<NA>" at position 1

print(pd.to_numeric([1, 2, 3, 'abc'], errors='raise'))
# ValueError: Unable to parse string "abc" at position 3

3.向下转换数据类型

根据规则(根据文档),它将转换为最小的数据类型

  • 'integer' 或 'signed':最小的有符号 int dtype(最小值:np.int8)
  • 'unsigned':最小的 unsigned int dtype(最小值:np.uint8)
  • 'float': 最小的 float dtype (min.: np.float32)

如果requested类型大小大于input ,则不进行downcasting

# With a = ['1', '2.0', '-3', 4]

pd.to_numeric(a, downcast='integer')
# array([ 1,  2, -3,  4], dtype=int8)

pd.to_numeric(a, downcast='float')
# array([ 1.,  2., -3.,  4.], dtype=float32)

对于你的情况,你会做

pd.to_numeric(df['col3'], errors='coerce').astype(pd.Int64Dtype())

请注意, errors='coerce'返回一个具有float数据类型的系列。 可以使用astype数据astype属性进行转换,因为它是数字数据类型。

实际上浮点数据类型可以包含 NaN 但整数值会抛出错误,如果您的 Pandas 版本低于 v0.24 但从 v0.24 可以包含 NaN 所以你可以尝试

df.col3.astype(pd.Int64Dtype())

或者你可以用一些特定的 no 替换 NaN,然后​​转换为整数

df.col3.fillna(-1).astype('Int64')

您可以使用对象。

df['col3']=df['col3'].astype(object)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM