2017-01-07 33 views
1

我有一組測量值;每個測量值都是DataFrame中的一行。我想爲這些測量添加一列,以反映與參考相比測量速度的提升。每個度量都通過其「數據集」和「算法」加以區分,並且每個數據集 - 算法對都有一個參考運行時。pandas:歸一化組內的值,每組有一個參考值(groupby?split-apply-combine?)

col = ['program', 'dataset', 'algorithm', 'extra', 'runtime'] 
df = pandas.DataFrame(
    [['program-ref', 'dataset-X', 'algorithm-i', 'x', 1.0], 
    ['program-ref', 'dataset-X', 'algorithm-j', 'x', 2.0], 
    ['program-ref', 'dataset-Y', 'algorithm-i', 'x', 3.0], 
    ['program-ref', 'dataset-Y', 'algorithm-j', 'x', 4.0], 
    ['program-B', 'dataset-X', 'algorithm-i', 'x', 5.0], 
    ['program-B', 'dataset-X', 'algorithm-j', 'x', 6.0], 
    ['program-B', 'dataset-Y', 'algorithm-i', 'x', 7.0], 
    ['program-B', 'dataset-Y', 'algorithm-j', 'x', 8.0], 
    ['program-C', 'dataset-X', 'algorithm-i', 'x', 9.0], 
    ['program-D', 'dataset-X', 'algorithm-j', 'x', 10.0], 
    ['program-E', 'dataset-Y', 'algorithm-i', 'x', 11.0], 
    ['program-E', 'dataset-Y', 'algorithm-j', 'x', 12.0], 
    ], columns=col) 

我想添加名爲「加速」,其中「加速」對於每個測量被計算爲(的倒數)爲測量由運行時用於參考測量除以運行柱(對於數據集 - 算法對)。例如,在上面的DataFrame中,第5行(程序B,數據集X,算法i)的'加速'應該是1 /(5.0/1.0)。

這似乎是拆分應用組合(http://pandas.pydata.org/pandas-docs/stable/groupby.html)的一個實例,但其中顯示的應用函數通常是組中所有內容或其輸入只有一個特定度量的函數的集合。在這裏,我需要將參考度量「應用」到組中的所有內容。

我還在上面添加了'extra'列,因爲我希望輸出與除了新的'加速'列以外的輸入相同,而groupby似乎想要剔除所有「令人討厭」的列。

回答

1

由於每個算法數據集組合有多個程序名稱,我不喜歡爲完成目標而設置數據。還要注意,由於存在程序數據集算法值的獨特組合,因此給定樣本數據時groupby方法是無關緊要的。也許你的真實數據有不同的要求?如果是這樣,請更新樣本數據以反映要求。同時,請嘗試以下操作。

將參考值與其餘數據合併會更容易,以便可以更輕鬆地將相應的值相互關聯。

ref_df = df.loc[df['program'] == 'program-ref', ['dataset', 'algorithm', 'runtime']] 
# EDIT: only include the following line if you wish to remove the reference 
# rows from the final output 
# df = df.loc[~(df['program'] == 'program-ref')] 

new_df = pd.merge(df, ref_df, on=['dataset', 'algorithm'], 
           suffixes=['', '_ref']) 

# you don't actually need a groupby since there are unique 
# program-dataset-algorithm combinations. 
new_df['speedup'] = 1/(new_df['runtime']/new_df['runtime_ref']) 

# optional groupby approach 
new_df['speedup'] = new_df.groupby(['program', 'dataset', 'algorithm']).apply(
          lambda x: 1/(x['runtime']/x['runtime_ref'])).values 

>>> new_df.sort_values('program', ascending=False) 
     program dataset algorithm extra runtime runtime_ref speedup 
0 program-ref dataset-X algorithm-i  x  1.0   1.0 1.000000 
3 program-ref dataset-X algorithm-j  x  2.0   2.0 1.000000 
6 program-ref dataset-Y algorithm-i  x  3.0   3.0 1.000000 
9 program-ref dataset-Y algorithm-j  x  4.0   4.0 1.000000 
8  program-E dataset-Y algorithm-i  x  11.0   3.0 0.272727 
11 program-E dataset-Y algorithm-j  x  12.0   4.0 0.333333 
5  program-D dataset-X algorithm-j  x  10.0   2.0 0.200000 
2  program-C dataset-X algorithm-i  x  9.0   1.0 0.111111 
1  program-B dataset-X algorithm-i  x  5.0   1.0 0.200000 
4  program-B dataset-X algorithm-j  x  6.0   2.0 0.333333 
7  program-B dataset-Y algorithm-i  x  7.0   3.0 0.428571 
10 program-B dataset-Y algorithm-j  x  8.0   4.0 0.500000 
+0

Hi @ 3novak,我的數據真的是這樣設置的。每個實驗都會生成一個JSON文件,其中包含其參數,其中包括程序和數據集以及算法和運行時。我想說程序/數據集/算法的組合是獨一無二的,但是你是對的,數據集+算法確實有多個可能的程序。我使用'data_unfiltered = [json.load(open(jf))for jf in json_input_files]''然後'df = json_normalize(data_unfiltered)''讀取了JSON文件。 我很樂意接受其他關於如何組織這方面的建議。 – jowens

+0

難道你不能按我演示的方式分割嗎?如果你已經有了你發佈的格式的數據,我發佈的解決方案應該很快解析它。我想不出任何其他方式來處理數據的原始格式沒有無窮無盡的kludge。雖然也許有一種方法! – 3novak

+0

我理解你的方法分兩步走,也許第一步的輸出是「我演示的方式」。第1步是爲該行添加一個具有適當引用運行時的引用列。第2步是一個微不足道的適用於生成我需要的加速。這似乎是一個簡單的方法;我現在就給它一個旋風! – jowens

相關問題