2015-06-15 4 views
4

Я пытаюсь переформатировать таблицу на основе подсчетов в разных столбцах.Форматирование сводной таблицы в Python

df = pd.DataFrame({'Number': [1, 2, 3, 4, 5], 'X' : ['X1', 'X2', 'X3', 'X3', 'X3'], 'Y' : ['Y2','Y1','Y1','Y1', 'Y2'], 'Z' : ['Z3','Z1','Z1','Z2','Z1']}) 

    Number X Y Z 
0  1 X1 Y2 Z3 
1  2 X2 Y1 Z1 
2  3 X3 Y1 Z1 
3  4 X3 Y1 Z2 
4  5 X3 Y2 Z1 

Я хочу верхний ряд, чтобы быть Х отсортирован по частоте (X3 сначала, потому что он появляется в два раза) Тогда для каждого значения X, подсчитать частоту его Y и Z значений и распечатать тот, который показывает вверх по большинство.

X3 X2 X1 
Y Y1 Y1 Y2   
Z Z1 Z1 Z3 

До сих пор у меня есть код, который может сортировать

import pandas as pd 

df = pd.DataFrame({'Number': [1, 2, 3, 4, 5], 'X' : ['X1', 'X2', 'X3', 'X3', 'X3'], 'Y' : ['Y2','Y1','Y1','Y1', 'Y2'], 'Z' : ['Z3','Z1','Z1','Z2','Z1']}) 
pivot = df.pivot_table(index='X', columns=['Y', 'Z'], values = 'Number', aggfunc='count') 
# clean the table from NaNs (not necessary, but more beautiful): 
pivot.fillna(0, inplace=True) 
pivot['sum'] = pivot.sum(axis=1) 
pivot.sort('sum', ascending=False, inplace=True) 
df = pivot[:5].transpose() 
df.to_csv('sorted.csv') 

и выходы:

Y Z X3 X1 X2 
Y1 Z1 1 0 1 
Y1 Z2 1 0 0 
Y2 Z1 1 0 0 
Y2 Z3 0 1 0 
sum  3 1 1 

Но это еще не то, что я ищу, может кто-нибудь помочь мне с этим? Спасибо!

ответ

2

Вам понадобится пользовательская функция mode, потому что pandas.Series.mode не работает, если ничего не происходит по крайней мере дважды; хотя ниже один не самый эффективный один, он делает работу:

>>> mode = lambda ts: ts.value_counts(sort=True).index[0] 
>>> cols = df['X'].value_counts().index 
>>> df.groupby('X')[['Y', 'Z']].agg(mode).T.reindex(columns=cols) 
    X3 X1 X2 
Y Y1 Y2 Y1 
Z Z1 Z3 Z1 

к сведению, что в вашем образце кадра, X1 и X2 привязаны числа появлений.

1

Вы можете использовать счетчик, чтобы получить наиболее распространенные элементы. Это возвращается в виде кортежей пар элемента и количества вхождений, поэтому используйте использование списка для выбора только элементов (т. Е. I [0] - это элемент).

from collections import Counter 

X = [i[0] for i in Counter(df.X).most_common()] 

Затем используйте список понимание и .loc перебрать наиболее распространенные крестики и выбрать наиболее распространенный «Y» и значение «Z».

Y = [Counter(df.loc[df.X == x, 'Y']).most_common(1)[0][0] for x in X] 

Z = [Counter(df.loc[df.X == x, 'Z']).most_common(1)[0][0] for x in X] 

>>> pd.DataFrame({'X': X, 'Y': Y, 'Z': Z}).T 
    0 1 2 
X X3 X2 X1 
Y Y1 Y1 Y2 
Z Z1 Z1 Z3 
Смежные вопросы