【问题标题】:How to speedup pd.read_csv datetime parsing?如何加快 pd.read_csv 日期时间解析?
【发布时间】:2019-09-11 19:38:16
【问题描述】:

我有一个 csv (sep=' ') 文件,它每天都会更新 1000 行。

YYYY-MM-DD-HH-MM-SS col1 col2 col3 col4 col5

它的行可以追溯到 2015 年。它是按日期时间排序的。 我真的只有今天的数据。

这是我使用的代码:

dprsf = lambda dtstr: datetime.datetime.strptime(dtstr, "%Y-%m-%d-%H-%M-%S")
dfigfut = pd.read_csv(fpath, sep=' ', header=None, names=('DateTime', 'col1', 'col2', 'col3', 'col1', 'col5'), parse_dates=[0], date_parser=dprsf, index_col=0)
dfigfut = dfigfut[starttime:endtime]

这需要大量解析不需要的行以丢弃它们。我怀疑大部分收益都来自于此。 接下来,可以加速解析器吗?

谢谢

【问题讨论】:

  • 使用该字符串格式,您不需要 lambda 调用。
  • 你试过pd.read_csv(fpath, ...., skiprows=N)N是前一天数据集最后一行的索引
  • 不幸的是,行数是可变的。我只知道解析日期时间后是否需要一行。需要今天的行。
  • 冻糕,推断没有用。有什么选择?
  • 如果您真的只关心前一天的数据,并且行数是可变的,您是否可以:a) 在某个数据库中读取的总行数? (您可以第一次手动计算文件中的行数并从那里开始)或b)如果您不能做a),只需假设并从2019年开始读取文件?

标签: pandas


【解决方案1】:

在日期时间格式和排序数据的特定情况下,您可以将DateTime 列作为字符串读取,对字符串进行过滤,然后才将过滤后的数据转换为日期时间。这提供了大约 10 倍的加速:

import pandas as pd
import numpy as np
import datetime
import timeit
import io

# prepare test data
fpath = 'so57877843.csv'
df = pd.DataFrame(pd.date_range('01-01-2015', '09-12-2019', freq='H'))
df = pd.concat([df, pd.DataFrame(np.random.rand(len(df),5))], axis=1)
df.columns = ['DateTime', 'col1', 'col2', 'col3', 'col4', 'col5']
df.to_csv(fpath, sep = ' ', header=None, date_format = "%Y-%m-%d-%H-%M-%S", index=False)

# test setup
today = datetime.datetime.now()
today = today.replace(hour=0, minute=0, second=0, microsecond=0)
with open(fpath) as f:
    csv = f.read()  # eliminate disk IO time

def read_date():
   dprsf = lambda dtstr: datetime.datetime.strptime(dtstr, "%Y-%m-%d-%H-%M-%S")
   dfigfut = pd.read_csv(io.StringIO(csv), sep=' ', header=None, names=('DateTime', 'col1', 'col2', 'col3', 'col4', 'col5'), parse_dates=[0], date_parser=dprsf, index_col=0)
   dfigfut = dfigfut[dfigfut.index >= today]
   return dfigfut

def read_str():
   dfigfut1 = pd.read_csv(io.StringIO(csv), sep=' ', header=None, names=('DateTime', 'col1', 'col2', 'col3', 'col4', 'col5'), index_col=0)
   dfigfut1 = dfigfut1[dfigfut1.index >= today.strftime("%Y-%m-%d")]
   dfigfut1.index = pd.to_datetime(dfigfut1.index, format="%Y-%m-%d-%H-%M-%S")
   return dfigfut1

print(timeit.timeit('read_date()', globals=globals(), number = 10))
print(timeit.timeit('read_str()', globals=globals(), number = 10))

assert(all(read_date() == read_str()))

输出(在我的机器上):

10.330610644
1.0750362959999986

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-07
    • 2014-01-29
    • 1970-01-01
    • 2010-10-27
    • 2023-03-06
    • 1970-01-01
    • 2013-02-04
    • 2015-07-22
    相关资源
    最近更新 更多