2017-06-29 41 views
1

最近我一直在使用多級數據框,並且我發現它們可以顯着減少大型數據集的計算時間。例如,考慮簡單的數據幀:設置多級熊貓數據框中的值python

df = pd.DataFrame([ 
     [1, 111, 0], [2, 222, 0], [1, 111, 0], 
     [2, 222, 1], [1, 111, 1], [2, 222, 2] 
    ], columns=["ID", "A", "B"], index=[1, 1, 2, 2, 3, 3] 
) 
df.head(6) 

    ID A B 
1 1 111 0 
1 2 222 0 
2 1 111 0 
2 2 222 1 
3 1 111 1 
3 2 222 2 

可以通過ID擺動,形成一個多層次的數據幀:

​​

關於有這種格式我的數據的偉大的事情是,我可以簡單地通過參考0級列執行所有ID爲「矢量」操作:

pivot_df["A"] * (1 + pivot_df["B"])**2 

ID 1 2 
1 111 222 
2 111 888 
3 444 999 

這些操作是真的對我很有幫助!在現實生活中,我的計算要複雜得多,需要執行> 1000個ID。我使用的通用DataFrame大小包含10列(0級)和1000個ID(級別1),包含350行。

我很想搞清楚做兩件事情:更新此樞軸化DataFrame中特定字段的值;爲此DataFrame創建一個新列。喜歡的東西

pivot_df["A"] = pivot_df["A"] * (1 + pivot_df["B"])**2 

pivot_df["C"] = pivot_df["A"] * (1 + pivot_df["B"])**2 

當我執行以下任一我沒有得到任何錯誤,但數據幀保持不變。我也試過使用.loc和.iloc,但我沒有成功。

我認爲問題在於維護計算的DataFrame的多級結構,但我對使用多級DataFrames並不確定如何有效地解決此問題非常新穎。我有一個笨拙的解決方法是效率不高(創建計算DataFrames的字典,然後將它們全部融合在一起......

df_dict = OrderedDict() 
df_dict["A"] = pivot_df["A"] 
df_dict["B"] = pivot_df["B"] 
df_dict["C"] = pivot_df["A"] * (1 + pivot_df["B"])**2 

dfs = [val.T.set_index(np.repeat(key, val.shape[1]), append=True).T for key, val in df_dict.iteritems()] 
final_df = reduce(lambda x, y: pd.merge(x, y, left_index=True, right_index=True), dfs) 
final_df.columns = final_df.columns.swaplevel(0, 1) 

或類似的,

df_dict = OrderedDict() 
df_dict["A"] = pivot_df["A"] * (1 + pivot_df["B"])**2 
df_dict["B"] = pivot_df["B"] 

dfs = [val.T.set_index(np.repeat(key, val.shape[1]), append=True).T for key, val in df_dict.iteritems()] 
final_df = reduce(lambda x, y: pd.merge(x, y, left_index=True, right_index=True), dfs) 
final_df.columns = final_df.columns.swaplevel(0, 1) 

這並不一定是笨重(我是那種驕傲的解決方法),但是這肯定不是效率或計算進行了優化。沒有人有任何建議?

+0

你的代碼不會產生你是顯示數據幀。 – piRSquared

+0

哎呀,我必須從我的Jupyter筆記本複製錯誤的代碼..我應該已經取代'df = pd.DataFrame([[1,111,0],[2,222,0],[1,111,0 ],[2,222,1], [1,111,1],[2,222,2]],列= [「ID」,「A」,「B」], index = [1, 1,2,2,3,3])' – RMatt

回答

0

選項1
不要先旋轉!
您聲明,因爲您可以在新的透視表單中執行矢量計算,所以它很方便。這是一種誤解,因爲您可以在數據透視之前輕鬆執行這些計算。

df['C'] = df["A"] * (1 + df["B"]) ** 2 
df.pivot(columns='ID') 

     A  B  C  
ID 1 2 1 2 1  2 
1 111 222 0 0 111 222 
2 111 222 0 1 111 888 
3 111 222 1 2 444 1998 

或者在管道的一行,如果你喜歡

df.assign(C=df.A * (1 + df.B) ** 2).pivot(columns='ID') 

     A  B  C  
ID 1 2 1 2 1  2 
1 111 222 0 0 111 222 
2 111 222 0 1 111 888 
3 111 222 1 2 444 1998 

選項2
pd.concat
但要回答你的問題...

pdf = df.pivot(columns='ID') 
pd.concat([ 
     pdf.A, pdf.B, pdf.A * (1 + pdf.B) ** 2 
    ], axis=1, keys=['A', 'B', 'C']) 

     A  B  C  
ID 1 2 1 2 1  2 
1 111 222 0 0 111 222 
2 111 222 0 1 111 888 
3 111 222 1 2 444 1998 

選項3
pd.concat
添加另一個級別之前列Concat的

pdf = df.pivot(columns='ID') 
c = pdf.A * (1 + pdf.B) ** 2 
c.columns = [['C'] * len(c.columns), c.columns] 

pd.concat([pdf, c], axis=1) 

     A  B  C  
ID 1 2 1 2 1  2 
1 111 222 0 0 111 222 
2 111 222 0 1 111 888 
3 111 222 1 2 444 1998 
+0

作爲我的過程的一部分,我需要在我的計算過程中的不同點執行'cumsum()'和'cumprod()',這是另一個原因我需要旋轉而不是直接執行計算。我執行一些自定義的自迴歸計算。 PD concat可能更有效,但直接改變A的值又怎麼樣呢? – RMatt

+0

@RMatt有道理。選項2和3應該可以幫你照顧它。 – piRSquared