2013-05-02 12 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, чтобы получить DataFrame в нужной форме:

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

6

Вы можете создать столбец в вашем DataFrame на основе ваших дней Позднего колонки с помощью map или apply функций следующим образом. Давайте сначала создадим образцы данных.

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 

Создайте вспомогательную функцию для преобразования данных из дней поздних столбцов и добавить столбец Code.

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 

Наконец, вы можете использовать groupby агрегировать в ID и кода колонны, и получить отсчеты групп следующим образом:

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

+0

Можете ли вы рассказать мне, как я могу изменить эти результаты. Я думаю, что groupby создает серию, которая не может быть повернута. – PrestonDocks

+0

Метод 'groupby' генерирует' Series' с 'MultiIndex'. Вы можете использовать 'unstack' для поворота индекса нижнего уровня в столбцы, как показано в отредактированном ответе выше. – mtadd

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] 
Смежные вопросы