Как получить значения для нескольких столбцов сразу в Pandas DataFrame?

Учитывая Pandas DataFrame, который имеет несколько столбцов с категориальными значениями (0 или 1), можно ли удобно получить значение_количество для каждого столбца одновременно?

Например, предположим, что я генерирую DataFrame следующим образом:

import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randint(0, 2, (10, 4)), columns=list('abcd'))

Я могу получить DataFrame следующим образом:

   a  b  c  d
0  0  1  1  0
1  1  1  1  1
2  1  1  1  0
3  0  1  0  0
4  0  0  0  1
5  0  1  1  0
6  0  1  1  1
7  1  0  1  0
8  1  0  1  1
9  0  1  1  0

Как мне удобно получить значения для каждого столбца и получить следующее удобно?

   a  b  c  d
0  6  3  2  6
1  4  7  8  4

Мое текущее решение:

pieces = []
for col in df.columns:
    tmp_series = df[col].value_counts()
    tmp_series.name = col
    pieces.append(tmp_series)
df_value_counts = pd.concat(pieces, axis=1)

Но должен быть более простой способ, например, укладка, поворот или группировка?

Ответ 1

Просто позвоните apply и пройдите pd.Series.value_counts:

In [212]:
df = pd.DataFrame(np.random.randint(0, 2, (10, 4)), columns=list('abcd'))
df.apply(pd.Series.value_counts)

Out[212]:
   a  b  c  d
0  4  6  4  3
1  6  4  6  7

Ответ 2

На самом деле существует довольно интересный и продвинутый способ решения этой проблемы с помощью crosstab и melt

df = pd.DataFrame({'a': ['table', 'chair', 'chair', 'lamp', 'bed'],
                   'b': ['lamp', 'candle', 'chair', 'lamp', 'bed'],
                   'c': ['mirror', 'mirror', 'mirror', 'mirror', 'mirror']})

df

       a       b       c
0  table    lamp  mirror
1  chair  candle  mirror
2  chair   chair  mirror
3   lamp    lamp  mirror
4    bed     bed  mirror

Мы можем сначала расплавить DataFrame

df1 = df.melt()
df1

   columns   index
0        a   table
1        a   chair
2        a   chair
3        a    lamp
4        a     bed
5        b    lamp
6        b  candle
7        b   chair
8        b    lamp
9        b     bed
10       c  mirror
11       c  mirror
12       c  mirror
13       c  mirror
14       c  mirror

И затем используйте функцию кросс-таблицы для подсчета значений для каждого столбца. Это сохраняет тип данных как int, который не будет иметь место для текущего выбранного ответа:

pd.crosstab(index=df['index'], columns=df['columns'])

columns  a  b  c
index           
bed      1  1  0
candle   0  1  0
chair    2  1  0
lamp     1  2  0
mirror   0  0  5
table    1  0  0

Или в одной строке, которая расширяет имена столбцов до имен параметров с помощью ** (это продвинуто)

pd.crosstab(**df.melt(var_name='columns', value_name='index'))

Кроме того, value_counts теперь является функцией верхнего уровня. Таким образом, вы можете упростить текущий выбранный ответ на следующее:

df.apply(pd.value_counts)