2017-10-18 71 views
1

我有一个熊猫数据帧,看起来是这样的:获得分组的顺序大熊猫数据帧

df = pd.DataFrame({'Name' : ['Kate', 'John', 'Peter','Kate', 'John', 'Peter'],'Distance' : [23,16,32,15,31,26], 'Time' : [3,5,2,7,9,4]}) 
df 


    Distance Name Time 
0 23  Kate 3 
1 16  John 5 
2 32  Peter 2 
3 15  Kate 7 
4 31  John 9 
5 26  Peter 2 

我想补充一点,告诉我一栏中,每个名称,什么是时代的秩序。

我想是这样的:

Order Distance Name Time 
    0  16  John 5 
    1  31  John 9 
    0  23  Kate 3 
    1  15  Kate 7 
    0  32  Peter 2 
    1  26  Peter 4 

我可以用一个for循环做:

df2 = df[df['Name'] == 'aaa'].reset_index().reset_index() # I did this just to create an empty data frame with the columns I want 

for name, row in df.groupby('Name').count().iterrows(): 
    table = df[df['Name'] == name].sort_values('Time').reset_index().reset_index() 
    to_concat = [df2,table] 
    df2 = pd.concat(to_concat) 

df2.drop('index', axis = 1, inplace = True) 
df2.columns = ['Order', 'Distance', 'Name', 'Time'] 
df2 

这工作,问题是(除了是非常unpythonic),大表(我的实际表格大约有5万行)需要运行大约半个小时。

有人可以帮助我以更简单的方式写更快的运行吗? 对不起,如果这已被回答某处,但我真的不知道如何搜索它。

最佳,

回答

2

使用sort_valuescumcount

df = df.sort_values(['Name','Time']) 
df['Order'] = df.groupby('Name').cumcount() 
print (df) 

    Distance Name Time Order 
1  16 John  5  0 
4  31 John  9  1 
0  23 Kate  3  0 
3  15 Kate  7  1 
2  32 Peter  2  0 
5  26 Peter  4  1 

如果需要第一柱使用insert

df = df.sort_values(['Name','Time']) 
df.insert(0, 'Order', df.groupby('Name').cumcount()) 
print (df) 
    Order Distance Name Time 
1  0  16 John  5 
4  1  31 John  9 
0  0  23 Kate  3 
3  1  15 Kate  7 
2  0  32 Peter  2 
5  1  26 Peter  4 
1
In [67]: df = df.sort_values(['Name','Time']) \ 
       .assign(Order=df.groupby('Name').cumcount()) 

In [68]: df 
Out[68]: 
    Distance Name Time Order 
1  16 John  5  0 
4  31 John  9  1 
0  23 Kate  3  0 
3  15 Kate  7  1 
2  32 Peter  2  0 
5  26 Peter  4  1 

PS我不知道这是最优雅的方式来做到这一点...

+0

出于某种原因,这不起作用,对于某些组的名称,“订单”在一半的时间内重新开始。例如,对于具有相同名称的行,我获得了像0,1,2,0,1这样的命令。 jezrael的答案虽然有效。 – user5576