2015-12-14 2 views
2

Я пытаюсь описать столбцы A, B средним, медианным, 25-м процентилем, 75-м процентили, стандартным отклонением.Pandas pivot_table percentile

df = pd.DataFrame({'A':[1,9,3,4,6,8,2,7], 
        'B':[2,4,7,8,9,2,5,6], 
        'S':['L','L','L','S','L','S','S','L']}) 

Вот что я сделал, и это сработало, так как я только 25-й процентиль:

df.pivot_table(columns = ['S'], values = ['A','B'], aggfunc = [np.mean, lambda x: np.percentile(x,25), np.median, np.std]) 

Но если я поставил 75-й процентиль в, он дает мне сообщение об ошибке:

Reindexing only valid with uniquely valued Index objects 

В идеале я хотел бы, чтобы в выходном списке появился 75-й процентиль в следующих столбцах.

+0

Как я прокомментировал ответ @ SteveMisuta - исходная ошибка возникает, потому что у вас есть две лямбда-функции, каждая из которых получает неявное имя «лямбда» в выходных столбцах. Конкретная переиндексация, необходимая для стержня, не будет работать с дублирующимися именами. Простое переименование одной или обеих лямбда-функций решит ее. Вы также можете рассмотреть возможность использования аргумента 'functools.partial' для аргументов карри. – ely

+0

@ Mr.F Что вы подразумеваете под «просто переименованием лямбда-функций»? Вы имеете в виду их замену? или называя их в кортеже вроде (75-й), лямбда x: np.percentile (x, 75))? Я попробовал последнего и не работал для меня. Есть ли другой способ «переименовать лямбда-функции»? Благодарю. –

+0

В Python объект функции имеет атрибут '__name__'. Обычно это имя функции, которое вы выбираете (т. Е. Вещь, следующая за 'def'). Для 'lambda', очевидно, нет имени, поэтому имя просто' '. Вы можете определить одну или обе функции как отдельные 'lambda', связанные с именем, например 'foo = lambda x: ...', а затем установить 'foo .__ name__' или определить' lambda's not как 'lambda', но как обычные функции Python, как в вашем ответе, и в этом случае их' __name__' будет установлено автоматически. – ely

ответ

2

Это будет делать то, что я думаю, что вы хотите, но без лямбда и несколько дополнительных линий:

def my25(g): 
    return np.percentile(g, 25) 

def my75(g): 
    return np.percentile(g, 75) 

df.pivot_table(columns = ['S'], values = ['A','B'], 
       aggfunc = [np.mean, my25, np.median, np.std, my75]) 

     mean  my25 median   std  my75  
S L  S L S  L S  L  S L S 
A 5.2 4.67 3 3.0  6 4 3.19 3.06 7 6.0 
B 5.6 5.00 4 3.5  6 5 2.70 3.00 7 6.5 

EDIT: на самом деле, можно использовать только лямбда-функции, если вы используете GroupBy агрегировать вместо pivot_table , и укажите имя каждой функции.

func_lst = [('mean',np.mean), ('25',lambda x:np.percentile(x,0.25)), 
      ('med',np.median), ('std',np.std), ('75',lambda x:np.percentile(x,0.75))] 

df.groupby ('S'). AGG (func_lst) .stack (уровень = 0) .unstack (уровень = 0) .swaplevel (0,1, ось = 1)

 mean  25 med   std  75  
S L  S L S L S  L  S L S 
A 5.2 4.67 3 3.0 6 4 3.19 3.06 7 6.0 
B 5.6 5.00 4 3.5 6 5 2.70 3.00 7 6.5 

Я думал, что использование func_lst в вызове pivot_table может работать, но это не так. В любом случае мне проще определить функции my25, my75 и использовать pivot_table.

+0

Вы должны добавить комментарий, чтобы объяснить, что переименование функции для 75-го процентиля решает проблему. В исходном случае ошибка возникает из-за наличия двух столбцов с именем «лямбда», а операция повторной индексации, необходимая для поворота, не будет работать с дублирующимися именами. – ely

Смежные вопросы