2016-08-15 99 views
4

如何对DataFrame进行排序,以便重复列中的行被“回收”。熊猫DataFrame按行重复排序

例如,我原来的数据帧是这样的:

In [3]: df 
Out[3]: 
    A B 
0 r1 0 
1 r1 1 
2 r2 2 
3 r2 3 
4 r3 4 
5 r3 5 

我想它转到:

In [3]: df_sorted 
Out[3]: 
    A B 
0 r1 0 
2 r2 2 
4 r3 4 
1 r1 1 
3 r2 3 
5 r3 5 

行进行排序,使得A列的行是一个“回收“时尚。

我已经在Pandas搜索了API,但似乎没有任何适当的方法来做到这一点。我可以编写一个复杂的函数来实现这一点,但只是想知道有没有什么聪明的方法或现有的熊猫方法可以做到这一点?提前致谢。

更新: 道歉为一个错误的陈述。在我真正的问题中,列B包含字符串值。

回答

3

可以使用cumcount通过AA列计数的重复,然后sort_values第一(在没有必要的样品,在真实数据也许很重要),然后由C。最后由drop删除列C

df['C'] = df.groupby('A')['A'].cumcount() 
df.sort_values(by=['C', 'A'], inplace=True) 
print (df) 
    A B C 
0 r1 0 0 
2 r2 2 0 
4 r3 4 0 
1 r1 1 1 
3 r2 3 1 
5 r3 5 1 

df.drop('C', axis=1, inplace=True) 
print (df) 
    A B 
0 r1 0 
2 r2 2 
4 r3 4 
1 r1 1 
3 r2 3 
5 r3 5 

时序

小DF(len(df)=6

In [26]: %timeit (jez(df)) 
1000 loops, best of 3: 2 ms per loop 

In [27]: %timeit (boud(df1)) 
100 loops, best of 3: 2.52 ms per loop 

大DF(len(df)=6000

In [23]: %timeit (jez(df)) 
100 loops, best of 3: 3.44 ms per loop 

In [28]: %timeit (boud(df1)) 
100 loops, best of 3: 2.52 ms per loop 

代码时间:

df = pd.concat([df]*1000).reset_index(drop=True) 
df1 = df.copy() 

def jez(df): 
    df['C'] = df.groupby('A')['A'].cumcount() 
    df.sort_values(by=['C', 'A'], inplace=True) 
    df.drop('C', axis=1, inplace=True) 
    return (df) 

def boud(df): 
    df['C'] = df.groupby('A')['B'].rank() 
    df = df.sort_values(['C', 'A']) 
    df.drop('C', axis=1, inplace=True) 
    return (df) 
100 loops, best of 3: 4.29 ms per loop 
4

您可以根据每组的第一行,然后是第二行,然后是第三行等来制定您的需求。因此,这相当于按行分组,然后根据'A'对结果进行分组。

您可以使用函数rank为每个键的行编号为'A'。适用于各组此功能,就大功告成了:

df['C'] = df.groupby('A')['B'].rank() 

df 
Out[8]: 
    A B C 
0 r1 0 1.0 
1 r1 1 2.0 
2 r2 2 1.0 
3 r2 3 2.0 
4 r3 4 1.0 
5 r3 5 2.0 

df.sort_values(['C', 'A']) 
Out[9]: 
    A B C 
0 r1 0 1.0 
2 r2 2 1.0 
4 r3 4 1.0 
1 r1 1 2.0 
3 r2 3 2.0 
5 r3 5 2.0 

您下降'C',如果你不需要它。


编辑跟进评论

我想当然你的样品'B'是你的索引列英寸如果不是,那么你需要对指数本身的工作:

df['C'] = df.reset_index().groupby('A')['index'].rank() 
+0

我根据标题中提到的重复项目采取OP问题。编辑该帖子,将您的宝贵意见考虑在内。谢谢 – Boud

+0

超级,你的第二个解决方案现在可以很好地工作(但不幸的是,它更慢。) – jezrael

+0

谢谢,布德。学习了一个非常有用的方法'rank'。然而,在我真正的问题中,“B”列实际上不是数字,所以我不能在该列上使用“rank”。我应该说,我的道歉。 – Xer