python - pandas 应用的可能加速

标签 python performance pandas dataframe cython

我定义了两个函数,它们将在我的程序中反复使用:

第一个函数是将字符串转换为日期时间,第二个函数是读取 csv 文件并提取事件发生前的一个值和事件发生后的一个值,并返回事件后的其余数据帧。

def to_timestamp(timestr):
   return datetime.datetime.strptime(timestr,'%H:%M:%S.%f')
def find_values(df,ticker,event_time):
   df=pd.read_csv(ticker+'.csv',sep=',')
   df['Time'] = df['Timestamp'].apply(to_timestamp)
   df_earlier = df[df['Time']<=newstime]
   df_later = df[df['Time']>newstime]
   price_1=df_earlier['Price'].iloc[-1]
   price_2=df_later['Price'].iloc[0]
   return (price_1,Price_2,df_later)

csv 文件具有以下形式:

     Timestamp,       Price 
   04:15:01.274, 35.50
   04:15:01.353, 35.71
   04:15:05.184, 37.37
   05:36:25.240, 37.60
   05:44:40.678, 36.51
   …

这两个函数都可以工作,但是如果我在数千个 csv 文件上使用它们,它们会非常慢。我认为主要的瓶颈是 apply 方法。有什么办法可以加快速度吗?谢谢

最佳答案

def find_values(ticker, event_time):
    filename = ticker+'.csv'
    df = pd.read_csv(filename, parse_dates=[0])
    idx = df['Timestamp'].searchsorted(event_time, side='right')
    price_1, price_2 = df['Price'].iloc[idx-1:idx+1]
    df_later = df.iloc[idx:]
    return price_1, price_2, df_later
<小时/>

例如,使用您发布的数据:

In [176]: p1, p2, df_later = find_values('ABC', pd.Timestamp('4:15:03'))

In [177]: p1, p2
Out[177]: (35.710000000000001, 37.369999999999997)

In [178]: df_later
Out[178]: 
                   Timestamp  Price
2 2015-01-19 04:15:05.184000  37.37
3 2015-01-19 05:36:25.240000  37.60
4 2015-01-19 05:44:40.678000  36.51
<小时/>

如果 csv 很大,解析 csv 的成本可能会很高。因此,你不希望 调用pd.read_csv如果你能帮忙的话,不止一次。推而广之,你 不应调用find_values每个代码多次。如果您确实需要 调用find_values同一股票行情不止一次,需要思考 探讨如何如此理想地重新设计算法 pd.read_csv可以称为 只有一次。缓存 pd.read_csv 返回的值可能是一种方式,或者 收集event_times调用 find_values 一次可能是另一个 方式。

现在假设您已经调用 find_values简单地说,让我们继续讨论如何提高它的速度。

你是对的,使用 apply这也是一个潜在的瓶颈,因为它为数据帧的每一行调用一次 Python 函数。而不是使用 to_timestamp 解析时间字符串,您可以改为使用 pd.read_csv内置的日期字符串解析能力:

df = pd.read_csv(filename, parse_dates=[0])

这会将第 0 个索引列解析为日期字符串。这将使 df['Timestamp'] dtype datetime64[ns] 的列。 这太棒了,因为它可以找到索引 event_time (我认为与 newstime 相同)适合 df['Timestamp']好简单。此外,日期计算在 datetime64 上执行的速度通常比在 Python 上执行的等效计算快得多 datetime.datetime对象。

查找整数索引,其中 event_time适合使用the searchsorted method :

idx = df['Timestamp'].searchsorted(event_time)

idx将是整数索引,其中 event_time如果将其插入 df['Timestamp'] 就会消失同时保持df['Timestamp']的排序。

<小时/>

接下来,请注意使用

df_earlier = df[df['Time']<=newstime]

也很昂贵,因为它形成一个(可能很大的)数据帧只是为了选取一个值。自 df['Time']<=newstime是一个 bool 掩码,这个新数据框 df[df['Time']<=newstime]复制 df 中的数据副本 。这是很多不必要的复制。

相反,您可以使用

price_1, price_2 = df['Price'].iloc[idx-1:idx+1]

只选择您想要的值,无需进行大量额外的复制。

最后,你可以使用

df_later = df.iloc[idx:]

定义df_later 。由于这使用基本切片而不是 bool 掩码,df_later df 的 View 。生成速度比 df[df['Time']>event_time] 更快因为没有复制。但也要注意,这意味着 df_later 中的基础数据df 的底层数据完全相同。因此,修改 df_later还修改 df反之亦然。如果您不想要df_later成为一个 View ,然后使用

df_later = df.iloc[idx:].copy()

关于python - pandas 应用的可能加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28036288/

相关文章:

python - 当先前的值很重要时如何使用 `apply()` 或其他矢量化方法

python - DataFrame.替换为嵌套字典

python - 创建自定义 sys.stdout 类?

Python:从另一个文件的路由内调用类内的函数

sql-server - SQL IF ELSE 性能问题

arrays - 对数组求和比在 Julia 中对单个变量求和要慢

python - 将日期时间索引值转换为索引号

python - 如何将值传递给 Popen.subprocess 内的方法参数?

python - 本地/全局范围

c# - 如何提高 MongoDB 插入性能