2016-09-01 360 views
4

我想更改以下代碼所示的訂單日期。
我想要的是一個結果(星期一,星期二,星期三,星期四,星期五,星期六,星期日)
- 應該說,按特定的預定義順序按鍵排序?按特定順序排列(情況:pandas DataFrame Groupby)


這裏是我的代碼需要一些好辦法:

f8 = df_toy_indoor2.groupby(['device_id', 'day'])['dwell_time'].sum() 

print(f8) 

當前的結果:

device_id       day 
device_112      Thu  436518 
            Wed  636451 
            Fri  770307 
            Tue  792066 
            Mon  826862 
            Sat  953503 
            Sun 1019298 
device_223      Mon 2534895 
            Thu 2857429 
            Tue 3303173 
            Fri 3548178 
            Wed 3822616 
            Sun 4213633 
            Sat 4475221 

期望的結果:

device_id       day 
device_112      Mon  826862 
            Tue  792066 
            Wed  636451 
            Thu  436518 
            Fri  770307 
            Sat  953503 
            Sun 1019298 
device_223      Mon 2534895 
            Tue 3303173 
            Wed 3822616 
            Thu 2857429 
            Fri 3548178 
            Sat 4475221 
            Sun 4213633 

這裏,type(df_toy_indoor2.groupby(['device_id', 'day'])['dwell_time'])是一個類'pandas.core.groupby.SeriesGroupBy'。

我發現.sort_values(),但它是一個內置的按值排序的函數。
我想獲得一些指針來設置一些命令來使用它進一步的數據操作。
在此先感謝。

+0

目前還不清楚你在問什麼。請提供[MCVE]。 – IanS

+0

我會說這很清楚。他希望在打印df時排序。 – Skirrebattie

+0

@IanS我只是在我的問題中添加了期望的結果。你是否清楚我的問題? – SUNDONG

回答

9

我花了一些時間,但我找到了解決辦法。 reindex做你想做的。見我的代碼示例:

a = [1, 2] * 2 + [2, 1] * 3 + [1, 2] 
b = ['Mon', 'Wed', 'Thu', 'Fri'] * 3 
c = list(range(12)) 
df = pd.DataFrame(data=[a,b,c]).T 
df.columns = ['device', 'day', 'value'] 
df = df.groupby(['device', 'day']).sum() 

給出:

  value 
device day  
1  Fri  7 
     Mon  0 
     Thu  12 
     Wed  14 
2  Fri  14 
     Mon  12 
     Thu  6 
     Wed  1 

然後做重新索引:

df.reindex(['Mon', 'Wed', 'Thu', 'Fri'], level='day') 

,或者更方便(學分佈爾汗)

df.reindex(list(calendar.day_abbr), level='day') 

給出:

  value 
device day  
1  Mon  0 
     Wed  14 
     Thu  12 
     Fri  7 
2  Mon  12 
     Wed  1 
     Thu  6 
     Fri  14 
+2

您可以使用'calendar'模塊並將reindex更改爲:'df.reindex(list(calendar.day_abbr),level ='day')',以避免明確定義工作日。 – burhan

+0

@Skirrebattie太棒了!這是我想知道的最簡單,最清晰的解決方案。 – SUNDONG

+0

@burhan酷。這很方便,我把它放進去。 – Skirrebattie

1

可能不是最好的方法,但據我所知,你不能通過函數/映射到sort_values。作爲一種解決方法,我通常使用assign添加一個新列並按該列進行排序。在你的例子中,這也需要首先重置索引(並將其設置回去)。

days = {'Mon': 1, 'Tue': 2, 'Wed': 3, 'Thu': 4, 'Fri': 5, 'Sun': 6, 'Sat': 7} 
f8 = f8.reset_index() 
(f8.assign(day_num=f8['day'].map(days)) 
    .sort_values(['device_id', 'day_num']) 
    .set_index(['device_id', 'day']) 
    .drop('day_num', axis=1)) 
Out: 
              0 
device_id      day   
0d4fd55bb363bf6f6f7f8b3342cd0467 Mon 826862 
           Tue 792066 
           Wed 636451 
           Thu 436518 
           Fri 770307 
           Sun 1019298 
           Sat 953503 
f6258edf9145d1c0404e6f3d7a27a29d Mon 2534895 
           Tue 3303173 
           Wed 3822616 
           Thu 2857429 
           Fri 3548178 
           Sun 4213633 
           Sat 4475221 
+1

這就像爲這個任務添加另一列,執行我的任務並將其刪除。 感謝您分享有用的技巧,我希望有人會通過預定義的順序庫添加Pandas的排序關鍵字。 – SUNDONG

+0

是的,它正是這樣做的。 – ayhan

+1

@SUNDONG我的解決方案按預定義順序執行排序鍵:) – Skirrebattie

1

如果您對groupby之前的數據框進行排序,熊貓將維護排序順序。首先你需要做的是找出一個很好的方法來排序一週的日子。這樣做的一種方法是爲每行分配一個表示星期幾的int值,然後對該列進行排序。例如:

import pandas 

df = pandas.DataFrame(
    columns=['device_id', 'day', 'dwell_time'], 
    data=[[1, 'Wed', 35], [1, 'Mon', 63], [2, 'Sat', 83], [2, 'Fri', 82]] 
) 

df['day_of_week'] = df.apply(
    lambda x: ['Mon', 'Tues', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].index(x.day), 
    1 
) 

print(df.sort(['device_id', 'day_of_week']).groupby(['device_id', 'day'])['dwell_time'].sum()) 

產量:

device_id day dwell_time 
1   Mon 63 
      Wed 35 
2   Fri 82 
      Sat 83 
+0

看起來您的解決方案需要在groupby之前進行DataFrame排序。排序可以在總結數值之後完成 - 我認爲更快。 – SUNDONG

3

設置'day'categorical D型,只要確保當您設置的天列表進行排序的類別,你想的那樣。然後執行groupby會自動爲您排序,但如果您嘗試對列進行排序,它將按照您指定的正確順序進行排序。

# Initial setup. 
np.random.seed([3,1415]) 
n = 100 
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] 
df = pd.DataFrame({ 
    'device_id': np.random.randint(1,3,n), 
    'day': np.random.choice(days, n), 
    'dwell_time':np.random.random(n) 
    }) 


# Set as category, groupby, and sort. 
df['day'] = df['day'].astype("category", categories=days, ordered=True) 
df = df.groupby(['device_id', 'day']).sum() 

所得輸出:

   dwell_time 
device_id day    
1   Mon 4.428626 
      Tue 3.259319 
      Wed 2.436024 
      Thu 0.909724 
      Fri 4.974137 
      Sat 5.583778 
      Sun 2.687258 
2   Mon 3.117923 
      Tue 2.427154 
      Wed 1.943927 
      Thu 4.599547 
      Fri 2.628887 
      Sat 6.247520 
      Sun 2.716886 

注意,此方法適用於任何類型的定製排序。例如,如果您有一個條目爲'a', 'b', 'c'的列,並希望以非標準順序對其進行排序,例如, 'c', 'a', 'b',您只需執行相同類型的過程:將列指定爲分類,並且您的類別處於所需的非標準順序。

+0

這更有意義。不過你不需要'ordered = True'嗎? – ayhan

+1

我認爲閱讀文檔也是如此,但它沒有它。我會添加它只是安全的。另外,經過一些測試,'groupby'會自動對輸出進行排序,所以告訴它排序索引是沒有必要的。 – root

+0

謝謝@root。這對預處理dfs和顯示結果也有很大的幫助。 – SUNDONG