Как создать строку суммы и столбец суммы в пандах? - PullRequest
0 голосов
/ 21 ноября 2018

Я прохожу курс Академии хана по статистике, чтобы немного освежить свои студенческие годы и как способ научить меня работать с пандами и другим научным Python.

I 'У меня есть таблица, которая выглядит следующим образом от Академии Хана:

             | Undergraduate | Graduate | Total
-------------+---------------+----------+------
Straight A's |           240 |       60 |   300
-------------+---------------+----------+------
Not          |         3,760 |      440 | 4,200
-------------+---------------+----------+------
Total        |         4,000 |      500 | 4,500

Я бы хотел воссоздать эту таблицу с помощью панд.Конечно, я мог бы создать DataFrame, используя что-то вроде

"Graduate": {...},
"Undergraduate": {...},
"Total": {...},

Но это кажется наивным подходом, который быстро упал бы и просто не был бы расширяемым.

Я получилне итоговая часть таблицы вот так:

df = pd.DataFrame(
    {
        "Undergraduate": {"Straight A's": 240, "Not": 3_760},
        "Graduate": {"Straight A's": 60, "Not": 440},
    }
)
df

Я искал и нашел пару многообещающих вещей, таких как:

df['Total'] = df.sum(axis=1)

Но я ничего не нашелужасно элегантно.

Я нашел функцию crosstab, которая выглядит так, как будто она должна делать то, что я хочу, но похоже, что для этого мне нужно было бы создать фрейм данных, состоящий из 1/0 длявсе эти значения, которые кажутся глупыми, потому что у меня уже есть агрегат.

Я нашел несколько подходов, которые, кажется, вручную строят новую итоговую строку, но кажется, что должен быть лучший способ, что-тонапример:

totals(df, rows=True, columns=True)

или что-то в этом роде.

Существует ли это в пандах, или мне просто нужно собраться со своим собственным подходом?

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018

Исходные данные:

>>> df = pd.DataFrame(dict(Undergraduate=[240, 3760], Graduate=[60, 440]), index=["Straight A's", "Not"])
>>> df
Out: 
              Graduate  Undergraduate
Straight A's        60            240
Not                440           3760

Вы можете использовать df.T только для воссоздания этой таблицы:

>>> df_new = df.T
>>> df_new
Out: 
               Straight A's   Not
Graduate                 60   440
Undergraduate           240  3760

После вычисления Total по строкам и столбцам:

>>> df_new.loc['Total',:]= df_new.sum(axis=0)
>>> df_new.loc[:,'Total'] = df_new.sum(axis=1)
>>> df_new
Out: 
               Straight A's     Not   Total
Graduate               60.0   440.0   500.0
Undergraduate         240.0  3760.0  4000.0
Total                 300.0  4200.0  4500.0
0 голосов
/ 21 ноября 2018

Или в два этапа, используя предложенную вами функцию .sum() (которая также может быть немного более читабельной):

import pandas as pd

df = pd.DataFrame( {"Undergraduate": {"Straight A's": 240, "Not": 3_760},"Graduate": {"Straight A's": 60, "Not": 440},})

#Total sum per row: 
df.loc['Total',:]= df.sum(axis=0)

#Total sum per column: 
df.loc[:,'Total'] = df.sum(axis=1)

Вывод:

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500
0 голосов
/ 21 ноября 2018

Исходные данные, используя crosstab, если вы просто основываетесь на своем входе, вам просто нужно melt до crosstab

s=df.reset_index().melt('index')
pd.crosstab(index=s['index'],columns=s.variable,values=s.value,aggfunc='sum',margins=True)
Out[33]: 
variable      Graduate  Undergraduate   All
index                                      
Not                440           3760  4200
Straight A's        60            240   300
All                500           4000  4500

Игрушечные данные

df=pd.DataFrame({'c1':[1,2,2,3,4],'c2':[2,2,3,3,3],'c3':[1,2,3,4,5]}) 
# before `agg`, I think your input is the result after `groupby` 
df
Out[37]: 
   c1  c2  c3
0   1   2   1
1   2   2   2
2   2   3   3
3   3   3   4
4   4   3   5


pd.crosstab(df.c1,df.c2,df.c3,aggfunc='sum',margins
=True)
Out[38]: 
c2     2     3  All
c1                 
1    1.0   NaN    1
2    2.0   3.0    5
3    NaN   4.0    4
4    NaN   5.0    5
All  3.0  12.0   15
0 голосов
/ 21 ноября 2018

append и assign

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

append

Я использую append для укладки Series или DataFrame по вертикали.Он также создает copy, чтобы я мог продолжать цепочку.

assign

Я использую assign для добавления столбца.Тем не менее, DataFrame, над которым я работаю, находится между ними.Поэтому я использую lambda в аргументе assign, который сообщает Pandas, чтобы применить его к вызывающему DataFrame.


df.append(df.sum().rename('Total')).assign(Total=lambda d: d.sum(1))

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500

Забавная альтернатива

Использует drop с errors='ignore', чтобы избавиться от потенциально существующих Total строк и столбцов.

Кроме того, все еще в очереди.

def tc(d):
  return d.assign(Total=d.drop('Total', errors='ignore', axis=1).sum(1))

df.pipe(tc).T.pipe(tc).T

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...