Создание пузырьковой диаграммы из кросс-таблицы pandas

У меня есть фреймворк pandas с 4 столбцами и несколькими тысячами строк. Все записи либо True, либо False. Назовем фрейм данных «df» и столбцы «c0», «c1», «c2» и «c3». Меня интересует, сколько строк имеет каждое из 2 ^ 4 = 16 возможных значений истинности, поэтому я делаю кросс-таблицу:

xt = pd.crosstab([df.c0,df.c1],[df.c2,df.c3])
print(xt)

Это отображает красивую таблицу ячеек 4x4, каждая из которых содержит количество строк, которые имеют эту комбинацию значений истинности. Более того, пространственное расположение этих 16 ячеек имеет для меня значение и полезно. ОК, все хорошо. Но как мне это построить?

В частности, я хотел бы создать пузырьковую диаграмму этих подсчетов кросс-таблиц, т.е. графическое представление данных кросс-таблицы в том же пространственном расположении, что и в таблице, но теперь замените каждое число на цветная капля (скажем, круг) площадью, пропорциональной количеству. Итак, это диаграмма рассеяния с четырьмя (c0, c1) значениями истинности по одной оси, четырьмя (c2, c3) значениями истинности по другой оси и регулярной сеткой 4x4 из кругов разного размера.

Я знаю, что могу создать пузырьковую диаграмму, передав данные о размере ключевому слову 's' функции разброса matplotlib, но я не могу найти простой способ сообщить пандам о создании диаграммы рассеяния, которая использует заголовки столбцов в качестве x-координат , заголовки строк в виде y-координат и значения данных в виде размеров пузырьков для диаграммы рассеяния. Мне повезло: я преобразовал фрейм данных в массив numpy и построил его, но затем я теряю структуру меток осей из кросс-таблицы. (Да, я мог бы просто перестроить метки галочки вручную, но я хотел бы иметь возможность алгоритмически воспроизвести эту задачу для других аналогичных наборов данных.)

РЕДАКТИРОВАТЬ: Вдохновленный ответом @piRSquared ниже, вот некоторые пояснения того, о чем я прошу. Этот код близок к тому, что я хочу, но оси на результирующем графике потеряли какую-либо информацию о многоуровневой структуре меток MultiIndex объекта кросс-таблицы.

import pandas as pd
import numpy as np

randomData=np.random.choice([True,False],size=(100, 4),p=[.6,.4])
df = pd.DataFrame(randomData, columns=['c0','c1','c2','c3'])
xt=pd.crosstab([df.c0,df.c1], [df.c2,df.c3])

x=np.array([range(4)]*4)
y=x.transpose()[::-1,:]
pl.scatter(x,y,s=np.array(xt)*10)

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

c2          False       True       
c3          False True  False True 
c0    c1                           
False False     0     8     4     9
      True      3     2     4    10
True  False     7     5     3    10
      True      2     7     8    18

Или, возможно, что-то напоминающее то, что здесь выражают легенда и ось абсцисс:

xt.plot(kind='bar',stacked=True)

(Другая ссылка на изображение графика: график стека, который знает о многоиндексной природе его базового фрейма данных.)


person Sean P Robinson    schedule 31.08.2017    source источник


Ответы (1)


Надеюсь это поможет

df = pd.DataFrame(
    np.random.choice(
        np.arange(6),
        size=(100, 2),
        p=np.arange(1, 7) / 21
    ), columns=list('AB')
)

c = pd.crosstab(df.A, df.B).stack().reset_index(name='C')

c.plot.scatter('A', 'B', s=c.C * 10)

введите описание изображения здесь

person piRSquared    schedule 31.08.2017
comment
Это близко к выполнению работы (и это действительно умно!), Но кросс-таблица в исходной задаче многоиндексирована, и мне не очевидно, как экстраполировать этот ответ на случай multiIndex. - person Sean P Robinson; 01.09.2017
comment
Для меня не очевидно, как вы хотите, чтобы это выглядело. Можешь нарисовать, сфотографировать и выложить. - person piRSquared; 01.09.2017
comment
Хорошо, я отредактирую свой пост, чтобы уточнить, о чем я прошу. - person Sean P Robinson; 01.09.2017