使用Pandas大规模识别和更改数据类型的有效方法

cigdeys3  于 2023-05-21  发布在  其他
关注(0)|答案(2)|浏览(117)

我发现了一种方法来识别数据框中的日期时间列,然后对它们全部应用strftime格式。然而,我正试图扩大我的技能与Pandas和远离使用申请,所以答案更有效将是伟大的!下面是一些示例代码。。

import pandas as pd

# Create df
test_tz_df = pd.DataFrame(
    {
        'With tz' : [(pd.to_datetime('today') - pd.DateOffset(days=1)).tz_localize(tz='America/Los_Angeles').tz_localize(None)]*2,
        'Without tz' : [(pd.to_datetime('today') - pd.DateOffset(days=1))]*2,
        'strings' : ['string a','string b']
    }
)

# Find the dt columns to edit
datetime_cols = test_tz_df.select_dtypes(include=["datetime64[ns]"]).columns.to_list()

# apply() strftime() formatting
test_tz_df[datetime_cols] = test_tz_df[datetime_cols].apply(lambda x : x.dt.strftime('%Y-%m-%d %H:%M:%S'))
a64a0gku

a64a0gku1#

我发现.at[].apply().iteritems().loc[]更快
下面是一个带有timeit结果的示例实现:

#define functions to test
def use_apply(df):
  df = df.apply(lambda x : x.dt.strftime('%Y-%m-%d %H:%M:%S'))
  return df

def use_loc(df):
  d = {c:[] for c in df.columns}
  for c in df.columns:
    s = df[c]
    for i in range(len(s)):
      d[c].append(s.at[i].strftime('%Y-%m-%d %H:%M:%S'))
  return pd.DataFrame(d)

#set up dataframe
t_df = pd.DataFrame(
    {
        'With_tz' : [(pd.to_datetime('today') - pd.DateOffset(days=1)).tz_localize(tz='America/Los_Angeles').tz_localize(None)]*2,
        'Without_tz' : [(pd.to_datetime('today') - pd.DateOffset(days=2))]*2
    }
)

#timeit
print("With apply: ", timeit.timeit(lambda: use_apply(t_df), number=1000))
print("With .at: ", timeit.timeit(lambda: use_loc(t_df), number=1000))

结果:使用:0.989
与.at:0.357
这是一个相当显著的时间优势,尽管两个循环看起来很荒谬。
(You我会注意到我跳过了问题中标识日期时间列的部分;我看不出有什么办法可以改善这一点)。

myss37ts

myss37ts2#

apply()没有利用即时加载,这意味着随着数据的增长,执行时间也会增长
你是对的,但不是在你现在的情况下:

datetime_cols = test_tz_df.select_dtypes(include=["datetime64[ns]"]).columns.to_list()

for i in np.logspace(1, 7, 7, dtype=int):
    df1 = test_tz_df.reindex(test_tz_df.index.repeat(i))
    print(f'For {len(df1):,} records')
    %timeit test_tz_df[datetime_cols].apply(lambda x : x.dt.strftime('%Y-%m-%d %H:%M:%S'))

输出:

For 20 records
1.04 ms ± 16.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

For 200 records
1.01 ms ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

For 2,000 records
997 µs ± 11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

For 20,000 records
1.03 ms ± 16.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

For 200,000 records
1.02 ms ± 9.58 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

For 2,000,000 records
1.02 ms ± 12.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

For 20,000,000 records
1.03 ms ± 20.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

您只在两列上创建了一个“循环”,因此在这里寻找apply的替代方案是不相关的。

相关问题