2016-08-15 140 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