Cómo contar por grupo en R

El conteo por múltiples grupos, a veces llamado informes de tabla cruzada, puede ser una forma útil de ver datos que van desde encuestas de opinión pública hasta pruebas médicas. Por ejemplo, ¿cómo votó la gente por género y grupo de edad? ¿Cuántos desarrolladores de software que usan R y Python son hombres y mujeres?

Hay muchas formas de hacer este tipo de conteo por categorías en R. Aquí, me gustaría compartir algunos de mis favoritos.

Para las demostraciones de este artículo, usaré un subconjunto de la encuesta Stack Overflow Developers, que encuesta a los desarrolladores sobre docenas de temas que van desde salarios hasta tecnologías utilizadas. Lo reduciré con columnas para los idiomas utilizados, el género y si codifican como pasatiempo. También agregué mi propia columna LanguageGroup para saber si un desarrollador informó que usa R, Python, ambos o ninguno.

Si desea seguir adelante, la última página de este artículo tiene instrucciones sobre cómo descargar y discutir los datos para obtener el mismo conjunto de datos que estoy usando.

Los datos tienen una fila para cada respuesta de la encuesta y las cuatro columnas son todas caracteres.

str (mydata) 'data.frame': 83379 obs. de 4 variables: $ Género: chr "Hombre" "Hombre" "Hombre" "Hombre" ... $ LanguageWorkedWith: chr "HTML / CSS; Java; JavaScript; Python" "C ++; HTML / CSS; Python" "HTML / CSS "" C; C ++; C #; Python; SQL "... $ Aficionado: chr" Sí "" No "" Sí "" No "... $ LanguageGroup: chr" Python "" Python "" Ninguno "" Python "...

Filtre los datos sin procesar para hacer que las tablas de referencias cruzadas sean más manejables, incluida la eliminación de los valores faltantes y tomar solo los dos géneros más grandes, Hombre y Mujer.

El paquete de conserje

Entonces, ¿cuál es el desglose por género dentro de cada grupo de idiomas? Para este tipo de informes en un marco de datos, una de mis herramientas de uso es la tabyl()función del paquete de conserje . 

La tabyl()función básica devuelve un marco de datos con recuentos. El primer nombre de columna que agrega a un tabyl()argumento se convierte en la fila y el segundo en la columna

biblioteca (conserje) tabyl (mydata, Gender, LanguageGroup)

Género Ambos Ninguno Python R Hombre 3264 43908 29044969 Mujer 374 3705 1940175

Lo bueno de esto tabyl()es que también es muy fácil generar porcentajes. Si desea ver los porcentajes de cada columna en lugar de los totales sin procesar, agregue adorn_percentages("col"). A continuación, puede canalizar esos resultados a una función de formato como  adorn_pct_formatting().

tabyl (mydata, Gender, LanguageGroup)%>%

adorn_percentages ("col")%>%

adorn_pct_formatting (dígitos = 1)

Género Ambos Ninguno Python R Hombre 89,7% 92,2% 93,7% 84,7% Mujer 10,3% 7,8% 6,3% 15,3%

Para ver los porcentajes por fila, sume adorn_percentages("row")

Si desea agregar una tercera variable, como Hobbyist, también es fácil.

tabyl (mydata, género, grupo de idiomas, aficionado)%>%

adorn_percentages ("col")%>%

adorn_pct_formatting (dígitos = 1)

Sin embargo, de esta forma se vuelve un poco más difícil comparar visualmente los resultados en más de dos niveles. Este código devuelve una lista con un marco de datos para cada opción de tercer nivel:

$ No Género Ambos Ninguno Python R Hombre 79.6% 86.7% 86.4% 74.6% Mujer 20.4% 13.3% 13.6% 25.4% $ Sí Género Ambos Ninguno Python R Hombre 91.6% 93.9% 95.0% 88.0% Mujer 8.4% 6.1% 5.0% 12.0%

El paquete CGPfunctions

Vale la pena echarle un vistazo al paquete CGPfunctions para encontrar formas rápidas y fáciles de visualizar datos de tabla cruzada. Instálalo desde CRAN con lo habitual install.packages("CGPfunctions").

El paquete tiene dos funciones de interés para examinar las tablas de referencias cruzadas: PlotXTabs()y PlotXTabs2(). Este código devuelve gráficos de barras de los datos (primer gráfico a continuación):

biblioteca (CGPfunctions)

PlotXTabs (mydata)

Captura de pantalla de Sharon Machlis,

PlotXTabs2(mydata) crea un gráfico con un aspecto diferente y algunos resúmenes estadísticos (segundo gráfico a la izquierda).

Si no necesita o no desea esos resúmenes, puede eliminarlos con results.subtitle = FALSE, como  PlotXTabs2(mydata, LanguageGroup, Gender, results.subtitle = FALSE).

Captura de pantalla de Sharon Machlis,

PlotXTabs2()tiene un par de docenas de opciones de argumentos, que incluyen título, leyenda, leyendas, combinación de colores y uno de los cuatro tipos de trama: lateral, pila, mosaico o porcentaje. También hay opciones familiares para los usuarios de ggplot2, como ggtheme y palette. Puede ver más detalles en el archivo de ayuda de la función.

El paquete vtree

El paquete vtree genera gráficos para tablas de referencias cruzadas en lugar de gráficos. Ejecutando la vtree()función principal en una variable, como 

biblioteca (vtree)

vtree (mydata, "LanguageGroup")

te da esta respuesta básica:

Sharon Machlis,

No estoy interesado en los valores predeterminados de color aquí, pero puede intercambiar en una paleta RColorBrewer. El argumento de la paleta de vtree usa números de paleta , no nombres; puede ver cómo están numerados en la documentación del paquete vtree. Podría elegir 3 para verdes y 5 para morados, por ejemplo. Desafortunadamente, esos valores predeterminados le dan un color más intenso para números de conteo más bajos , lo que no siempre tiene sentido (y no me funciona bien en este ejemplo). Puedo cambiar ese comportamiento predeterminado sortfill = TRUEpara usar el color más intenso para el valor más alto

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

Sharon Machlis,

Si encuentra que el color oscuro dificulta la lectura del texto, existen algunas opciones. Una opción es usar el argumento simple , como  vtree(mydata, "LanguageGroup", plain = TRUE). Otra opción es establecer un solo color de relleno en lugar de una paleta, usando el fillcolorargumento, como  vtree(mydata, LanguageGroup", fillcolor = "#99d8c9").

Para ver dos variables en un informe de tabla de referencias cruzadas, simplemente agregue un segundo nombre de columna y una paleta o color si no desea el predeterminado. Puede utilizar la opción simple o especificar dos paletas o dos colores. A continuación, elegí colores específicos en lugar de paletas, y también giré el gráfico para leer verticalmente.

vtree (mydata, c ("LanguageGroup", "Sexo"),

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

horiz = FALSE)

Sharon Machlis,

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)

Con el árbol de conseguir tan ocupados, creo que esto ayuda a tener ya sea el recuento o el porcentaje como etiquetas de nodo, pero no ambos. Entonces, el último argumento en el código anterior  showcount = FALSEestablece que el gráfico muestre solo porcentajes y no recuentos.

Sharon Machlis,

Más opciones de conteo por grupo

Hay otras formas útiles de agrupar y contar en R, como base R, dplyr y data.table. Base R tiene la  xtabs()función específica para esta tarea. Tenga en cuenta la sintaxis de la fórmula a continuación: una tilde y luego una variable más otra variable.

xtabs (~ LanguageGroup + Sexo, datos = mydata)

Género Idioma Grupo Hombre Mujer Ambos 3264374 Ninguno 43908 3705 Python 29044 1940 R 969175

La count()función de dplyr combina "agrupar por" y "contar filas en cada grupo" en una única función.

biblioteca (dplyr)

mi resumen %

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

Como ocurre con la mayoría de los datos, ggplot2 es una buena opción para visualizar resultados resumidos. El primer gráfico de ggplot a continuación traza LanguageGroup en el eje X y el recuento de cada uno en el eje Y. El color de relleno representa si alguien dice que codifica como pasatiempo. Y facet_wrap dice: Haga un gráfico separado para cada valor en la columna Género.

biblioteca (ggplot2)

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

geom_bar (stat = "identidad") +

facet_wrap (facetas = vars (género))

Sharon Machlis,

Debido a que hay relativamente pocas mujeres en la muestra, es difícil comparar porcentajes entre géneros cuando ambos gráficos usan la misma escala del eje Y. Sin embargo, puedo cambiar eso, por lo que cada gráfico usa una escala separada, agregando el argumento scales = “free_y”a la facet_wrap()función:

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

geom_bar (stat = "identidad") +

facet_wrap (facetas = vars (género), escalas = "free_y")

Ahora es más fácil comparar múltiples variables por género.

Para obtener más sugerencias de R, diríjase a la página "Haga más con R" o consulte la lista de reproducción de YouTube "Haga más con R".

Consulte la página siguiente para obtener información sobre cómo descargar y gestionar los datos utilizados en esta demostración.