2016-01-19 44 views
2

我有這樣一個數據幀:如何在不同的範圍內的數據幀列正常化值

T data 
0 0 10 
1 1 20 
2 2 30 
3 3 40 
4 4 50 
5 0  5 
6 1 13 
7 2 21 
8 0  3 
9 1  7 
10 2 11 
11 3 15 
12 4 19 

T的值是其中所有範圍從0上升到一定值,由此最大數量可以不同的序列序列之間。 通常,data中的值不等間隔,現在僅用於演示目的。

我想要實現的是添加一個名爲dataDiv的第三列,其中某個序列的data中的每個值除以屬於各個序列的T = 0的值。在我的情況下,我有3個序列,對於第一個序列,我希望將每個值除以10,在第二個序列中,每個值應該除以5,並且第三個序列除以3. 因此,預期結果如下所示:

T data dataDiv 
0 0 10 1.000000 
1 1 20 2.000000 
2 2 30 3.000000 
3 3 40 4.000000 
4 4 50 5.000000 
5 0  5 1.000000 
6 1 13 2.600000 
7 2 21 4.200000 
8 0  3 1.000000 
9 1  7 2.333333 
10 2 11 3.666667 
11 3 15 5.000000 
12 4 19 6.333333 

我目前實現的方式是如下: 我先確定指數在這T = 0。然後循環這些索引並將data中的數據除以相應序列的T=0的值,這給出了期望的輸出(如上所示)。代碼如下:

import pandas as pd 
df = pd.DataFrame({'T': range(5) + range(3) + range(5), 
        'data': range(10, 60, 10) + range(5, 25, 8) + range(3, 21, 4)}) 

# get indices where T = 0 
idZE = df[df['T'] == 0].index.tolist() 

# last index of dataframe 
idZE.append(max(df.index)+1) 

# add the column with normalzed values 
df['dataDiv'] = df['data'] 

# loop through indices where T = 0 and normalize values 
for ix, indi in enumerate(idZE[:-1]): 

    df['dataDiv'].iloc[indi:idZE[ix + 1]] = df['data'].iloc[indi:idZE[ix + 1]]/df['data'].iloc[indi] 

我的問題是:有沒有比避免循環更聰明的解決方案?

回答

5

如果支持向量化計算並且應該執行得更快,以下方法可避免循環。基本思想是在'T'列中標記整數運行,在這些組中找到第一個值,然後將'data'中的值除以適當的第一個值。

df['grp'] = (df['T'] == 0).cumsum()   # label consecutive runs of integers 
x = df.groupby('grp')['data'].first()   # first value in each group 
df['dataDiv'] = df['data']/df['grp'].map(x) # divide 

這得到所需的列數據框:

T data grp dataDiv 
0 0 10 1 1.000000 
1 1 20 1 2.000000 
2 2 30 1 3.000000 
3 3 40 1 4.000000 
4 4 50 1 5.000000 
5 0  5 2 1.000000 
6 1 13 2 2.600000 
7 2 21 2 4.200000 
8 0  3 3 1.000000 
9 1  7 3 2.333333 
10 2 11 3 3.666667 
11 3 15 3 5.000000 
12 4 19 3 6.333333 

(然後你可以刪除 'GRP' 列,如果你想:df.drop('grp', axis=1)

由於@DSM下面指出,這三行代碼可以合併爲一個使用groupby.transform

df['dataDiv'] = df['data']/df.groupby((df['T'] == 0).cumsum())['data'].transform('first') 
+0

看起來很像很好,工作正常,謝謝!我現在立刻贊成它,稍後可能會接受它,這取決於其他答案的質量。 – Cleb

+0

完全沒問題! –

+1

不值得一個單獨的答案,但也可以使用'.transform(「first」)',然後除以'x'而不是'df [「grp」] .map(x)'。數額相同的事情。 – DSM

相關問題