如何在不知道 NA 值模式的情况下快速将列转换为数字
Posted
技术标签:
【中文标题】如何在不知道 NA 值模式的情况下快速将列转换为数字【英文标题】:How to convert columns to number quickly without know the NA value patterns 【发布时间】:2015-09-12 20:07:52 【问题描述】:我有许多列标题相同的 CSV 文件要解析。在这些文件中,可能有几种模式来表示 NA,例如:“-”、“--”、“/”、...
我不知道所有的模式,所以我无法为read_csv()
正确设置na_values
参数。
是否有任何快速方法可以在这些文件中找到所有 NA 模式,或者在不知道所有模式的情况下,我仍然可以将所有列转换为数字?这是我尝试过的:
patterns = set()
for i, fn in enumerate(glob(u"data/*.csv")):
df = pd.read_csv(fn, encoding="utf-8-sig", usecols=cols, dtype=str, keep_default_na=False)
df_num = df.convert_objects(convert_numeric=True)
patterns.update( df[df_num.isnull()].stack().value_counts().index )
但是convert_objects()
很慢。这是一些测试:
read_csv(dtype=str)
:大约2.2s
read_csv()
没有 dtype
参数:大约 2.5 秒
read_csv(dtype=str)
+ convert_objects()
: 8.4s
所以,read_csv()
可以比convert_objects()
更快地将字符串转换为数字。但是如果有一个元素不能转成数字,整列就会变成字符串列。
有没有更快的方法可以在不设置na_values
参数的情况下将所有列转换为数字?
【问题讨论】:
您能不能将NaN
的所有已知可能值传递给na_values
?否则,我认为您会坚持使用当前的方法
numpy 的 .astype(float) 更快吗?
【参考方案1】:
为什么不直接将“index_col”参数设置为 False。我相信这将导致熊猫从零开始按顺序对您的列进行编号。以下是您的代码在更改后的样子:
patterns = set()
for i, fn in enumerate(glob(u"data/*.csv")):
df = pd.read_csv(fn, encoding="utf-8-sig", index_col=False, usecols=cols, dtype=str, keep_default_na=False)
df_num = df.convert_objects(convert_numeric=True)
patterns.update( df[df_num.isnull()].stack().value_counts().index )
【讨论】:
我不完全确定,但是当使用 index_col=False 时,您可能不再需要 usecols=cols。【参考方案2】:如果您有 pandas 版本 >= 0.17.0
,您可以尝试为每一列应用 pandas.to_numeric
(或者您可能知道可疑列):
import pandas as pd
df = pd.DataFrame('a':[1, 2, 3, 4, 'b', 'a', 6], 'b':[0, 1, 2, 'a', 3, 4, 'b'], dtype=str)
一些基准测试:
In [78]: %timeit df.convert_objects(convert_numeric=True)
1000 loops, best of 3: 480 µs per loop
In [79]: %timeit df.apply(pd.to_numeric, errors='coerce')
1000 loops, best of 3: 880 µs per loop
我们可以看到它比 convert_object 慢。让我们将raw=True
传递给apply
:
In [82]: %timeit df.apply(pd.to_numeric, raw=True, errors='coerce')
1000 loops, best of 3: 288 µs per loop
现在它的速度几乎是convert_objects
的 2 倍。
【讨论】:
以上是关于如何在不知道 NA 值模式的情况下快速将列转换为数字的主要内容,如果未能解决你的问题,请参考以下文章
INSERT IF NOT EXISTS 类型函数供我在不将列转换为主键的情况下使用?
如何在不生成 SettingWithCopyWarning 的情况下将列插入 DataFrame