2016-04-09 43 views
6

我通過將分類變量轉換爲二進制矩陣來預處理機器學習分類任務的數據,主要使用pd.get_dummies()。這應用於單個Pandas DataFrame列,並輸出一個新的DataFrame,其行數與原始列中唯一數量的分類變量的原始寬度和寬度相同。Python Pandas:爲什麼numpy比pandas更快地分配列?我可以進一步優化嗎?

我需要完成這個形狀的數據框:(3,000,000 x 16)它輸出形狀的二進制矩陣:(3,000,000 x 600)

在此過程中,轉換爲二進制矩陣pd.get_dummies()的步驟非常快,但使用pd.DataFrame.loc[]對輸出矩陣的分配要慢得多。由於我已經切換到直接儲存np.ndarray這是很多更快,我只是想知道爲什麼? (請參見問題底部的終端輸出以進行時間比較

n.b.正如評論中指出的那樣,我可以在整個框架上全部使用pd.get_dummies()。但是,一些列需要量身定製的預處理,即:放入桶中。最難處理的列是包含一串標籤的列(由,,分開,它必須如下處理:df[col].str.replace(' ','').str.get_dummies(sep=',')。此外,預處理的訓練集和測試集需要相同的一組列(從all_cols繼承) 。因爲他們可能沒有出現在相同的功能,一旦被分解成一個矩陣

請參見下面的代碼每個版本

數據幀版本:

def preprocess_df(df): 
    with open(PICKLE_PATH + 'cols.pkl', 'rb') as handle: 
     cols = pickle.load(handle) 

    x = np.zeros(shape=(len(df),len(cols))) 
    # x = pd.DataFrame(columns=all_cols) 

    for col in df.columns: 
     # 1. make binary matrix 
     df_col = pd.get_dummies(df[col], prefix=str(col)) 

     print "Processed: ", col, datetime.datetime.now() 

     # 2. assign each value in binary matrix to col in output 
     for dummy_col in df_col.columns: 
      x.loc[:, dummy_col] = df_col[dummy_col] 

     print "Assigned: ", col, datetime.datetime.now() 

    return x.values 

NP版本:

def preprocess_np(df): 
    with open(PICKLE_PATH + 'cols.pkl', 'rb') as handle: 
     cols = pickle.load(handle) 

    x = np.zeros(shape=(len(df),len(cols))) 

    for col in df.columns: 
     # 1. make binary matrix 
     df_col = pd.get_dummies(df[col], prefix=str(col)) 

     print "Processed: ", col, datetime.datetime.now() 

     # 2. assign each value in binary matrix to col in output 
     for dummy_col in df_col.columns: 
      idx = [i for i,j in enumerate(all_cols) if j == dummy_col][0] 
      x[:, idx] = df_col[dummy_col].values.T 

     print "Assigned: ", col, datetime.datetime.now() 

    return x 

定時輸出(10,000示例)

數據幀版本:

Processed: Weekday 
Assigned: Weekday 0.437081 
Processed: Hour 0.002366 
Assigned: Hour 1.33815 

NP版本:

Processed: Weekday 
Assigned: Weekday 0.006992 
Processed: Hour 0.002632 
Assigned: Hour 0.008989 

是否有不同的方法來進一步優化這個?目前我感興趣,因爲我放棄了一個潛在的有用功能,因爲它處理輸出的額外15,000列速度太慢。

任何有關我正在採取的方法的一般建議也很感激!

謝謝

+0

你不能在整個data.frame上使用get_dummies嗎?你爲什麼每列應用它? – Zelazny7

+0

啊!有趣的問題是,一些專欄需要量身定製的預處理,即:投入水桶。此外,一個特定的列處理標籤列表,它必須像這樣處理:'df [col] .str.replace('','')。str.get_dummies(sep =',')'。另外,預處理訓練集和測試集需要相同的一組列(從'all_cols'繼承),因爲它們在分解成矩陣後可能不具有相同的特徵。 – jfive

+1

@jfive通常最好將它們輸出爲timedeltas,對吧?所以更明顯的是發生了什麼。試着從早先的日期中減去後面的日期,或者使用'from timeit import default_timer as timer'並使用該定時器。 – Paul

回答

1

一個實驗是在更改爲x.loc[:, dummy_col] = df_col[dummy_col].values。如果輸入是一個序列,pandas正在檢查每個分配的索引順序。如果沒有必要,分配一個ndarray會關閉它,並且這應該會提高性能。

相關問題