2016-07-05 72 views
4

我有日期和值的数据帧,加快熊猫据帧迭代

Date  Price 
Jun 30 95.60 
Jun 29 94.40 
Jun 28 93.59 
Jun 27 92.04 
Jun 24 93.40 
Jun 23 96.10 
Jun 22 95.55 
Jun 21 95.91 
Jun 20 95.10 
Jun 17 95.33 
Jun 16 97.55 
Jun 15 97.14 
Jun 14 97.46 
Jun 13 97.34 
Jun 10 98.83 
Jun 9  99.65 
Jun 8  98.94 
Jun 7  99.03 
Jun 6  98.63 
Jun 3  97.92 
Jun 2  97.72 

有它通过dateframe迭代函数,

indic_up = [False, False,False, False] 
i = 4 
while i+4 <= df.index[-1]: 
    if (df.get_value(i, 'value') > df.get_value(i-1, 'value')) or 
     (df.get_value(i, 'value') > df.get_value(i-2, 'value')) or 
     (df.get_value(i, 'value') > df.get_value(i-3, 'value')) or 
     (df.get_value(i, 'value') > df.get_value(i-4, 'value')):indic_up.append(True) 
    else:indic_up.append(False) 
    i = i+1 

此功能的逻辑是,如果今天的value大于昨天,前天或之前那么它是truefalse。 这个功能似乎对我很慢,所以我怎么可以重写这样的

for index, row in df.iterrows(): 
row['a'], index 

for idx in df.index: 
df.ix[idx, 'a'], idx 

此功能,或者我可以通过将数据帧为numpy的阵列实现多快?

回答

2

也请Scipy

想法:通过计算该区间内的最小值并与当前值进行比较,将当前元素与之前的4值进行比较。如果匹配,我们基本上没有通过所有的比较,因此选择False。因此,按代码方式,只需比较当前元素与该区间中的最小值。这是scipyminimum_filter在一起。

实现:

from scipy.ndimage.filters import minimum_filter 

# Extract values from relevant column into a NumPy array for further procesing 
A = df['value'].values 

# Look for no match with interval-ed min & look for NOT matching for True as o/p 
indic_up_out = A != minimum_filter(A,footprint=np.ones((5,)),origin=2) 

# Set first four as False because those would be invalid with a 5 elem runway 
indic_up_out[:4] = 0 
1

实际上,你可以一次。这是我的实验。它表明循环遍历列表比您的方法快得多。 @Divakar的回答其实非常好。

import pandas as pd 
import timeit 
import numpy as np 

df = pd.DataFrame({'Date':['Jun 30', 'Jun 29', 'Jun 28', 'Jun 27', 'Jun 24', 'Jun 23', 'Jun 22', 'Jun 21', 'Jun 20', 'Jun 17', 
         'Jun 16','Jun 15', 'Jun 14', 'Jun 13', 'Jun 10', 'Jun 9', 'Jun 8', 'Jun 7', 'Jun 6', 'Jun 3', 'Jun 2'], 
      'value': ['95.60', '94.40', '93.59', '92.04', '93.40', '96.10', '95.55', '95.91', '95.10', '95.33', '97.55', 
         '97.14', '97.46', '97.34', '98.83', '99.65', '98.94', '99.03', '98.63', '97.92', '97.72']}) 


def by_df_get_value(): 
    indic_up = [False, False,False, False] 
    i = 4 
    while i+4 <= df.index[-1]: 
     if (df.get_value(i, 'value') > df.get_value(i-1, 'value')) or \ 
     (df.get_value(i, 'value') > df.get_value(i-2, 'value')) or \ 
     (df.get_value(i, 'value') > df.get_value(i-3, 'value')) or \ 
     (df.get_value(i, 'value') > df.get_value(i-4, 'value')): 

     indic_up.append(True) 
    else: 
     indic_up.append(False) 
    i = i+1 


def by_list(): 
    indic_up = [False, False,False, False] 
    values = df['value'].tolist() 
    for i, v in enumerate(values): 
     if i < 4: 
      continue 
     if (v > values[i-1]) or \ 
      (v > values[i-2]) or \ 
      (v > values[i-3]) or \ 
      (v > values[i-4]): 
      indic_up.append(True) 
     else: 
      indic_up.append(False) 

total_time = [] 
for i in range(10): 
    t = timeit.Timer('by_df_get_value()','from __main__ import by_df_get_value').timeit(number=1) 
    total_time.append(t) 
print('by_df_get_value(): ', '{:.20f}'.format(np.mean(total_time))) 


total_time = [] 
for i in range(10): 
    t = timeit.Timer('by_list()','from __main__ import by_list').timeit(number=1) 
    total_time.append(t) 
print('by_list', '{:.20f}'.format(np.mean(total_time))) 

这里是我的机器上输出:

by_df_get_value(): 0.00015220100467558951 
by_list(): 0.00002649170055519790