2015-04-21 25 views
-1

我無法打破數據框,應用計算並將其重新組合在一起。將數據框分解爲組,應用計算並重新合併爲一個數據框

這是我的數據框的樣子:

Priority ID  Name Coverage Group 
1   1000 Name 1 33   Group A 
2   1001 Name 2 67   Group A 
3   1002 Name 3 100  Group A 
4   1003 Name 4 33   Group B 
5   1004 Name 5 67   Group B 
6   1005 Name 6 100  Group B 
7   1006 Name 7 33   Group C 
8   1007 Name 8 67   Group C 
9   1008 Name 9 100  Group C 

我想創建一個新的「有效範圍」一欄,因爲我目前的「覆蓋」一欄是累積性的每個「小組」。例如,作爲「A組」的一部分的「名稱3」實際上具有33(100-67)的覆蓋範圍。

,我希望獲得最後的結果是這樣的:

Priority ID Name Coverage Group Effective Coverage 
1   1000 Name 1 33   Group A 33 
2   1001 Name 2 67   Group A 34 
3   1002 Name 3 100   Group A 33 
4   1003 Name 4 33   Group B 33 
5   1004 Name 5 67   Group B 34 
6   1005 Name 6 100   Group B 33 
7   1006 Name 7 33   Group C 33 
8   1007 Name 8 67   Group C 34 
9   1008 Name 9 100   Group C 33 

這是我到目前爲止有:

for group in groups: 

    effective_coverage = [df[df['group']==group].coverage.iloc[0]] 

    for i in range(1,len(df[df['group']==group].placementID)): 
     ecov = df[df['group']==group].coverage.iloc[i] - df[df['group']==group].coverage.iloc[i-1] 
     effective_coverage.append(ecov) 

    effective_coverage = pd.Series(effective_coverage, name='effective_coverage') 

    print effective_coverage 

    df[df['group']==group] = df[df['group']==group].join(effective_coverage) 
    print df[df['group']==group] 

我知道這個邏輯我把計算有效覆蓋範圍是正確的,因爲對於每個組,它都會打印出33,34,33的正確有效範圍。

然而,當我嘗試加入有效覆蓋系列,並打印出組只是一個數據幀,它只是返回:

Priority ID Name Coverage Group 
1   1000 Name 1 33   Group A 
2   1001 Name 2 67   Group A 
3   1002 Name 3 100   Group A 

而且沒有成功加入我的新計算出的有效覆蓋。

這裏有什麼想法嗎?我是一個大的Python noob,所以我很樂意聽到更優雅的方法來完成這個,如果任何人有一個。

回答

1

你可以寫一個自定義的split_cumsum功能,它計算Effective Coverage

In [33]: def split_cumsum(grp): 
    .....:  grp['Effective Coverage'] = grp['Coverage'] 
    .....:  grp['Effective Coverage'][1:] = np.diff(grp['Coverage']) 
    .....:  return grp 

而且,當時applysplit_cumsumdf.groupby('Group')

In [34]: df.groupby('Group').apply(split_cumsum) 
Out[34]: 
    Priority ID Name Coverage Group Effective Coverage 
0   1 1000 Name 1  33 Group A     33 
1   2 1001 Name 2  67 Group A     34 
2   3 1002 Name 3  100 Group A     33 
3   4 1003 Name 4  33 Group B     33 
4   5 1004 Name 5  67 Group B     34 
5   6 1005 Name 6  100 Group B     33 
6   7 1006 Name 7  33 Group C     33 
7   8 1007 Name 8  67 Group C     34 
8   9 1008 Name 9  100 Group C     33 
+0

謝謝約翰,我不太瞭解什麼情況下創建函數並將其應用於DataFrame是有意義的,但此解決方案絕對是一種更簡潔的方法。 – ploo

0

此外,您可以在groups

In [53]: df['Effective Coverage'] = df.groupby('Group')['Coverage'].diff() 

In [54]: df 
Out[54]: 
    Priority ID Name Coverage Group Effective Coverage 
0   1 1000 Name 1  33 Group A     NaN 
1   2 1001 Name 2  67 Group A     34 
2   3 1002 Name 3  100 Group A     33 
3   4 1003 Name 4  33 Group B     NaN 
4   5 1004 Name 5  67 Group B     34 
5   6 1005 Name 6  100 Group B     33 
6   7 1006 Name 7  33 Group C     NaN 
7   8 1007 Name 8  67 Group C     34 
8   9 1008 Name 9  100 Group C     33 
012使用

然後填充NaN與值從Coverage

In [55]: df['Effective Coverage'] = df['Effective Coverage'].fillna(df['Coverage']) 

In [56]: df 
Out[56]: 
    Priority ID Name Coverage Group Effective Coverage 
0   1 1000 Name 1  33 Group A     33 
1   2 1001 Name 2  67 Group A     34 
2   3 1002 Name 3  100 Group A     33 
3   4 1003 Name 4  33 Group B     33 
4   5 1004 Name 5  67 Group B     34 
5   6 1005 Name 6  100 Group B     33 
6   7 1006 Name 7  33 Group C     33 
7   8 1007 Name 8  67 Group C     34 
8   9 1008 Name 9  100 Group C     33 
0

如果Coverage列是一個累計總數,則該列的最大值將是總的組。我已經改變了你的報道的數字,這樣就可以看到什麼是與GROUPBY然後將其加入到原始數據幀發生:

df = pd.DataFrame({'Priority': np.arange(1, 10), 'ID': np.arange(1000, 1009), 'Name': ['Name {0}'.format(i) for i in np.arange(1, 10)], 'Coverage': [33, 67, 100, 11, 22, 33, 67, 124, 200], 'Group': ['Group {0}'.format(i) for i in ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C', 'C']]})[['Priority', 'ID', 'Name', 'Coverage', 'Group']] 

df2 = df.join(df.groupby('Group').Coverage.max(), on='Group', rsuffix='_max') 

然後,您可以只需添加新列來計算有效覆蓋:

df2['Effective Coverage'] = df2.Coverage.divide(df2.Coverage_max) 

>>> df2 
    Priority ID Name Coverage Group Coverage_max Effective Coverage 
0   1 1000 Name 1  33 Group A   100   0.330000 
1   2 1001 Name 2  67 Group A   100   0.670000 
2   3 1002 Name 3  100 Group A   100   1.000000 
3   4 1003 Name 4  11 Group B   33   0.333333 
4   5 1004 Name 5  22 Group B   33   0.666667 
5   6 1005 Name 6  33 Group B   33   1.000000 
6   7 1006 Name 7  67 Group C   200   0.335000 
7   8 1007 Name 8  124 Group C   200   0.620000 
8   9 1008 Name 9  200 Group C   200   1.000000 
相關問題