關於你的第一個問題,我不能確切地說明爲什麼這個實例很慢。但通常,apply
不利用矢量化。另外,apply
會返回一個新的Series或DataFrame對象,所以對於一個非常大的DataFrame,您會有相當大的IO開銷(我無法保證自Pandas加載內部實現優化以來100%的時間就是這種情況)。
對於您的第一種方法,我假設您正在嘗試使用p_dict
作爲查找表填充df
中的「值」列。這是約1000倍更快地使用pd.merge
:
import string, sys
import numpy as np
import pandas as pd
##
# Part 1 - filling a column by a lookup table
##
def f1(col, p_dict):
return [p_dict[p_dict['ID'] == s]['value'].values[0] for s in col]
# Testing
n_size = 1000
np.random.seed(997)
p_dict = pd.DataFrame({'ID': [s for s in string.ascii_uppercase], 'value': np.random.randint(0,n_size, 26)})
df = pd.DataFrame({'p_id': [string.ascii_uppercase[i] for i in np.random.randint(0,26, n_size)]})
# Apply the f1 method as posted
%timeit -n1 -r5 temp = df.apply(f1, args=(p_dict,))
>>> 1 loops, best of 5: 832 ms per loop
# Using merge
np.random.seed(997)
df = pd.DataFrame({'p_id': [string.ascii_uppercase[i] for i in np.random.randint(0,26, n_size)]})
%timeit -n1 -r5 temp = pd.merge(df, p_dict, how='inner', left_on='p_id', right_on='ID', copy=False)
>>> 1000 loops, best of 5: 826 µs per loop
關於第二個任務,我們可以快速添加一個新列p_dict
計算在時間窗開始於min_week_num
並在一週該行中結尾的平均p_dict
。這要求p_dict
沿着WEEK
列升序排列。然後你可以再次使用pd.merge
。
我假設在以下示例中min_week_num
爲0。但是您可以輕鬆修改rolling_growing_mean
以獲得不同的價值。由於它每次迭代進行固定次數的操作,因此該方法將在O(n)中運行。
n_size = 1000
np.random.seed(997)
p_dict = pd.DataFrame({'WEEK': range(52), 'value': np.random.randint(0, 1000, 52)})
df = pd.DataFrame({'WEEK': np.random.randint(0, 52, n_size)})
def rolling_growing_mean(values):
out = np.empty(len(values))
out[0] = values[0]
# Time window for taking mean grows each step
for i, v in enumerate(values[1:]):
out[i+1] = np.true_divide(out[i]*(i+1) + v, i+2)
return out
p_dict['Means'] = rolling_growing_mean(p_dict['value'])
df_merged = pd.merge(df, p_dict, how='inner', left_on='WEEK', right_on='WEEK')
你試圖做的第一部分是什麼?從f的定義來看,我懷疑它沒有做你想做的事情。也許你應該添加數據框的小例子和預期的結果。 –
感謝Ami,對於第一個問題,例如,p_dict是國家ID與國名查找表,我想查詢國名與國家ID作爲輸入,如果沒有國家ID存在,返回NA :) – linpingta