2016-06-12 17 views
2

我有下面的最小代碼太慢了。對於我需要的1000行,大約需要2分鐘。我需要它跑得更快。Python:快速子集和循環數據框

import numpy as np 
import pandas as pd 

df = pd.DataFrame(np.random.randint(0,1000,size=(1000, 4)), columns=list('ABCD')) 
start_algorithm = time.time() 
myunique = df['D'].unique() 
for i in myunique: 
    itemp = df[df['D'] == i] 
    for j in myunique: 
     jtemp = df[df['D'] == j] 

我知道numpy的可以讓它運行得更快,但請記住,我想保持原來的數據幀的一部分(或陣列numpy的)爲列「d」的具體數值。我怎樣才能提高其表現?

+0

嘗試總是以提供[最小,完整的,並且可驗證示例](http://stackoverflow.com/help/mcve)當提問時。如果出現_pandas_問題,請提供樣本_input_和_output_數據集(CSV/dict/JSON/Python代碼格式中的5-7行_s text_,因此可以在爲您編寫答案時使用它)。這將有助於避免_situations_,例如:「您的代碼不適合我」或「它不適用於我的數據」等。 – MaxU

+1

您不清楚您想要做什麼... – MaxU

+0

我不希望通過數據行的行進行簡單的循環。否則,我可以輕鬆地在numpy中實現它。我需要循環通過olumn'D'的獨特值,這將產生原始數據幀的子集。有了numpy,我應該迭代2d數組的所有元素,並在'D'列中存儲具有相同值的行。沒有真正的數據需要處理,這就是爲什麼我給了數據框的隨機值。 – ilias

回答

3

避免多次計算子數據幀df[df['D'] == i]。原始代碼計算這個len(myunique)**2次。相反,您可以爲每個i(即總共len(myunique)次)計算一次,存儲結果,然後再將它們組合在一起。例如,

groups = [grp for di, grp in df.groupby('D')] 
    for itemp, jtemp in IT.product(groups, repeat=2): 
     pass 

import pandas as pd 
import itertools as IT 
df = pd.DataFrame(np.random.randint(0,1000,size=(1000, 4)), columns=list('ABCD')) 

def using_orig(): 
    myunique = df['D'].unique() 
    for i in myunique: 
     itemp = df[df['D'] == i] 
     for j in myunique: 
      jtemp = df[df['D'] == j] 

def using_groupby(): 
    groups = [grp for di, grp in df.groupby('D')] 
    for itemp, jtemp in IT.product(groups, repeat=2): 
     pass 

In [28]: %timeit using_groupby() 
10 loops, best of 3: 63.8 ms per loop 
In [31]: %timeit using_orig() 
1 loop, best of 3: 2min 22s per loop 

關於評論:

我可以很容易地更換ITEMP和其中a = 1或打印「jtemp你好「所以無視

上面的答案解決了如何更有效地計算itempjtemp。如果itempjtemp對您的實際計算不重要,那麼我們需要更好地理解您真正想要計算的內容以便建議(如果可能)更快地計算它的方法。

+0

我希望我有你的魔法水晶球...;) – MaxU

+1

我對itemp和jtemp的評論意在強調(當時我認爲)問題是與獨特。正如我現在可以從unutbu的驚人答案中看到的那樣,我顯然是錯誤的,並且我對向其他成員致敬,因爲有些誤導了他們。你的回答正常,我感謝你的時間和貢獻。 – ilias

0

這裏的一個矢量化的方法來形成基於獨特的元素的基團從"D"柱 -

# Sort the dataframe based on the sorted indices of column 'D' 
df_sorted = df.iloc[df['D'].argsort()] 

# In the sorted dataframe's 'D' column find the shift/cut indces 
# (places where elements change values, indicating change of groups). 
# Cut the dataframe at those indices for the final groups with NumPy Split. 
cut_idx = np.where(np.diff(df_sorted['D'])>0)[0]+1 
df_split = np.split(df_sorted,cut_idx) 

樣品測試

1]與隨機元素形式的樣本數據幀:

>>> df = pd.DataFrame(np.random.randint(0,100,size=(5, 4)), columns=list('ABCD')) 
>>> df 
    A B C D 
0 68 68 90 39 
1 53 99 20 85 
2 64 76 21 19 
3 90 91 32 36 
4 24 9 89 19 

2]運行原始碼並打印結果:

>>> myunique = df['D'].unique() 
>>> for i in myunique: 
...  itemp = df[df['D'] == i] 
...  print itemp 
... 
    A B C D 
0 68 68 90 39 
    A B C D 
1 53 99 20 85 
    A B C D 
2 64 76 21 19 
4 24 9 89 19 
    A B C D 
3 90 91 32 36 

3]運行建議代碼和打印結果:

>>> df_sorted = df.iloc[df['D'].argsort()] 
>>> cut_idx = np.where(np.diff(df_sorted['D'])>0)[0]+1 
>>> df_split = np.split(df_sorted,cut_idx) 
>>> for split in df_split: 
...  print split 
... 
    A B C D 
2 64 76 21 19 
4 24 9 89 19 
    A B C D 
3 90 91 32 36 
    A B C D 
0 68 68 90 39 
    A B C D 
1 53 99 20 85