2016-11-21 10 views
3

は、これは私のパンダのDATAFRAMEです:パンダの行の値の条件付き交換DATAFRAME

ID START END SEQ 
1 11  12 5 
1 14  15 6 
1 13  14 7 
2 10  14 1 
3 11  15 1 
3 16  17 2 

は、私は、同じIDの配列の値は1、2、となるように、配列の値を変更したいです...等、例えば

ID START END SEQ 
1 11  12 1 
1 14  15 3 
1 13  14 2 
2 10  14 1 
3 11  15 1 
3 16  17 2 

forループを回避するにはどうすればよいですか? GROUPBY操作上の

答えて

0

Boudの答えに小さなビットを追加、何を意図しすることはSEQ列を結果の順序を持​​っているのであればあなたができる、START列の値に依存ここで

In [3]: df 
Out[3]: 
    ID START END SEQ 
0 1  11 12 5 
1 1  14 15 6 
2 1  13 14 7 
3 2  10 14 1 
4 3  11 15 1 
5 3  16 17 2 

In [4]: df['SEQ'] = df.sort_values(by='START').groupby('ID').cumcount()+1 

In [5]: df 
Out[5]: 
    ID START END SEQ 
0 1  11 12 1 
1 1  14 15 3 
2 1  13 14 2 
3 2  10 14 1 
4 3  11 15 1 
5 3  16 17 2 
1

使用cumcount:

df.groupby('ID').cumcount()+1 
0

は2 approacあり、

ある
df['SEQ'] = df.sort_values(by='START').groupby('ID').cumcount()+1 

を介してこれを実現

def id_ramp(a): 
    out = np.ones(a.size,dtype=int) 
    idx = np.nonzero(np.append(True,a[1:] > a[:-1]))[0] 
    out[idx[1:]] = -idx[1:] + idx[:-1] + 1 
    return out.cumsum() 

def id_ramp2(a): 
    out = np.ones(a.size,dtype=int) 
    idx = np.nonzero(a[1:] > a[:-1])[0]+1 
    out[idx[0]] = -idx[0]+1 
    out[idx[1:]] = idx[:-1] - idx[1:]+1 
    return out.cumsum() 

ランタイムテスト - - それらのランプ配列を作成するためにnp.cumsumを使用してNumPyとHES

In [381]: a = np.sort(np.random.randint(1,100,(1000))) 

In [382]: df = pd.DataFrame(a, columns=[['ID']]) 

In [383]: %timeit df['SEQ'] = df.groupby('ID').cumcount()+1 #@Boud's soln 
100 loops, best of 3: 2.01 ms per loop 

In [384]: %timeit df['SEQ'] = id_ramp(df.ID.values) 
1000 loops, best of 3: 315 µs per loop 

In [385]: %timeit df['SEQ'] = id_ramp2(df.ID.values) 
1000 loops, best of 3: 304 µs per loop 

あなたは常にソートされていないID列を使用している場合、私たちはそこにいくつかのargsortを使用する必要があります、ように -

a = df.ID.values 
sidx = a.argsort(kind='mergesort') 
df['SEQ'] = id_ramp2(a[sidx])[sidx.argsort()] 

サンプルcを見てみましょうどのように動作するか見るためにase -

In [447]: df 
Out[447]: 
    ID 
0 1 
1 1 
2 7 
3 5 
4 3 
5 8 
6 1 
7 3 
8 7 
9 2 
10 5 
11 7 

In [448]: a = df.ID.values 
    ...: sidx = a.argsort(kind='mergesort') 
    ...: df['SEQ'] = id_ramp2(a[sidx])[sidx.argsort()] 
    ...: 

In [449]: df 
Out[449]: 
    ID SEQ 
0 1 1 
1 1 2 
2 7 1 
3 5 1 
4 3 1 
5 8 1 
6 1 3 
7 3 2 
8 7 2 
9 2 1 
10 5 2 
11 7 3 
関連する問題