有没有办法在午夜过后的秒数记录上加速日期解析器?
Is there a way to accelerate date parser on seconds-past-midnight records?
假设我有以下数据集,在 date_str
列中包含日期 (str
),在 seconds_past_midnight
列中包含午夜后的秒数 (int
)。我想根据这两列的组合来解析日期时间。
import pandas as pd
import numpy as np
n = 1000000
df = pd.DataFrame({'seconds_past_midnight': np.random.randint(34200, 57601, size=n), 'date_str': ['2015-07-14']*n})
print(df)
date_str seconds_past_midnight
0 2015-07-14 48642
1 2015-07-14 39170
2 2015-07-14 43940
3 2015-07-14 46927
4 2015-07-14 55376
5 2015-07-14 35859
6 2015-07-14 38705
7 2015-07-14 35932
8 2015-07-14 36874
9 2015-07-14 39487
... ... ...
999990 2015-07-14 54837
999991 2015-07-14 47146
999992 2015-07-14 54188
999993 2015-07-14 54729
999994 2015-07-14 35574
999995 2015-07-14 35815
999996 2015-07-14 38727
999997 2015-07-14 38374
999998 2015-07-14 53055
999999 2015-07-14 43303
[1000000 rows x 2 columns]
print(df.dtypes)
date_str object
seconds_past_midnight int64
dtype: object
我能想到的最直接的方法是根据这些秒数构造 pd.Timedelta
并将它们添加到日期对象中,但这本质上是使用 [=16= 时的逐行 for 循环] 做转换,这很慢。
%time df.apply(lambda row: pd.to_datetime(row.date_str) + pd.Timedelta(row.seconds_past_midnight, 's'), axis=1)
CPU times: user 2min 5s, sys: 311 ms, total: 2min 5s
Wall time: 2min 5s
所以我想知道是否有办法加速这个过程?也许我不知道 datetime 对象上的一些矢量化函数?我认为稍微提高速度的一种方法是使用 multiprocessing
模块,也许我可以期望在 8 核 PC 上快 4-6 倍。另外,因为我在 apply
中调用 python 函数,cython 或 jit 在这种情况下没有帮助?
您可以解析它 strptime("%Y-%m-%d %f"),%f 在技术上是微秒,不知道这是否有帮助?
dates = pd.to_datetime(df.date_str) + pd.to_timedelta(df.seconds_past_midnight, unit='s')
pd.to_datetime
和 pd.to_timedelta
都已经矢量化了。
In [13]: np.random.seed(1234)
In [14]: df = pd.DataFrame({'seconds_past_midnight': np.random.randint(34200, 57601, size=n), 'date_str': ['2015-07-14']*n})
In [15]: df.head()
Out[15]:
date_str seconds_past_midnight
0 2015-07-14 35518
1 2015-07-14 51248
2 2015-07-14 56721
3 2015-07-14 57417
4 2015-07-14 42671
In [16]: df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 2 columns):
date_str 1000000 non-null object
seconds_past_midnight 1000000 non-null int64
dtypes: int64(1), object(1)
memory usage: 22.9+ MB
In [17]: (pd.to_datetime(df['date_str']) + pd.to_timedelta(df['seconds_past_midnight'],unit='s')).head()
Out[17]:
0 2015-07-14 09:51:58
1 2015-07-14 14:14:08
2 2015-07-14 15:45:21
3 2015-07-14 15:56:57
4 2015-07-14 11:51:11
dtype: datetime64[ns]
In [18]: %timeit pd.to_datetime(df['date_str']) + pd.to_timedelta(df['seconds_past_midnight'],unit='s')
10 loops, best of 3: 187 ms per loop
这是当前的主人,它有一些性能改进。在 0.16.2 中,这慢了 2 倍。
你也可以用NumPy datetime64's and timedelta64's做加法:
(np.array(df['date_str'], '<M8[D]') +
np.array(df['seconds_past_midnight'], dtype='<m8[s]'))
例如,
import pandas as pd
import numpy as np
np.random.seed(1234)
n = 1000000
df = pd.DataFrame({
'seconds_past_midnight': np.random.randint(34200, 57601, size=n),
'date_str': ['2015-07-14']*n})
包括对 DataFrame 的赋值:
In [4]: pd.__version__
Out[6]: u'0.16.2+175.g5a9a9da'
In [7]: %timeit df['date'] = np.array(df['date_str'], '<M8[D]')+np.array(df['seconds_past_midnight'], dtype='<m8[s]')
10 loops, best of 3: 94.6 ms per loop
In [8]: %timeit df['date2'] = pd.to_datetime(df['date_str']) + pd.to_timedelta(df['seconds_past_midnight'],unit='s')
10 loops, best of 3: 188 ms per loop
In [12]: df['date'].equals(df['date2'])
Out[12]: True
(没有分配给DataFrame,datetime64/timedelta64和returns一个NumPy数组,而to_datetime/to_timedelta
和returns一个Pandas系列所以比较这些将是苹果与橘子的比较。)
假设我有以下数据集,在 date_str
列中包含日期 (str
),在 seconds_past_midnight
列中包含午夜后的秒数 (int
)。我想根据这两列的组合来解析日期时间。
import pandas as pd
import numpy as np
n = 1000000
df = pd.DataFrame({'seconds_past_midnight': np.random.randint(34200, 57601, size=n), 'date_str': ['2015-07-14']*n})
print(df)
date_str seconds_past_midnight
0 2015-07-14 48642
1 2015-07-14 39170
2 2015-07-14 43940
3 2015-07-14 46927
4 2015-07-14 55376
5 2015-07-14 35859
6 2015-07-14 38705
7 2015-07-14 35932
8 2015-07-14 36874
9 2015-07-14 39487
... ... ...
999990 2015-07-14 54837
999991 2015-07-14 47146
999992 2015-07-14 54188
999993 2015-07-14 54729
999994 2015-07-14 35574
999995 2015-07-14 35815
999996 2015-07-14 38727
999997 2015-07-14 38374
999998 2015-07-14 53055
999999 2015-07-14 43303
[1000000 rows x 2 columns]
print(df.dtypes)
date_str object
seconds_past_midnight int64
dtype: object
我能想到的最直接的方法是根据这些秒数构造 pd.Timedelta
并将它们添加到日期对象中,但这本质上是使用 [=16= 时的逐行 for 循环] 做转换,这很慢。
%time df.apply(lambda row: pd.to_datetime(row.date_str) + pd.Timedelta(row.seconds_past_midnight, 's'), axis=1)
CPU times: user 2min 5s, sys: 311 ms, total: 2min 5s
Wall time: 2min 5s
所以我想知道是否有办法加速这个过程?也许我不知道 datetime 对象上的一些矢量化函数?我认为稍微提高速度的一种方法是使用 multiprocessing
模块,也许我可以期望在 8 核 PC 上快 4-6 倍。另外,因为我在 apply
中调用 python 函数,cython 或 jit 在这种情况下没有帮助?
您可以解析它 strptime("%Y-%m-%d %f"),%f 在技术上是微秒,不知道这是否有帮助?
dates = pd.to_datetime(df.date_str) + pd.to_timedelta(df.seconds_past_midnight, unit='s')
pd.to_datetime
和 pd.to_timedelta
都已经矢量化了。
In [13]: np.random.seed(1234)
In [14]: df = pd.DataFrame({'seconds_past_midnight': np.random.randint(34200, 57601, size=n), 'date_str': ['2015-07-14']*n})
In [15]: df.head()
Out[15]:
date_str seconds_past_midnight
0 2015-07-14 35518
1 2015-07-14 51248
2 2015-07-14 56721
3 2015-07-14 57417
4 2015-07-14 42671
In [16]: df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 2 columns):
date_str 1000000 non-null object
seconds_past_midnight 1000000 non-null int64
dtypes: int64(1), object(1)
memory usage: 22.9+ MB
In [17]: (pd.to_datetime(df['date_str']) + pd.to_timedelta(df['seconds_past_midnight'],unit='s')).head()
Out[17]:
0 2015-07-14 09:51:58
1 2015-07-14 14:14:08
2 2015-07-14 15:45:21
3 2015-07-14 15:56:57
4 2015-07-14 11:51:11
dtype: datetime64[ns]
In [18]: %timeit pd.to_datetime(df['date_str']) + pd.to_timedelta(df['seconds_past_midnight'],unit='s')
10 loops, best of 3: 187 ms per loop
这是当前的主人,它有一些性能改进。在 0.16.2 中,这慢了 2 倍。
你也可以用NumPy datetime64's and timedelta64's做加法:
(np.array(df['date_str'], '<M8[D]') +
np.array(df['seconds_past_midnight'], dtype='<m8[s]'))
例如,
import pandas as pd
import numpy as np
np.random.seed(1234)
n = 1000000
df = pd.DataFrame({
'seconds_past_midnight': np.random.randint(34200, 57601, size=n),
'date_str': ['2015-07-14']*n})
包括对 DataFrame 的赋值:
In [4]: pd.__version__
Out[6]: u'0.16.2+175.g5a9a9da'
In [7]: %timeit df['date'] = np.array(df['date_str'], '<M8[D]')+np.array(df['seconds_past_midnight'], dtype='<m8[s]')
10 loops, best of 3: 94.6 ms per loop
In [8]: %timeit df['date2'] = pd.to_datetime(df['date_str']) + pd.to_timedelta(df['seconds_past_midnight'],unit='s')
10 loops, best of 3: 188 ms per loop
In [12]: df['date'].equals(df['date2'])
Out[12]: True
(没有分配给DataFrame,datetime64/timedelta64和returns一个NumPy数组,而to_datetime/to_timedelta
和returns一个Pandas系列所以比较这些将是苹果与橘子的比较。)