2015-06-01 4 views
3

У меня есть набор данных, как показано ниже, и мне нужно все различные веса для каждой категории в одной строке и подсчетаКак расширить данные на основе одного столбца в python (транспонировать)?

Sample_data 

    category weights 
1 aa  3.2 
2 aa  2.2 
3 aa  4.2 
4 bb  3.5 
5 bb  4.5 
6 aa  0.5 
7 cc  0.6 
8 bb  7.5 
9 cc  6.6 
10 dd  2.2 
11 aa  3.3 
12 bb  4.4 
13 cc  5.5 
14 dd  6.6 

И то, что мне нужно, это подсчет каждой уникальной категории и различные веса каждой категории в той же строки.

Expected output: 

category count weight1 weight2 weight3 weight4 weight5 
1 aa  5  3.2  2.2  4.2  0.5  3.3 
2 bb  4  3.5  4.5  7.5  4.4 
3 cc  3  0.6  6.6  5.5 
4 dd  2  2.2  6.6 

Я думал

sampledata['category'].groupby(level = 0) 

будет работать, но это не так. Может ли кто-нибудь помочь мне, как это сделать в python.

+1

Не могли бы вы расширить о том, как 'sampledata' точно выглядит? Я имею в виду, что это 'category' и' weightights' два списка или это массив или ...? – Callahan

+1

это панда данных с двумя категориями переменных и весами – ashok

+0

Это сообщение (http://stackoverflow.com/questions/773/how-do-i-use-pythons-itertools-groupby) прекрасно объясняет, как использовать itertools.groupby , – Tim

ответ

2

я мог бы сократить это, но в следующих работах:

In [51]: 

cat = df.groupby('category')['weights'].agg({'count':'count', 'weight_cat':lambda x: list(x)}).reset_index() 
cat 
Out[51]: 
    category count     weight_cat 
0  aa  5 [3.2, 2.2, 4.2, 0.5, 3.3] 
1  bb  4  [3.5, 4.5, 7.5, 4.4] 
2  cc  3   [0.6, 6.6, 5.5] 
3  dd  2     [2.2, 6.6] 
In [52]: 

cat = cat.join(cat['weight_cat'].apply(lambda x: pd.Series(x))) 
cat 
Out[52]: 
    category count     weight_cat 0 1 2 3 4 
0  aa  5 [3.2, 2.2, 4.2, 0.5, 3.3] 3.2 2.2 4.2 0.5 3.3 
1  bb  4  [3.5, 4.5, 7.5, 4.4] 3.5 4.5 7.5 4.4 NaN 
2  cc  3   [0.6, 6.6, 5.5] 0.6 6.6 5.5 NaN NaN 
3  dd  2     [2.2, 6.6] 2.2 6.6 NaN NaN NaN 
In [68]: 

rename_cols = [col for col in cat if type(col) == int] 
rename_weight_cols = ['weight'+str(col + 1) for col in rename_cols] 
d = dict(zip(rename_cols, rename_weight_cols)) 
cat.rename(columns = d,inplace=True) 
cat 
Out[68]: 
    category count     weight_cat weight1 weight2 weight3 \ 
0  aa  5 [3.2, 2.2, 4.2, 0.5, 3.3]  3.2  2.2  4.2 
1  bb  4  [3.5, 4.5, 7.5, 4.4]  3.5  4.5  7.5 
2  cc  3   [0.6, 6.6, 5.5]  0.6  6.6  5.5 
3  dd  2     [2.2, 6.6]  2.2  6.6  NaN 

    weight4 weight5 
0  0.5  3.3 
1  4.4  NaN 
2  NaN  NaN 
3  NaN  NaN 

Так что выше делает первую группу в столбце «категории» и выполнить агрегацию на колонке веса, мы создаем столбец подсчета, а затем мы переходим все значения для этой группы в список и добавить ,

Затем я вызываю apply в этот список, чтобы превратить его в серию, это автоматически сгенерирует имена столбцов 0..4.

Затем я создаю dict, чтобы переименовать столбцы с весом от 1 до 5 по желанию.

+0

Большое спасибо. Вы сделали мой день. – ashok

0

Учитывая, что данные образцы в виде списка словарей называется data, где каждый словарь имеет category ключ и weight ключ, то следующий код даст вам то, что вам нужно:

trans_data = {} 
for item in data: 
    if item['category'] in trans_data: 
     trans_data[item['category']]['count'] += 1 
     trans_data[item['category']]['weights'].append(item['weight']) 
    else: 
     trans_data[item['category']] = {'count': 1, 'weights': [item['weight'],]} 

предполагается, что структура данных data иметь следующий вид:

data = [{'category': 'aa', 'weight': 3.2}, {'category': 'bb', 'weight': 2.2}, {'category': 'aa', 'weight': 1.1}] 
+0

Op добавили, что данные представляют собой тип данных 'pandas'. Во всяком случае, список 'dict'? Скорее один 'dict' с ключами' category' и 'weightights'. – Callahan

+0

@OrenD попробовал ваш код и производит следующую ошибку TypeError: строковые индексы должны быть целыми, а не str. Я не понимал, как с этим бороться. – ashok

+0

@ Callahan, увидел разъяснения re: panda после факта. Предлагаемые выборочные данные не имеют смысла быть представленными в одном dict. – OrenD

1

Вы также можете использовать unstack после сброса индекса каждой группы:

dfw = df.groupby(['category'])['weights'].apply(lambda i: i.reset_index(drop=True)).unstack(level=1) 

размера (здесь 'count') каждой группы df.groupby(['category']).size().

dfw.rename(columns=lambda x: 'weight'+ str(x+1), inplace=True) # string concatenation to give column labels 
dfw.insert(0, 'count', df.groupby(['category']).size()) #insert count at position 0 

Это дает:

  count weight1 weight2 weight3 weight4 weight5 
category              
aa   5  3.2  2.2  4.2  0.5  3.3 
bb   4  3.5  4.5  7.5  4.4  NaN 
cc   3  0.6  6.6  5.5  NaN  NaN 
dd   2  2.2  6.6  NaN  NaN  NaN 
Смежные вопросы