Как считать по группе в R

Подсчет по нескольким группам - иногда называемый отчетами с перекрестными таблицами - может быть полезным способом просмотра данных, начиная от опросов общественного мнения до медицинских тестов. Например, как люди голосовали по полу и возрасту? Сколько мужчин и женщин среди разработчиков программного обеспечения, использующих как R, так и Python?

Есть много способов сделать такой подсчет по категориям в R. Здесь я хотел бы поделиться некоторыми из моих любимых.

Для демонстраций в этой статье я буду использовать подмножество опроса разработчиков Stack Overflow, в котором разработчики опрашиваются по десяткам тем, от заработной платы до используемых технологий. Я сокращу его столбцами для используемых языков, пола и того, кодируют ли они для хобби. Я также добавил свой собственный столбец LanguageGroup, чтобы узнать, использовал ли разработчик R, Python, оба или ни один из них.

Если вы хотите продолжить, на последней странице этой статьи есть инструкции о том, как загрузить и обработать данные, чтобы получить тот же набор данных, который я использую.

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

str (mydata) 'data.frame': 83379 набл. из 4 переменных: $ Gender: chr "Man" "Man" "Man" "Man" ... $ LanguageWorkedWith: chr "HTML / CSS; Java; JavaScript; Python" "C ++; HTML / CSS; Python" "HTML / CSS "" C; C ++; C #; Python; SQL "... $ Hobbyist: chr" Да "" Нет "" Да "" Нет "... $ LanguageGroup: chr" Python "" Python "" Ни то, ни другое "" Python "...

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

Пакет дворника

Итак, какова гендерная разбивка в каждой языковой группе? Для этого типа отчетов во фрейме данных одним из моих популярных инструментов является tabyl()функция пакета janitor. 

Базовая tabyl()функция возвращает фрейм данных со счетчиками. Имя первого столбца, которое вы добавляете к tabyl()аргументу, становится строкой , а второе - столбцом

библиотека (дворник) табыл (mydata, Gender, LanguageGroup)

Пол Оба Нет Python R Мужчина 3264 43908 29044 969 Женщина 374 3705 1940 175

Что хорошо, так tabyl()это то, что проценты тоже очень легко генерировать. Если вы хотите видеть проценты для каждого столбца вместо исходных итогов, добавьте adorn_percentages("col"). Затем вы можете передать эти результаты в функцию форматирования, например  adorn_pct_formatting().

tabyl (mydata, Gender, LanguageGroup)%>%

adorn_percentages ("col")%>%

adorn_pct_formatting (цифры = 1)

Пол Оба Не Python R Мужчина 89,7% 92,2% 93,7% 84,7% Женщина 10,3% 7,8% 6,3% 15,3%

Чтобы увидеть проценты по строкам, добавьте adorn_percentages("row")

Если вы хотите добавить третью переменную, например Hobbyist, это тоже легко.

tabyl (mydata, Gender, LanguageGroup, Hobbyist)%>%

adorn_percentages ("col")%>%

adorn_pct_formatting (цифры = 1)

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

$ Нет Пол Ни один Python R Мужчина 79,6% 86,7% 86,4% 74,6% Женщина 20,4% 13,3% 13,6% 25,4% $ Да Пол Оба Ни один Python R Мужчина 91,6% 93,9% 95,0% 88,0% Женщина 8,4% 6,1% 5,0% 12,0%

Пакет CGPfunctions

В пакете CGPfunctions стоит поискать несколько быстрых и простых способов визуализации данных кросс-таблицы. Установите его из CRAN обычным install.packages("CGPfunctions").

В пакете есть две интересующие функции для проверки кросс-таблиц: PlotXTabs()и PlotXTabs2(). Этот код возвращает гистограммы данных (первый график ниже):

библиотека (CGP-функции)

PlotXTabs (mydata)

Снимок экрана Шарон Махлис,

PlotXTabs2(mydata) создает график с другим видом и некоторые статистические сводки (второй график слева).

Если вам не нужны или не нужны эти сводки, вы можете удалить их results.subtitle = FALSE, например  PlotXTabs2(mydata, LanguageGroup, Gender, results.subtitle = FALSE).

Снимок экрана Шарон Махлис,

PlotXTabs2()имеет несколько десятков вариантов аргументов, включая заголовок, заголовок, легенды, цветовую схему и один из четырех типов графика: сторона, стопка, мозаика или процент. Есть также параметры, знакомые пользователям ggplot2, такие как ggtheme и palette. Вы можете увидеть более подробную информацию в файле справки функции.

Пакет vtree

Пакет vtree генерирует графику для кросс- таблиц, а не графиков. Запуск основной vtree()функции для одной переменной, например 

библиотека (vtree)

vtree (mydata, "LanguageGroup")

дает вам такой базовый ответ:

Шэрон Махлис,

Я не в восторге от цветовых значений по умолчанию, но вы можете поменять местами палитру RColorBrewer. Аргумент палитры vtree использует номера палитры , а не имена; вы можете увидеть, как они пронумерованы в документации пакета vtree. Я мог бы, например, выбрать 3 для зеленого и 5 для фиолетового. К сожалению, эти значения по умолчанию дают вам более интенсивный цвет для меньшего количества чисел, что не всегда имеет смысл (и не подходит для меня в этом примере). Я могу изменить это поведение по умолчанию, sortfill = TRUEчтобы использовать более интенсивный цвет для более высокого значения. 

vtree (mydata, "LanguageGroup", palette = 3, sortfill = TRUE)

Шэрон Махлис,

Если вы обнаружите, что темный цвет затрудняет чтение текста, есть несколько вариантов. Один из вариантов - использовать простой аргумент, например  vtree(mydata, "LanguageGroup", plain = TRUE). Другой вариант - установить один цвет заливки вместо палитры, используя fillcolorаргумент, например  vtree(mydata, LanguageGroup", fillcolor = "#99d8c9").

Чтобы просмотреть две переменные в отчете с перекрестной таблицей, просто добавьте имя второго столбца и палитру или цвет, если вы не хотите использовать значение по умолчанию. Вы можете использовать простой вариант или указать две палитры или два цвета. Ниже я выбрал определенные цвета вместо палитр, а также повернул график, чтобы он читался вертикально.

vtree (mydata, c ("LanguageGroup", "Пол"),

fillcolor = c (LanguageGroup = "# e7d4e8", Gender = "# 99d8c9"),

горизонт = ЛОЖЬ)

Шэрон Махлис,

You can add more than two categories, although it gets a bit harder to read and follow as the tree grows. If you’re only interested in some of the branches, you can specify which to display with the keep argument. Below, I set vtree() to show only people who use R without Python or who use both R and Python.

vtree(mydata, c("Gender", "LanguageGroup", "Hobbyist"),

horiz = FALSE, fillcolor = c(LanguageGroup = "#e7d4e8",

Gender = "#99d8c9", Hobbyist = "#9ecae1"),

keep = list(LanguageGroup = c("R", "Both")), showcount = FALSE)

Поскольку дерево становится очень загруженным, я думаю, что полезно иметь в качестве меток узлов либо счетчик, либо процент, а не то и другое одновременно. Таким образом, последний аргумент в приведенном выше коде,,  showcount = FALSEустанавливает график для отображения только процентов, а не счетчиков.

Шэрон Махлис,

Больше рассчитывать по группам

Есть и другие полезные способы группировки и подсчета в R, включая base R, dplyr и data.table. Base R имеет  xtabs()функцию специально для этой задачи. Обратите внимание на синтаксис формулы ниже: тильда, затем одна переменная плюс еще одна переменная.

xtabs (~ LanguageGroup + Gender, data = mydata)

Пол Язык Группа Мужчина Женщина Оба 3264 374 Ни то, ни другое 43908 3705 Python 29044 1940 R 969 175

Функция dplyr count()объединяет «группировать по» и «подсчитывать строки в каждой группе» в одну функцию.

библиотека (dplyr)

my_summary%

count(LanguageGroup, Gender, Hobbyist, sort = TRUE)

my_summary LanguageGroup Gender Hobbyist n 1 Neither Man Yes 34419 2 Python Man Yes 25093 3 Neither Man No 9489 4 Python Man No 3951 5 Both Man Yes 2807 6 Neither Woman Yes 2250 7 Neither Woman No 1455 8 Python Woman Yes 1317 9 R Man Yes 757 10 Python Woman No 623 11 Both Man No 457 12 Both Woman Yes 257 13 R Man No 212 14 Both Woman No 117 15 R Woman Yes 103 16 R Woman No 72

In the three lines of code below, I load the data.table package, create a data.table from my data, and then use the special .N data.table symbol that stands for number of rows in a group. 

library(data.table)

mydt <- setDT(mydata)

mydt[, .N, by = .(LanguageGroup, Gender, Hobbyist)]

Visualizing with ggplot2

Как и большинство данных, ggplot2 - хороший выбор для визуализации итоговых результатов. Первый график ggplot ниже отображает LanguageGroup по оси X, а количество для каждого - по оси Y. Цвет заливки показывает, говорит ли кто-то, что программирование - это хобби. Кроме того, facet_wrap говорит: сделайте отдельный график для каждого значения в столбце Пол.

библиотека (ggplot2)

ggplot (my_summary, aes (LanguageGroup, n, fill = Hobbyist)) +

geom_bar (stat = "identity") +

facet_wrap (facets = vars (Пол))

Шэрон Махлис,

Поскольку в выборке относительно мало женщин, трудно сравнивать процентное соотношение между полами, когда на обоих графиках используется одна и та же шкала оси Y. Я могу изменить , что, хотя, так что каждый график использует отдельную шкалу, добавляя аргумент scales = “free_y”к facet_wrap()функции:

ggplot (my_summary, aes (LanguageGroup, n, fill = Hobbyist)) +

geom_bar (stat = "identity") +

facet_wrap (facets = vars (Пол), scale = "free_y")

Теперь стало проще сравнивать несколько переменных по полу.

Чтобы узнать больше советов по R, перейдите на страницу «Делайте больше с R» или посмотрите плейлист YouTube «Делайте больше с R».

На следующей странице представлена ​​информация о том, как загружать и обрабатывать данные, используемые в этой демонстрации.