¡Hola! En este tercer encuentro profundizaremos en el paquete tidyverse a partir de funciones de agrupamiento, pivoteo de las tablas y representación gráfica de los datos. Continuaremos trabajando con la base de datos de la AUH.
eah <- read.csv("https://cdn.buenosaires.gob.ar/datosabiertos/datasets/direccion-general-de-estadisticas-y-censos/encuesta-anual-hogares/encuesta-anual-hogares-2019.csv", encoding = "latin1")
Ahora activemos nuestra libreria
library(tidyverse)
Asi como en el encuentro pasado vimos algunas funciones de tabulado para seleccionar, filtrar, crear y/o modficiar segun algunos criterios, ahora veremos como agrupar nuestra informacion segun el criterio que establezcamos Supongamos que queremos pedirle a R una tabla que contenga la cantidad de registros acumulado de varones y mujeres por comuna.
eah |>
group_by(comuna) |>
summarise(cantidad=n())
## # A tibble: 15 × 2
## comuna cantidad
## <int> <int>
## 1 1 1265
## 2 2 765
## 3 3 906
## 4 4 1300
## 5 5 818
## 6 6 755
## 7 7 1116
## 8 8 1640
## 9 9 967
## 10 10 765
## 11 11 728
## 12 12 801
## 13 13 833
## 14 14 847
## 15 15 813
Algunas cuestiones:
Para que la tabla exprese los datos agrupados de acuerdo a x criterio debe ir acoplado con la función summarise(), que resume estadisticamente segun el criterio elegido. Como vimos en el encuentro pasado que con summarise podemos generar registros estadisticos a partir de la mediana, máximos, mínimos, desviación, etc. También podemos pedirle el numero de registros con la función n(), que nos devuelve el tamaño del grupo seleccionado, función que solo funciona dentro de otra función como summarise() o mutate()
Veremos que nos devuelve dos columnas: Una, la columna con la variable que estamos trabajando y otra con los resultados del informe estadistico expresado en una nueva variable
La tabla tiene 15 filas, ya que le pedimos que nos agrupe la información a partir de las categorías de la variable Comunas. Por ello que son 15 categorías únicas y excluyentes en las que se están agrupando los datos.
Si corren la linea de código:
#?n()
Verán en el panel de salida la explicación de la función y a qué paquete pertenece.
Veamos qué sucede con con otras variables
unique(eah$parentesco_jefe)
## [1] "Jefe" "Otro no familiar"
## [3] "Padre/Madre/Suegro/a" "Otro familiar"
## [5] "Conyugue o pareja" "Hijo/a - Hijastro/a"
## [7] "Nieto/a" "Yerno/nuera"
## [9] "Servicio domestico y sus familiares"
eah |>
group_by(parentesco_jefe) |>
summarise(cantidad=n())
## # A tibble: 9 × 2
## parentesco_jefe cantidad
## <chr> <int>
## 1 Conyugue o pareja 2845
## 2 Hijo/a - Hijastro/a 4526
## 3 Jefe 5848
## 4 Nieto/a 297
## 5 Otro familiar 374
## 6 Otro no familiar 135
## 7 Padre/Madre/Suegro/a 194
## 8 Servicio domestico y sus familiares 39
## 9 Yerno/nuera 61
En el primer encuentro vimos que con unique() pudimos apreciar la cantidad de categorias excluyentes que tienecada campo Y segun esa cantidad fueron agrupados los datos con group_by() y summarise().
Tambien podemos hacerlo con dos variables! Supongamos que queremos ver la cantidad de varones y mujeres por comuna
eah |>
group_by(comuna,sexo) |>
summarise(cantidad=n())
## # A tibble: 30 × 3
## # Groups: comuna [15]
## comuna sexo cantidad
## <int> <chr> <int>
## 1 1 Mujer 683
## 2 1 Varon 582
## 3 2 Mujer 413
## 4 2 Varon 352
## 5 3 Mujer 503
## 6 3 Varon 403
## 7 4 Mujer 710
## 8 4 Varon 590
## 9 5 Mujer 463
## 10 5 Varon 355
## # … with 20 more rows
No es indiferente en el group_by() que variables elijamos primero, ya que su elección dependerá de donde aparezca y facilitarán o no su lectura. Aun así, podría ser mas fácil aun a la lectura, por que no armamos dos variables con la cantidad de mujeres y varones por comuna?
Desagreguemos la logica de la tabla;
Primero, pensemos qué tabla queremos que nos arroje. Para ello podemos seleccionar primero las dos columnas con las que queremos trabajar.
Segundo, sabemos que necesitamos crear dos objetos que resuman la cantidad de datos agrupados según un criterio; la cantidad de varones y mujeres por comuna. Entonces, agruparemos por comuna, pero le pediremos la sumatoria de casos que cumplan con una condición
eah |>
group_by(comuna) |>
summarise(varones=sum(sexo=="Varon"),
mujeres=sum(sexo=="Mujer"))
## # A tibble: 15 × 3
## comuna varones mujeres
## <int> <int> <int>
## 1 1 582 683
## 2 2 352 413
## 3 3 403 503
## 4 4 590 710
## 5 5 355 463
## 6 6 352 403
## 7 7 520 596
## 8 8 783 857
## 9 9 473 494
## 10 10 361 404
## 11 11 323 405
## 12 12 376 425
## 13 13 357 476
## 14 14 391 456
## 15 15 378 435
¡Otro más! ¿Y si queremos el promedio salarial de varones y mujeres por comuna que solo sean jefes de hogares, y por comuna?
resumen <- eah |>
filter(parentesco_jefe=="Jefe") |>
group_by(comuna) |>
summarise(varones=sum(sexo=="Varon"),
mujeres=sum(sexo=="Mujer"),
promedio_v=round(mean(ingreso_total_lab[sexo == "Varon"])),
promedio_m=round(mean(ingreso_total_lab[sexo=="Mujer"])))
Observen cómo el summarise es útil para pedir el resumen de:
La suma de varones por comuna.
La suma de mujeres por comuna.
El promedio redondeando de los ingresos totales laborales en donde el jefe de hogar sea varon.
El promedio redondeado de los ingresos laborales en donde la jefa del hogar sea mujer.
Una observación, ¿cómo sabe R que quiero el resultado promedio de los ingresos totales laborales separado por Varon y Mujer? Si no lo especificara, me arroja un resultado agrupado. Es por eso que dentro, del campo ingreso_total_lab abro [], para indagar dentro de la base y especificar la categoría con la que quiero que trabaje. Por último, la función round es para redondear valores con decimales…
Pasemos a pivotear los resultados. Pivot loger es una funcion útil cuando queremos pasar nuestras filas a columnas, pasando desde ancho a lo largo.
# pivot_longer(cols = el argumento cols nos está pidiendo que elijamos qué campos queremos pivotear,
# names_to= "resumen" creamos un campo que se llame "resumen" y donde están agrupadas en forma de categorías los campos que señalamos arriba en cols= )
# values_to ="valores") creamos un campo que se llame "valores" y donde estarán las categorías de los campos que acabamos de pivotear. De esta manera nada se pierde, solo pivotean.
resumen |>
pivot_longer(cols=c(varones,mujeres,promedio_v,promedio_m), # tomamos estas columnas
names_to = "resumen", # los nombres de las columnas pasan a ser categorias de la nueva variable "resumen"
values_to = "valores") |> # los valores que refieren a ella pasan a ser parte de esta nueva variable. Entonces por comuna tenemos el resumen estadistico de cada uno
filter(comuna %in% c(1,5)) |> # traeme el resumen de las comunas 1 y 5
view()
De esta manera tenemos los datos a lo largo antes que a lo ancho. En resumen estarán contenidas las categorías estadísticas y en valores, sus respectivos valores. De esta forma podemos trabajar solo con la comuna 1 y cada uno de los valores estadísticos en dos filas, antes que en 4. Esto también nos dará la ventaja de poder trabajarlo en un gráfico
Supongamos que queremos pivotear la tabla desde lo largo a lo ancho.
resumen2 <- eah |>
group_by(comuna,dominio) |>
summarise(promedio=mean(ingreso_per_capita_familiar))
## `summarise()` has grouped output by 'comuna'. You can override using the
## `.groups` argument.
# Hasta aqui hemos agrupado el promedio de ingresos totales laborales segun comuna y el dominio
# La estructura de pivot_wider es así:
#pivot_wider(names_from = "dominio", Le pedimos que pasen a ser campos/variables aquellas categorias del campo dominio
# values_from = "promedio") y que los datos de promedio pasen
resumen2 |>
pivot_wider(names_from = "dominio",
values_from = "promedio")
## # A tibble: 15 × 3
## # Groups: comuna [15]
## comuna `Resto de la Ciudad` `Villas de emergencia`
## <int> <dbl> <dbl>
## 1 1 29550. 8104.
## 2 2 44995. NA
## 3 3 24320. NA
## 4 4 20729. 7259.
## 5 5 28352. NA
## 6 6 34113. NA
## 7 7 25133. 6208.
## 8 8 17290. 7071.
## 9 9 19204. 7433.
## 10 10 25983. NA
## 11 11 27022. NA
## 12 12 31003. NA
## 13 13 38653. NA
## 14 14 42670. NA
## 15 15 29528. 9032.
Notemos ahora cómo los datos pasaron de dos campos a tres. Sin embargo, notemos también como muchas filas tienen NAs. Si notamos la tabla sin pivotear, resumen2, no todas las categorías de dominio tienen su correlato con registros. Por ejemplo las comunas 2 y 3, no hay datos de los ingresos_per_capita_familiar en Villas de Emergencia. Ello conlleva a que los datos aparezcan sin registro.
Inspeccionar la AUH y seleccionar aquellas variables con las que se quedarán para trabajar y construir con esta selección un nuevo objeto que se llame: “agrupado”
Tomar una o dos categorías como máximo de una sola variable, e inspeccionar cuantos casos representa de la base. Para este caso no crearemos otro objeto.
Con la variable que acabamos de trabajar, ahora agruparemos todos sus categorías para ver cuanto representa cada una. Para este caso deberán utilizar la funcion group_by() y summarise(). Elijan ustedes qué operación es la más convenientes; máximos, mínimos, promedio, etc.
Inspeccionen el resumen realizado y pivoteen la base a lo largo o a lo ancho y reflexionen qué ventajas tiene hacerlo según el criterio elegido.
A partir de la tabla generada, crear un nuevo objeto
Partiendo de que ggplot trabaja con de visualización, y los 3 componentes de la gramática; datos, objeto geometrico en cuestión y atributos:
ggplot(resumen)
Solo nos aparece un gráfico vacío, ya que no le estamos pidiendo qué tipo de objeto geométrico lo compondrá. Para ello debemos definirlo:
Partiendo de que un histograma es la distribución de frecuencias. Queremos conocer que valores de varones tienen mayor frecuencias
ggplot(resumen, # el data set
mapping = aes(x=varones)) + # los atributos esteticos
geom_histogram() # el tipo de objeto geométrico
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
# Supongamos que le queremos asignar un color
ggplot(resumen,
aes(x=varones)) +
geom_histogram(fill="red", # color de relleno
color="black", # color del contorno
alpha=.5)+ # transparencia
theme_bw() # Hay distintas tematicas para asignarles a los cuadros
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(resumen,
aes(x=varones)) +
geom_density(fill="#69b3a2", color="#e9ecef", alpha=0.8) +
theme_classic() # Podemos elegir distintas formas de presentar nuestras tablas con el grupo de funciones theme_
ggplot(resumen,
aes(x=varones)) +
geom_density(fill="#3A95B1", color="black", alpha=0.8) +
theme_minimal() # algo más minimalista
# Quiero conocer la cantidad de valores de varones por comuna
ggplot(resumen, aes(x=comuna,y=promedio_v)) +
geom_col()
# Supongamos que queremos asignarle un color a nuestra variable
# Por defecto, con la funcion fill(), si nuestros datos son de tipo numericos, asignarán un valor continuo de colores,
ggplot(resumen, aes(x=comuna,y=promedio_v,fill=promedio_v)) +
geom_col() +
coord_flip() # invertimos la perspectiva grafica
# Para una mejor visualización traemos la funcion reorder(x,y) que los ordenar de forma jerárquica
ggplot(resumen, aes(x=comuna,y=promedio_v,fill=promedio_v)) +
geom_col(aes(x=reorder(comuna, promedio_v), y=promedio_v))+
coord_flip() +
theme_minimal()
# que nos cuenta el gráfico? que significan las categorías a la izquierda y las de debajo?
# Si pasamos nuestros datos a categoricos, desaparece la estetica de valores continuos, y aparece, por el contrario,
# en formato categorico, unicos.
ggplot(resumen, aes(x=comuna,y=promedio_v,fill=as.factor(promedio_v))) +
geom_col() +
coord_flip()
# Tambien pueden ser representados mediante etiquetas!
ggplot(resumen) + # en esta ocasion, estamos definiendo la estetica debajo
geom_label(aes(x=comuna,y=promedio_v, label=comuna), color="white",fill="red")
ggplot(resumen) +
geom_point(aes(x=comuna,y=promedio_v,size=promedio_v)) # el parametro size asigna la estetica del punto segun el valor numerico más alto o bajo
# Podemos cambiarles las formas
ggplot(resumen) +
geom_point(aes(x=comuna,y=promedio_v,size=promedio_v),shape=4,stroke=3) # Con shape cambiamos la forma de nuestros datos, con stroke asignamos mas o menos relleno
ggplot(resumen) +
geom_point(aes(x=comuna,y=promedio_v,size=promedio_v),
color="black",
fill="#69b3a2",
shape=22,
alpha=0.5,
size=6,
stroke = 1) +
theme_linedraw()
ggplot(resumen) +
geom_point(aes(x=comuna,y=promedio_v,size=promedio_v),
color="orange",
fill="#69b3a2",
shape=21,
alpha=0.5,
size=6,
stroke = 2)
Pero, ¿qué sería de la representación gráfica de las tablas sin un título correspondiente a sus datos?
ggplot(resumen, aes(x=comuna,y=promedio_v,fill=promedio_v)) +
geom_col(aes(x=reorder(comuna, promedio_v), y=promedio_v), color="black")+
coord_flip() +
theme_minimal() +
labs(title = "Promedio de ingreso laboral en varones jefes de hogares", # Titulo
subtitle = "Segun comuna", # Subitulo
x="Comunas", # Eje X
y="Promedio", # Eje Y
fill="Promedio", # Panel izquierdo
caption = "Elaboración Propia en base a la Encuesta Anual de Hogares") + # Referencia del grafico
theme(plot.title=element_text(face="bold", # Grosor del texto
size=16), # tamaño±o del texto
plot.subtitle = element_text(face = "bold.italic",
size=13),
plot.caption = element_text(face="bold", # Referencia del grafico
size=10,
color="#44A75D"), # Color
axis.text = element_text(face = "bold", # Categorias de ejes X-Y
size = 10,
colour = "red"),
axis.title = element_text(face="bold", # Titulo de categorias ejes X-Y
size = 9,
colour = "violet",
hjust = 1), # Posicion de las leyendas
legend.title = element_text(face = "bold",
size = 10,
color="#D467CC"), # Titulo de la leyenda
legend.text = element_text(face = "bold",
size = 10,
vjust = 1,
color="#962445")) # Datos de la leyenda
Retomando aquél objeto que creamos en el desafío de este encuentro:
Representar solo las frecuencias de sus variables mediante un histograma o gráfico de densidad y asignarle un título
Representar mediante un cuadro de puntos dos variables, asignarle un título, un subtítulo, modificar el nombre de la leyenda a uno más pertinente y asignar una leyenda que describa quién lo hizo
Representar mediante un cuadro de tablas dos variables,asignarle un título, un subtítulo, modificar el nombre de la leyenda a uno más pertinente, asignar una leyenda que describa quién lo hizo y modificar los atributos estéticos estos cuatro puntos.