2013-05-02 116 views
16

我有一個csv文件,顯示訂購部件。這些專欄包括日期晚,數量和商品。按值的範圍對數據進行分組

我需要將數據按遲到天數進行分組,並將商品與數量的總和進行分組。然而,遲到的日子需要分組到不同的範圍。

>56 
>35 and <= 56 
>14 and <= 35 
>0 and <=14 

我希望我可以使用字典一些如何。這樣

{'Red':'>56,'Amber':'>35 and <= 56','Yellow':'>14 and <= 35','White':'>0 and <=14'} 

什麼我尋找的結果是這樣

 Red Amber Yellow White 
STRSUB 56 60  74  40 
BOTDWG 20 67  87  34 

我是新來的大熊貓,所以我不知道這是不可能的。誰能提供一些建議。

感謝

回答

21

假設你開始了這個數據:

df = pd.DataFrame({'ID': ('STRSUB BOTDWG'.split())*4, 
        'Days Late': [60, 60, 50, 50, 20, 20, 10, 10], 
        'quantity': [56, 20, 60, 67, 74, 87, 40, 34]}) 
# Days Late  ID quantity 
# 0   60 STRSUB  56 
# 1   60 BOTDWG  20 
# 2   50 STRSUB  60 
# 3   50 BOTDWG  67 
# 4   20 STRSUB  74 
# 5   20 BOTDWG  87 
# 6   10 STRSUB  40 
# 7   10 BOTDWG  34 

然後您可以使用pd.cut找到狀態類別。請注意,在默認情況下,pd.cut拆分系列df['Days Late']成是半開間隔,(-1, 14], (14, 35], (35, 56], (56, 365]類:

df['status'] = pd.cut(df['Days Late'], bins=[-1, 14, 35, 56, 365], labels=False) 
labels = np.array('White Yellow Amber Red'.split()) 
df['status'] = labels[df['status']] 
del df['Days Late'] 
print(df) 
#  ID quantity status 
# 0 STRSUB  56  Red 
# 1 BOTDWG  20  Red 
# 2 STRSUB  60 Amber 
# 3 BOTDWG  67 Amber 
# 4 STRSUB  74 Yellow 
# 5 BOTDWG  87 Yellow 
# 6 STRSUB  40 White 
# 7 BOTDWG  34 White 

現在使用pivot獲得數據框所需形式:

df = df.pivot(index='ID', columns='status', values='quantity') 

和使用reindex以獲得所需的行和列順序:

df = df.reindex(columns=labels[::-1], index=df.index[::-1]) 

因此,

import numpy as np 
import pandas as pd 

df = pd.DataFrame({'ID': ('STRSUB BOTDWG'.split())*4, 
        'Days Late': [60, 60, 50, 50, 20, 20, 10, 10], 
        'quantity': [56, 20, 60, 67, 74, 87, 40, 34]}) 
df['status'] = pd.cut(df['Days Late'], bins=[-1, 14, 35, 56, 365], labels=False) 
labels = np.array('White Yellow Amber Red'.split()) 
df['status'] = labels[df['status']] 
del df['Days Late'] 
df = df.pivot(index='ID', columns='status', values='quantity') 
df = df.reindex(columns=labels[::-1], index=df.index[::-1]) 
print(df) 

產生

 Red Amber Yellow White 
ID        
STRSUB 56  60  74  40 
BOTDWG 20  67  87  34 
+0

非常感謝您的支持,我認爲這將有助於我在日常工作中通過PANDAS實現很多。還要感謝mtadd,我注意到你也更新了你的答案(它是令人滿意的)。 – PrestonDocks 2013-05-03 18:57:50

6

您可以通過使用mapapply功能如下創建一個基於你的延遲天數列在您的DataFrame列。我們先創建一些示例數據。

df = pandas.DataFrame({ 'ID': 'foo,bar,foo,bar,foo,bar,foo,foo'.split(','), 
         'Days Late': numpy.random.randn(8)*20+30}) 

    Days Late ID 
0 30.746244 foo 
1 16.234267 bar 
2 14.771567 foo 
3 33.211626 bar 
4 3.497118 foo 
5 52.482879 bar 
6 11.695231 foo 
7 47.350269 foo 

創建一個輔助函數來改造延遲天數列的數據,添加一個名爲代碼列。

def days_late_xform(dl): 
    if dl > 56: return 'Red' 
    elif 35 < dl <= 56: return 'Amber' 
    elif 14 < dl <= 35: return 'Yellow' 
    elif 0 < dl <= 14: return 'White' 
    else: return 'None' 

df["Code"] = df['Days Late'].map(days_late_xform) 

    Days Late ID Code 
0 30.746244 foo Yellow 
1 16.234267 bar Yellow 
2 14.771567 foo Yellow 
3 33.211626 bar Yellow 
4 3.497118 foo White 
5 52.482879 bar Amber 
6 11.695231 foo White 
7 47.350269 foo Amber 

最後,您可以使用groupbyID代碼列聚集,並獲得各組的計數,如下所示:

g = df.groupby(["ID","Code"]).size() 
print g 

ID Code 
bar Amber  1 
    Yellow 2 
foo Amber  1 
    White  2  
    Yellow 2 

df2 = g.unstack() 
print df2 

Code Amber White Yellow 
ID 
bar  1 NaN  2 
foo  1  2  2 
+0

謝謝。我會在今天的工作中看到這個,並告訴你它是如何發生的。 – PrestonDocks 2013-05-03 05:22:23

+0

你能告訴我怎樣才能轉換這些結果。我認爲groupby製作了一系列無法​​旋轉的系列。 – PrestonDocks 2013-05-03 10:41:37

+0

'groupby'方法通過'MultiIndex'生成'Series'。您可以使用'unstack'將最低級索引轉換爲列,如上面編輯的答案所示。 – mtadd 2013-05-03 18:32:33

3

我知道這是來晚了一點,但我有同樣的問題,因爲你並想分享功能np.digitize。這聽起來像你想要的。

a = np.random.randint(0, 100, 50) 
grps = np.arange(0, 100, 10) 
grps2 = [1, 20, 25, 40] 
print a 
[35 76 83 62 57 50 24 0 14 40 21 3 45 30 79 32 29 80 90 38 2 77 50 73 51 
71 29 53 76 16 93 46 14 32 44 77 24 95 48 23 26 49 32 15 2 33 17 88 26 17] 

print np.digitize(a, grps) 
[ 4 8 9 7 6 6 3 1 2 5 3 1 5 4 8 4 3 9 10 4 1 8 6 8 6 
    8 3 6 8 2 10 5 2 4 5 8 3 10 5 3 3 5 4 2 1 4 2 9 3 2] 

print np.digitize(a, grps2) 
[3 4 4 4 4 4 2 0 1 4 2 1 4 3 4 3 3 4 4 3 1 4 4 4 4 4 3 4 4 1 4 4 1 3 4 4 2 
4 4 2 3 4 3 1 1 3 1 4 3 1]