2015-12-08 34 views
1

我有一列需要轉換爲18-29,30-39,40-49,50-59,60-69和70+年齡範圍的年齡值:試圖在python中創建分組變量

對於一些DF數據的 '文件' 的一個例子,我有:

enter image description here

,並希望得到:

enter image description here

我三ED以下內容:

file['agerange'] = file[['age']].apply(lambda x: "18-29" if (x[0] > 16 
             or x[0] < 30) else "other") 

我寧願不只是做一個GROUPBY因爲桶的大小並不統一,但我很開放的,作爲一個解決方案,如果它的工作原理。

在此先感謝!

+0

僅供參考,這是不引發錯誤,它只是給了我所有的空值 – Josh

+0

您沒有提供足夠的數據,輸入(什麼是文件?你爲什麼影響內置'文件'?什麼是適用的?),預期輸出是什麼? – JustMe

+0

好的,我添加了一些示例數據。文件是我的DF的名稱。我也知道這個公式是不完整的。我在第一部分不工作後發佈在這裏... – Josh

回答

1

它看起來像你正在使用熊貓圖書館。它們包括這樣的功能:http://pandas.pydata.org/pandas-docs/version/0.16.0/generated/pandas.cut.html

這裏是我的嘗試:

import pandas as pd 

ages = pd.DataFrame([81, 42, 18, 55, 23, 35], columns=['age']) 

bins = [18, 30, 40, 50, 60, 70, 120] 
labels = ['18-29', '30-39', '40-49', '50-59', '60-69', '70+'] 
ages['agerange'] = pd.cut(ages.age, bins, labels = labels,include_lowest = True) 

print(ages) 

    age agerange 
0 81  70+ 
1 42 40-49 
2 18 18-29 
3 55 50-59 
4 23 18-29 
5 35 30-39 
0

您可以使用itertools.groupby使用// 10作爲關鍵功能。

In [10]: ages = [random.randint(18, 99) for _ in range(100)] 

In [11]: [(key, list(group)) for (key, group) in itertools.groupby(sorted(ages), key=lambda x: x // 10)] 
Out[11]: 
[(1, [18]), 
(2, [20, 21, 21, 22, 23, 24, 25, 26, 26, 26, 27, 27, 28]), 
(3, [30, 30, 32, 32, 34, 35, 36, 37, 37]), 
(4, [41, 42, 42, 43, 43, 44, 45, 47, 48]), 
(5, [50, 51, 52, 53, 54, 55, 56, 56, 56, 56, 57, 58, 58, 58, 58]), 
(6, [60, 61, 62, 62, 62, 65, 65, 66, 66, 66, 66, 67, 69, 69, 69]), 
(7, [71, 71, 72, 72, 73, 75, 75, 77, 77, 78]), 
(8, [83, 83, 83, 83, 84, 84, 85, 86, 86, 87, 87, 88, 89, 89, 89]), 
(9, [91, 91, 92, 92, 93, 94, 97, 97, 98, 98, 99, 99, 99])] 

記住,groupby需要排序的數據,雖然如此,排序第一。或者使用字典和循環手動執行。

In [14]: groups = collections.defaultdict(list) 

In [15]: for x in ages: 
    ....:  groups[x//10].append(x) 

In [16]: groups 
Out[16]: defaultdict(<type 'list'>, {1: [18], 
      2: [26, 28, 21, 20, 26, 24, 21, 27, 25, 23, 27, 26, 22], 
      3: [37, 30, 32, 32, 35, 30, 36, 37, 34], 
      4: [45, 42, 43, 41, 47, 43, 48, 44, 42], 
      5: [52, 56, 58, 55, 58, 51, 58, 58, 57, 56, 53, 56, 50, 54, 56], 
      6: [69, 65, 62, 61, 65, 66, 66, 62, 69, 66, 67, 66, 60, 62, 69], 
      7: [71, 77, 71, 72, 77, 73, 78, 72, 75, 75], 
      8: [87, 83, 84, 86, 86, 83, 83, 87, 85, 83, 89, 88, 84, 89, 89], 
      9: [99, 92, 99, 98, 91, 94, 97, 92, 98, 97, 91, 93, 99]}) 

對於更復雜的分組,可以使key功能任意複雜。例如,將每個70歲及以上的人放入一個組中,請使用lambda x: min(x // 10, 7)。這適用於這兩種方法。你甚至可以將密鑰轉換爲字符串,如果你喜歡:

In [23]: keyfunc = lambda x: "{0}0-{0}9".format(x//10) if x < 70 else "70+" 
In [24]: [(key, list(group)) for (key, group) in itertools.groupby(sorted(ages), key=keyfunc)] 
Out[24]: 
[('10-19', [18]), 
('20-29', [20, 21, 21, 22, 23, 24, 25, 26, 26, 26, 27, 27, 28]), 
('30-39', [30, 30, 32, 32, 34, 35, 36, 37, 37]), 
('40-49', [41, 42, 42, 43, 43, 44, 45, 47, 48]), 
('50-59', [50, 51, 52, 53, 54, 55, 56, 56, 56, 56, 57, 58, 58, 58, 58]), 
('60-69', [60, 61, 62, 62, 62, 65, 65, 66, 66, 66, 66, 67, 69, 69, 69]), 
('70+', [all the rest]] 
+0

感謝您的快速響應。 // 10不會工作,因爲範圍並不全是統一的。難道這不是在70+的範圍以及18-29之間? – Josh

+0

@Josh你可以使你的關鍵功能任意複雜。看我的編輯。 –

+0

這是否也適用於浮點值? – Josh

1

不會嵌套循環是最簡單的解決方案嗎?

import random 
ages = [random.randint(18, 100) for _ in range(100)] 
age_ranges = [(18,29), (30,39), (40,49), (50,59), (60,69),(70,)] 

for a in ages: 
     for r in age_ranges: 
       if a >= r[0] and (len(r) == 1 or a < r[1]): 
         print a,r 
         break 
+0

我的想法是嵌套的,如果在lambda函數。這是天生的錯,還是隻是更清潔? – Josh

+0

您可以使用lambda函數: 'map(lambda x:「18-29」if(x> = 18)and(x <30)else「other」,[1,10,20,30]) ' – igon

+0

我在使用map時遇到屬性錯誤,而當我嘗試應用它時,它首先讓我將x更改爲x [0],然後返回所有null值 – Josh

0

一個朋友想出了這個響應脫機工作: 高清age_buckets(X): 如果x < 30: 回報'18 -29' ELIF X < 40: 回報'30 -39 ' elif的X < 50: 返回'40 -49' elif的X < 60: 返回'50 -59' elif的X < 70: 返回'60 -69' elif的X> = 70: 返回'70 +」 其他: 回報‘其他’

file['agerange'] = file.age.apply(age_buckets) 

謝謝大家誰在這個花了裂縫!