对 tz_convert 的 Pandas 应用函数进行向量化

Gau*_*sal 4 python vectorization apply pandas

我有一个数据框,其中hour列包含 UTC 格式的日期时间数据。我有一time_zone列包含每个观察的时区,我使用它转换hour为当地时间并将其保存在名为 的新列中local_hour。为此,我使用以下代码:

import pandas as pd

# Sample dataframe
import pandas as pd
df = pd.DataFrame({
    'hour': ['2019-01-01 05:00:00', '2019-01-01 07:00:00', '2019-01-01 08:00:00'],
    'time_zone': ['US/Eastern', 'US/Central', 'US/Mountain']
})

# Ensure hour is in datetime format and localized to UTC
df['hour'] = pd.to_datetime(df['hour']).dt.tz_localize('UTC')

# Add local_hour column with hour in local time 
df['local_hour'] = df.apply(lambda row: row['hour'].tz_convert(row['time_zone']), axis=1)

df
    hour                        time_zone   local_hour
0   2019-01-01 05:00:00+00:00   US/Eastern  2019-01-01 00:00:00-05:00
1   2019-01-01 07:00:00+00:00   US/Central  2019-01-01 01:00:00-06:00
2   2019-01-01 08:00:00+00:00   US/Mountain 2019-01-01 01:00:00-07:00
Run Code Online (Sandbox Code Playgroud)

该代码有效。然而,使用apply运行速度相当慢,因为实际上我有一个很大的数据框。有没有办法对其进行矢量化或以其他方式加速?

注意:我尝试过使用该swifter软件包,但就我而言,它并没有加快速度。

Ben*_*n.T 5

假设没有无限数量的 time_zone,也许您可​​以执行tz_convert每个组,例如:

\n\n
df['local_hour'] = df.groupby('time_zone')['hour'].apply(lambda x: x.dt.tz_convert(x.name))\nprint (df)\n\n                       hour    time_zone                 local_hour\n0 2019-01-01 05:00:00+00:00   US/Eastern  2019-01-01 00:00:00-05:00\n1 2019-01-01 07:00:00+00:00   US/Central  2019-01-01 01:00:00-06:00\n2 2019-01-01 08:00:00+00:00  US/Mountain  2019-01-01 01:00:00-07:00\n
Run Code Online (Sandbox Code Playgroud)\n\n

在示例中,它可能会比您所做的慢,但在更大的数据和组上,应该更快

\n\n

为了进行速度比较,使用df您提供的 3 行,它给出:

\n\n
%timeit df.apply(lambda row: row['hour'].tz_convert(row['time_zone']), axis=1)\n# 1.6 ms \xc2\xb1 102 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000 loops each)\n\n%timeit df.groupby('time_zone')['hour'].apply(lambda x: x.dt.tz_convert(x.name))\n# 2.58 ms \xc2\xb1 126 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n\n

soapply更快,但是如果你创建一个大 1000 倍但只有 3 个 time_zones 的数据帧,那么你的 groupby 速度大约快 20 倍:

\n\n
df = pd.concat([df]*1000, ignore_index=True)\n\n%timeit df.apply(lambda row: row['hour'].tz_convert(row['time_zone']), axis=1)\n# 585 ms \xc2\xb1 42.1 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 1 loop each)\n\n%timeit df.groupby('time_zone')['hour'].apply(lambda x: x.dt.tz_convert(x.name))\n# 27.5 ms \xc2\xb1 2.15 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

  • 将 2.5M 行 df 上的操作从 260 秒加速到 23 秒! (2认同)