Использование pandas pivot_table со столбцами Interval приводит к TypeError - PullRequest
1 голос
/ 19 июня 2019
      cat1             cat2                       col_a             col_b
0    (34.0, 38.0]    (15.9, 47.0]             29               10
1    (34.0, 38.0]    (15.9, 47.0]             37               22
2    (28.0, 34.0]    (47.0, 56.0]              3               13
3    (34.0, 38.0]    (47.0, 56.0]             15                7
4    (28.0, 34.0]    (56.0, 67.0]             42               20
5    (28.0, 34.0]    (47.0, 56.0]             31               23
6    (28.0, 34.0]    (56.0, 67.0]             26               17
7    (28.0, 34.0]    (56.0, 67.0]              7                1
8    (28.0, 34.0]    (56.0, 67.0]             36               19
9    (19.0, 28.0]    (56.0, 67.0]              5                7
10   (19.0, 28.0]    (56.0, 67.0]             21                5
11   (28.0, 34.0]    (67.0, 84.0]             37               13

В приведенном выше кадре данных я хочу выполнить эту операцию сводной таблицы, используя pandas

pd.pivot_table(df, index='cat1', columns='cat2', values='col_a')

, но получаю ошибку:

TypeError: Cannot cast array data from dtype('float64') to dtype('<U32') according to the rule 'safe'

И col_a, иcol_b имеют тип int32, а cat1 и cat2 имеют категориальный тип.Как мне избавиться от этой ошибки?

1 Ответ

4 голосов
/ 21 июня 2019

Это ошибка, связанная с поворотными столбцами, которые являются интервалами (см. GH25814 ) и будут исправлены для v0.25.Также просмотрите этот связанный вопрос, используя crosstab: Кросс-таблица Pandas в столбцах CategoryoricalDType. Вызывает TypeError

. Ниже приведены некоторые параметры.Для агрегирования вам нужно будет использовать pivot_table и преобразовать ваши категориальные столбцы в строку перед поворотом.

df2 = df.assign(cat1=df['cat1'].astype(str), cat2=df['cat2'].astype(str))
# to aggregate by taking the mean of col_a
df2.pivot_table(index='cat1', columns='cat2', values='col_a', aggfunc='mean')

Предостережение заключается в том, что вы теряете преимущество от того, что ваш индекс и столбцы являются интервалами.

Другим вариантом может быть поворот по категориальным кодам, а затем переназначение категорий:

df2 = df.assign(cat1=df['cat1'].cat.codes, cat2=df['cat2'].cat.codes)
pivot = df2.pivot_table(
    index='cat1', columns='cat2', values='col_a', aggfunc='mean')

pivot.index = df['cat1'].cat.categories
pivot.columns = df['cat2'].cat.categories

Это назначение будет работать, поскольку pivot_table сортирует интервалы заранее.


Образец минимального кода

import pandas as pd
import numpy as np

np.random.seed(0)

df = pd.DataFrame({
    'cat1': np.random.choice(100, 10), 
    'cat2': np.random.choice(100, 10), 
    'col_a': np.random.randint(1, 50, 10)})

df['cat1'] = pd.cut(df['cat1'], bins=np.arange(0, 101, 10))
df['cat2'] = pd.cut(df['cat2'], bins=np.arange(0, 101, 10))

df
          A         B   C
0  (40, 50]  (60, 70]  18
1  (40, 50]  (80, 90]  38
2  (60, 70]  (80, 90]  26
3  (60, 70]  (10, 20]  14
4  (60, 70]  (50, 60]   9
5   (0, 10]  (60, 70]  10
6  (80, 90]  (30, 40]  21
7  (20, 30]  (80, 90]  17
8  (30, 40]  (40, 50]   6
9  (80, 90]  (80, 90]  16

(df.assign(cat1=df['cat1'].astype(str), cat2=df['cat2'].astype(str))
   .pivot_table(index='cat1', columns='cat2', values='col_a', aggfunc='mean'))

cat2      (10, 20]  (30, 40]  (40, 50]  (50, 60]  (60, 70]  (80, 90]
cat1                                                                
(0, 10]        NaN       NaN       NaN       NaN      10.0       NaN
(20, 30]       NaN       NaN       NaN       NaN       NaN      17.0
(30, 40]       NaN       NaN       6.0       NaN       NaN       NaN
(40, 50]       NaN       NaN       NaN       NaN      18.0      38.0
(60, 70]      14.0       NaN       NaN       9.0       NaN      26.0
(80, 90]       NaN      21.0       NaN       NaN       NaN      16.0
...