2016-07-05 85 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