Как Pivot-и-Sort для двух столбцов в Python? - PullRequest
0 голосов
/ 13 февраля 2019

У меня очень большой массив данных о клиентах, категориях товаров и их цене.Я хотел бы провести несколько начальных расследований:

  • Определите лучших, например, n = 5 клиентов на основе их ВСЕГО расходов.
  • для каждого из этих клиентов, определите категории, которые они тратят.
  • Затем, возможно, создайте график в порядке убывания, показывающий главного клиента с его именем как X и его расходами как Y. Длякаждый, как показать свои торговые категории?

это потребует поворота и сортировки.Это генератор данных-примеров, благодаря здесь .

import numpy as np
import pandas as pd
from numpy.core.defchararray import add

np.random.seed(42)
n = 20

cols = np.array(['cust', 'cat'])
arr1 = (np.random.randint(5, size=(n, 2)) // [2, 1]).astype(str)
df = pd.DataFrame(
    add(cols, arr1), columns=cols
).join(
    pd.DataFrame(np.random.rand(n, 1).round(2)).add_prefix('val')
)
print(df)

df.pivot_table(index=['cust'],values=['val0'],aggfunc=[np.sum])

df.pivot_table(index=['cust','cat'],values=['val0'],aggfunc=[np.size,np.sum])

# the order according the previous line should be cust1,cust0,cust2. How to do? The following is the desired output in this case.

                size sum
                val0 val0
cust    cat
cust1   cat4    6.0  4.27
        cat3    2.0  1.07
        cat2    2.0  0.98
        cat0    2.0  0.44
        cat1    2.0  0.43

cust0   cat1    1.0  0.94
        cat4    1.0  0.91
        cat2    1.0  0.66
        cat3    1.0  0.03

cust2   cat1    2.0  1.25

Большое спасибо!

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Не уверен, что я понял, какой именно обзор вам нужен, но это также возможно при использовании groupby, а затем метода agg, подобного следующему:

overview = df.groupby('cust').agg({'val0':'sum',
                                   'cat':'max'}).reset_index().sort_values('val0', ascending=False)

    cust    val0    cat
1   cust1   7.19    cat4
0   cust0   2.54    cat4
2   cust2   1.25    cat1

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

Вам не нужно использовать функцию reset_index(), в этом случае она дает следующее:

overview = df.groupby('cust').agg({'val0':'sum',
                                   'cat':'max'}).sort_values('val0', ascending=False)


        val0    cat
cust        
cust1   7.19    cat4
cust0   2.54    cat4
cust2   1.25    cat1

И Наконец Если вы хотите, чтобы 5 лучших клиентов, вы можете просто использовать .head(5), так как значения уже отсортированы по убыванию:

overview = df.groupby('cust').agg({'val0':'sum',
                                   'cat':'max'}).sort_values('val0', ascending=False).head(5)
0 голосов
/ 13 февраля 2019

Здесь лучше агрегировать sum во избежание MultiIndex в столбцах.

Первый агрегат sum:

s = df.groupby('cust')['val0'].sum()
print (s)
cust
cust0    2.54
cust1    7.19
cust2    1.25
Name: val0, dtype: float64

Затем получить верхние значения по Series.nlargest:

top5 = s.nlargest(5)
print (top5)
cust
cust1    7.19
cust0    2.54
cust2    1.25
Name: val0, dtype: float64

При необходимости отфильтруйте только верхние 5 значений по boolean indexing и isin:

df1 = df[df['cust'].isin(top5.index)].copy()
#print(df1)

Дляправильное упорядочение cust создание упорядоченных категорий и агрегирование по обоим отфильтрованным столбцам, последняя сортировка по первому уровню cust со столбцом size:

df1['cust'] = pd.Categorical(df1['cust'], ordered=True, categories=top5.index)
df2 = (df1.groupby(['cust','cat'])['val0'].agg([np.size,np.sum])
         .sort_values(['cust','size'], ascending=[True, False])
         .reset_index())
print (df2)
    cust   cat  size   sum
0  cust1  cat4   6.0  4.27
1  cust1  cat0   2.0  0.44
2  cust1  cat1   2.0  0.43
3  cust1  cat2   2.0  0.98
4  cust1  cat3   2.0  1.07
5  cust0  cat1   1.0  0.94
6  cust0  cat2   1.0  0.66
7  cust0  cat3   1.0  0.03
8  cust0  cat4   1.0  0.91
9  cust2  cat1   2.0  1.25

Последний поворот и график по DataFrame.plot.bar:

df2.pivot('cust','cat','size').plot.bar()
...