2016-11-21 234 views
3

条件更换行的价值。这是我的熊猫数据框:在大熊猫数据帧

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的SEQ值是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 

我怎样才能有效地避免循环?在GROUPBY操作

回答

0

添加一点点,以Boud的答案,如果你打算什么是有在造成SEQ列的顺序取决于起始列的值,可以通过

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

也就是实现这一目标,

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

这里有两个approac使用np.cumsumNumPy HES创建这些斜坡阵列 -

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() 

运行测试 -

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看看它是如何工作的 -

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