将 pandas.Series 从 dtype 对象转换为浮点数,将错误转换为 nans
Posted
技术标签:
【中文标题】将 pandas.Series 从 dtype 对象转换为浮点数,将错误转换为 nans【英文标题】:Convert pandas.Series from dtype object to float, and errors to nans 【发布时间】:2014-11-15 03:53:57 【问题描述】:考虑以下情况:
In [2]: a = pd.Series([1,2,3,4,'.'])
In [3]: a
Out[3]:
0 1
1 2
2 3
3 4
4 .
dtype: object
In [8]: a.astype('float64', raise_on_error = False)
Out[8]:
0 1
1 2
2 3
3 4
4 .
dtype: object
我本来期望一个选项,允许转换而转向错误的值(如.
)至NaN
秒。有没有办法做到这一点?
【问题讨论】:
【参考方案1】:In [30]: pd.Series([1,2,3,4,'.']).convert_objects(convert_numeric=True)
Out[30]:
0 1
1 2
2 3
3 4
4 NaN
dtype: float64
【讨论】:
我想我前一阵子把raise_on_error
的功能拿出来了。不做任何事情。
我在这里打开了一个问题进行改进:github.com/pydata/pandas/issues/8332,请随时对提议的 API 发表评论
在 0.14.1 上,它阻止它抛出异常。如果不指定它,astype
语句会引发错误。
对不起,你是对的。这就是为什么永远不要只阅读代码,测试它:)
.convert_objects()
方法自 0.17 起已被弃用,pd.to_numeric
是新的方法。【参考方案2】:
使用pd.to_numeric
和errors='coerce'
# Setup
s = pd.Series(['1', '2', '3', '4', '.'])
s
0 1
1 2
2 3
3 4
4 .
dtype: object
pd.to_numeric(s, errors='coerce')
0 1.0
1 2.0
2 3.0
3 4.0
4 NaN
dtype: float64
如果您需要填写NaN
s,请使用Series.fillna
。
pd.to_numeric(s, errors='coerce').fillna(0, downcast='infer')
0 1
1 2
2 3
3 4
4 0
dtype: float64
注意,downcast='infer'
将尽可能将浮点数向下转换为整数。如果您不希望这样,请删除该参数。
从 v0.24+ 开始,pandas 引入了 Nullable Integer 类型,它允许 整数与 NaN 共存。如果您的列中有整数, 你可以使用
pd.__version__ # '0.24.1' pd.to_numeric(s, errors='coerce').astype('Int32') 0 1 1 2 2 3 3 4 4 NaN dtype: Int32
还有其他选项可供选择,请阅读文档了解更多信息。
DataFrames
的扩展名
如果您需要将此扩展到 DataFrames,则需要将其应用到每一行。您可以使用DataFrame.apply
执行此操作。
# Setup.
np.random.seed(0)
df = pd.DataFrame(
'A' : np.random.choice(10, 5),
'C' : np.random.choice(10, 5),
'B' : ['1', '###', '...', 50, '234'],
'D' : ['23', '1', '...', '268', '$$']
)[list('ABCD')]
df
A B C D
0 5 1 9 23
1 0 ### 3 1
2 3 ... 5 ...
3 3 50 2 268
4 7 234 4 $$
df.dtypes
A int64
B object
C int64
D object
dtype: object
df2 = df.apply(pd.to_numeric, errors='coerce')
df2
A B C D
0 5 1.0 9 23.0
1 0 NaN 3 1.0
2 3 NaN 5 NaN
3 3 50.0 2 268.0
4 7 234.0 4 NaN
df2.dtypes
A int64
B float64
C int64
D float64
dtype: object
您也可以使用DataFrame.transform
执行此操作;虽然我的测试表明这有点慢:
df.transform(pd.to_numeric, errors='coerce')
A B C D
0 5 1.0 9 23.0
1 0 NaN 3 1.0
2 3 NaN 5 NaN
3 3 50.0 2 268.0
4 7 234.0 4 NaN
如果您有很多列(数字;非数字),您可以通过仅在非数字列上应用 pd.to_numeric
来提高性能。
df.dtypes.eq(object)
A False
B True
C False
D True
dtype: bool
cols = df.columns[df.dtypes.eq(object)]
# Actually, `cols` can be any list of columns you need to convert.
cols
# Index(['B', 'D'], dtype='object')
df[cols] = df[cols].apply(pd.to_numeric, errors='coerce')
# Alternatively,
# for c in cols:
# df[c] = pd.to_numeric(df[c], errors='coerce')
df
A B C D
0 5 1.0 9 23.0
1 0 NaN 3 1.0
2 3 NaN 5 NaN
3 3 50.0 2 268.0
4 7 234.0 4 NaN
沿列应用pd.to_numeric
(即axis=0
,默认值)对于长数据帧应该稍微快一些。
【讨论】:
这太棒了:-),我们应该保持更新,因为在这个网站上弃用的方法对未来的访问者不利:-),你做到了 啊哈,也许你可以添加s.str.isalnum()
:-) 结合mask
@Wen 你的意思是s.str.isdigit()
?它仅适用于整数,不适用于浮点数。好主意。
@Wen 据我所知to_numeric
在这里是黄金。
@Dark 啊哈,是的 :-)以上是关于将 pandas.Series 从 dtype 对象转换为浮点数,将错误转换为 nans的主要内容,如果未能解决你的问题,请参考以下文章