liu*_*uan 40 python csv python-datetime string-to-datetime pandas
我有这样格式的.csv文件
timestmp, p
2014/12/31 00:31:01:9200, 0.7
2014/12/31 00:31:12:1700, 1.9
...
Run Code Online (Sandbox Code Playgroud)
当读取pd.read_csv并使用时间str转换为datetime时pd.to_datetime,性能会急剧下降.这是一个最小的例子.
import re
import pandas as pd
d = '2014-12-12 01:02:03.0030'
c = re.sub('-', '/', d)
%timeit pd.to_datetime(d)
%timeit pd.to_datetime(c)
%timeit pd.to_datetime(c, format="%Y/%m/%d %H:%M:%S.%f")
Run Code Online (Sandbox Code Playgroud)
而且表现是:
10000 loops, best of 3: 62.4 µs per loop
10000 loops, best of 3: 181 µs per loop
10000 loops, best of 3: 82.9 µs per loop
Run Code Online (Sandbox Code Playgroud)
那么,我怎样才能提高pd.to_datetime从csv文件中读取日期的性能?
jor*_*ris 45
这是因为当pandas dateutil.parser.parse具有非默认格式或没有format提供字符串时(这更灵活,但也更慢),pandas会回退到解析字符串.
如上所示,您可以通过提供format字符串来提高性能to_datetime.或者另一种选择是使用infer_datetime_format=True
显然,infer_datetime_format无法推断何时有微秒.如果没有这些示例,您可以看到大幅加速:
In [28]: d = '2014-12-24 01:02:03'
In [29]: c = re.sub('-', '/', d)
In [30]: s_c = pd.Series([c]*10000)
In [31]: %timeit pd.to_datetime(s_c)
1 loops, best of 3: 1.14 s per loop
In [32]: %timeit pd.to_datetime(s_c, infer_datetime_format=True)
10 loops, best of 3: 105 ms per loop
In [33]: %timeit pd.to_datetime(s_c, format="%Y/%m/%d %H:%M:%S")
10 loops, best of 3: 99.5 ms per loop
Run Code Online (Sandbox Code Playgroud)
这个问题已经得到了足够的答案,但是我想添加一些我正在运行的用于优化自己的代码的测试结果。
我从API中获取了这种格式:“ Wed Feb 08 17:58:56 +0000 2017”。
使用默认值pd.to_datetime(SERIES)和隐式转换,要花费大约一个小时来处理大约2000万行(取决于我有多少可用内存)。
也就是说,我测试了三种不同的转换:
# explicit conversion of essential information only -- parse dt str: concat
def format_datetime_1(dt_series):
def get_split_date(strdt):
split_date = strdt.split()
str_date = split_date[1] + ' ' + split_date[2] + ' ' + split_date[5] + ' ' + split_date[3]
return str_date
dt_series = pd.to_datetime(dt_series.apply(lambda x: get_split_date(x)), format = '%b %d %Y %H:%M:%S')
return dt_series
# explicit conversion of what datetime considers "essential date representation" -- parse dt str: del then join
def format_datetime_2(dt_series):
def get_split_date(strdt):
split_date = strdt.split()
del split_date[4]
str_date = ' '.join(str(s) for s in split_date)
return str_date
dt_series = pd.to_datetime(dt_series.apply(lambda x: get_split_date(x)), format = '%c')
return dt_series
# explicit conversion of what datetime considers "essential date representation" -- parse dt str: concat
def format_datetime_3(dt_series):
def get_split_date(strdt):
split_date = strdt.split()
str_date = split_date[0] + ' ' + split_date[1] + ' ' + split_date[2] + ' ' + split_date[3] + ' ' + split_date[5]
return str_date
dt_series = pd.to_datetime(dt_series.apply(lambda x: get_split_date(x)), format = '%c')
return dt_series
# implicit conversion
def format_datetime_baseline(dt_series):
return pd.to_datetime(dt_series)
Run Code Online (Sandbox Code Playgroud)
结果是:
# sample of 250k rows
dt_series_sample = df['created_at'][:250000]
%timeit format_datetime_1(dt_series_sample) # best of 3: 1.56 s per loop
%timeit format_datetime_2(dt_series_sample) # best of 3: 2.09 s per loop
%timeit format_datetime_3(dt_series_sample) # best of 3: 1.72 s per loop
%timeit format_datetime_baseline(dt_series_sample) # best of 3: 1min 9s per loop
Run Code Online (Sandbox Code Playgroud)
首次测试可显着减少97.7%的运行时间!
令人惊讶的是,看起来即使是“适当的表示形式”也需要更长的时间,可能是因为它是半隐式的。
结论:您越明确,它就会运行得越快。
| 归档时间: |
|
| 查看次数: |
14273 次 |
| 最近记录: |