Introducción

Este sitio web contiene todos los materiales “prácticos” para el taller “La demografía del parentesco: una introducción práctica” ofrecido en el Colegio de Mexico (24-28 Junio 2023). Aquí encontrarás recursos y herramientas prácticas para aplicar la teoría a tus propios objetivos de investigación.

Los ejercicios prácticos te ayudarán a comprender cómo funciona DemoKin y te proporcionarán las herramientas para personalizar el código según tus propias investigaciones, si es necesario.

Algunas cosas útiles:

Ten en cuenta que esta página puede cambiar durante el curso, así que no te preocupes si notas algunos cambios. Podemos adaptar el contenido en función de nuestra interacción o corregir errores en el código a lo largo del camino.

Espero que disfrutes del curso y te sea útil.

¡Empecemos!

Diego Alburez Gutierrez

Configuración

Configuración inicial

Pronto comenzaremos las sesiones de laboratorio de computación, por lo que sería genial si de antemano hemos preparado el entorno de R. Primero, necesitarás tener instalados R y RStudio.

Segundo, instala la versión de desarrollo de DemoKin. Hicimos cambios en el paquete antes de este taller, así que si ya has instalado el paquete, desinstálalo e instálalo nuevamente.

# remove.packages("DemoKin")
install.packages("DemoKin")

Otros paquetes que serán útiles son:

packages_needed <- c("tidyverse", "matrixcalc", "Matrix", "expm") 
packages_needed_nothaving <- packages_needed[!packages_needed %in% installed.packages()]
for(lib in packages_needed_nothaving) install.packages(lib,dependencies=TRUE)

Los paquetes de la familia tidyverse serán muy útiles para resumir y visualizar los resultados. Por favor, carga esas librerías y contáctanos en caso de que surjan problemas con este tema. Los paquetes matrixcalc y Matrix nos ayudarán con algunas operaciones de matrices.

Los datos para ejemplos y ejercicios pueden provenir de estimaciones y proyecciones de la población de la ONU, utilizando la API del DataPortal de la División de Población de las Naciones Unidas, o de tablas ubicadas en GitHub.

Operaciones con vectores y matrices en R

La intención de esta sección es introducir algunos operadores básicos de matrices y vectores, siguiendo el apéndice A de Caswell (2001). Hay muchos recursos en línea sobre álgebra de matrices con R (consultar Fieller (2016) para obtener uno completo). Aquí vamos a mostrar algunos relevantes para nuestros propósitos. En caso de tener experiencia con operaciones de matrices en R, esto no te añadirá mucho. Consultar Caswell (2001) para obtener detalles matemáticos.

  • Creación
# vector columna con 4 elementos de valor 1
a_vector <- c(1, 1, 1, 1)
a_vector
## [1] 1 1 1 1
same_vector <- rep(1, 4) # ¡repetir un valor!
same_vector
## [1] 1 1 1 1

La función matrix necesita un vector de entrada y cómo debería ser organizado por filas y columnas, por defecto en dirección de columnas (puede ser en dirección de filas con byrow = TRUE).

a_matrix <- matrix(1:16, nrow = 4, ncol = 4)
a_matrix
##      [,1] [,2] [,3] [,4]
## [1,]    1    5    9   13
## [2,]    2    6   10   14
## [3,]    3    7   11   15
## [4,]    4    8   12   16

Una matriz especial es la matriz Identidad, una matriz diagonal con unos en la diagonal y ceros en otros lugares.

identity_matrix <- diag(1, 4)
a_matrix %*% identity_matrix == a_matrix
##      [,1] [,2] [,3] [,4]
## [1,] TRUE TRUE TRUE TRUE
## [2,] TRUE TRUE TRUE TRUE
## [3,] TRUE TRUE TRUE TRUE
## [4,] TRUE TRUE TRUE TRUE

Por lo general, un subíndice indica la dimensión: \(I_n\) de dimensión \(n\).

  • Dimensiones

Para matrices y vectores es un poco diferente:

# con matriz:
dim(a_matrix)
## [1] 4 4
# con vectores:
# dim(a_vector) da error. 
# Los vectores en R no tienen una dimensión por defecto, son sin dimensiones pero tienen una longitud. 
# Operativamente, para nuestros propósitos, podemos considerarlo como un vector columna. 
# Para mostrarlo de manera matricial debemos convertirlo en un objeto de matriz. Consultar la sección 2.10.1 de Fieller (2016) para más detalles.
length(a_vector)
## [1] 4
as.matrix(a_vector)
##      [,1]
## [1,]    1
## [2,]    1
## [3,]    1
## [4,]    1
dim(as.matrix(a_vector))
## [1] 4 1

Verificar las dimensiones es una buena práctica para validar si dos objetos pueden ser sumados o multiplicados (y en qué orden). Sabes que algo relacionado con eso está sucediendo incorrectamente cuando ves este mensaje “non-conformable arguments”.

  • Suma
# necesita las mismas dimensiones
other_vector <- rep(10, 4)
a_vector + other_vector
## [1] 11 11 11 11
other_matrix <- matrix(10, nrow = 4, ncol = 4)
a_matrix + other_matrix
##      [,1] [,2] [,3] [,4]
## [1,]   11   15   19   23
## [2,]   12   16   20   24
## [3,]   13   17   21   25
## [4,]   14   18   22   26
  • Multiplicación

Esto se utilizará mucho en las secciones A mano, y se utiliza mucho dentro de DemoKin. Aquí hay una figura muy intuitiva que muestra la multiplicación de \(A\) por \(B\) (dimensiones 4x2 por 2x3 da una dimensión de 4x3):

No es lo mismo hacer \(A\) por \(B\) que \(B\) por \(A\). Puedes multiplicar una matriz por otra matriz, o una matriz por un vector. El símbolo en R es el mismo para multiplicar escalares, pero rodeado por %.

a_matrix %*% other_matrix
##      [,1] [,2] [,3] [,4]
## [1,]  280  280  280  280
## [2,]  320  320  320  320
## [3,]  360  360  360  360
## [4,]  400  400  400  400
a_matrix %*% a_vector
##      [,1]
## [1,]   28
## [2,]   32
## [3,]   36
## [4,]   40

No confundir con el producto de Hadamard, que es el operador elemento por elemento, y utiliza el símbolo *.

a_matrix * other_matrix
##      [,1] [,2] [,3] [,4]
## [1,]   10   50   90  130
## [2,]   20   60  100  140
## [3,]   30   70  110  150
## [4,]   40   80  120  160
a_vector * other_vector
## [1] 10 10 10 10
  • Transpuesta

Voltea una matriz sobre su diagonal.

t(a_matrix)
##      [,1] [,2] [,3] [,4]
## [1,]    1    2    3    4
## [2,]    5    6    7    8
## [3,]    9   10   11   12
## [4,]   13   14   15   16
  • Determinante:

Creemos una matriz cuadrada no singular (sin determinante cero, con inversa):

set.seed(50)
other_matrix <- matrix(runif(25), 5, 5)

Obtener el determinante:

det(other_matrix)
## [1] 0.0790383
  • Inversa:

Esta es una matriz cuadrada que, cuando se multiplica por la matriz original, da como resultado la matriz identidad. Útil para el cálculo de la matriz fundamental, por ejemplo.

solve(other_matrix)
##            [,1]       [,2]       [,3]       [,4]       [,5]
## [1,] -0.7532561  0.4483513 -0.8803085  0.2389641  2.5925394
## [2,] -1.7584887  1.1373711  0.3223507  0.5824490  0.4623462
## [3,]  0.4501699 -1.0999430  0.8439473 -1.7318679  2.5762176
## [4,]  1.5851130  0.4581780 -0.2507393 -0.3155394 -2.0105742
## [5,]  0.5923742 -0.4038200  0.7294525  1.1270147 -2.4426687
  • Descomposición en valores propios.

Muy útil para estudiar el crecimiento asintótico y la distribución por etapas.

eigen_decomposition <- eigen(other_matrix)
eigen_values <- eigen_decomposition$values
eigen_vectors <- eigen_decomposition$vectors
eigen_values
## [1]  2.0530799+0.0000000i  0.4773004+0.3184035i  0.4773004-0.3184035i
## [4] -0.2875065+0.1851585i -0.2875065-0.1851585i
eigen_vectors
##               [,1]                    [,2]                    [,3]
## [1,] -0.4822995+0i -0.25138592-0.10180400i -0.25138592+0.10180400i
## [2,] -0.5185911+0i  0.04457630+0.50906992i  0.04457630-0.50906992i
## [3,] -0.5421256+0i  0.74451004+0.00000000i  0.74451004+0.00000000i
## [4,] -0.3441768+0i -0.31996739-0.04760300i -0.31996739+0.04760300i
## [5,] -0.2934154+0i  0.02297589-0.07637777i  0.02297589+0.07637777i
##                       [,4]                  [,5]
## [1,]  0.4840069+0.2144677i  0.4840069-0.2144677i
## [2,]  0.3504491-0.0257238i  0.3504491+0.0257238i
## [3,] -0.0063401+0.2390741i -0.0063401-0.2390741i
## [4,] -0.6151650+0.0000000i -0.6151650+0.0000000i
## [5,] -0.1934342-0.3510316i -0.1934342+0.3510316i

El valor dominante está en la primera posición eigen_values[1], y su vector asociado en la primera columna de la matriz eigen_vectors, eigen_vectors[1,]. Para separar la parte real y la parte imaginaria de los números complejos, puedes usar las funciones Re e Im.

  • Producto de Kronecker

Con el paquete Matrix, tenemos el producto de Kronecker entre matrices, con el símbolo \(\otimes\) (\(A\otimes B\), por ejemplo), útil, por ejemplo, para calcular distribuciones marginales en un contexto de múltiples estados:

library(Matrix)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
A <- matrix(1:4, nrow = 2, ncol = 2)
B <- matrix(11:14, nrow = 2, ncol = 2)
A
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
B
##      [,1] [,2]
## [1,]   11   13
## [2,]   12   14
kronecker(A, B)
##      [,1] [,2] [,3] [,4]
## [1,]   11   13   33   39
## [2,]   12   14   36   42
## [3,]   22   26   44   52
## [4,]   24   28   48   56
  • Matriz estructurada por bloques

También con el paquete Matrix, tenemos una función para construir una matriz estructurada por bloques a partir de una serie de matrices (el resultado es una matriz sparse por defecto, por lo que podemos convertirla nuevamente a matriz para ver los ceros):

bdiag(A, B) %>% as.matrix()
##      [,1] [,2] [,3] [,4]
## [1,]    1    3    0    0
## [2,]    2    4    0    0
## [3,]    0    0   11   13
## [4,]    0    0   12   14
  • Matriz de permutación de vec

Veamos cómo vectorizar una matriz con dimensión \(s=2\) (filas, podrían ser estados de salud) por \(w=4\) (columnas, clases de edad), y qué significa aplicar la matriz de permutación de vec (o conmutación).

# crear matriz A con 2 etapas y 4 edades
s <- 2
w <- 4
A <- matrix(c(10, 2, 5, 2, 
              4,  1, 2, 0), nrow = s, ncol = w, byrow = T)

# vectorizar A: reorganizar la matriz como un vector agrupando las etapas dentro de las clases de edad
library(matrixcalc)
a <- vec(A) 
a
##      [,1]
## [1,]   10
## [2,]    4
## [3,]    2
## [4,]    1
## [5,]    5
## [6,]    2
## [7,]    2
## [8,]    0

Esta operación es útil en métodos de múltiples estados para reorganizar vectores ordenados por edad-estados a estados-edades. Relaciona el siguiente resultado con el anterior.

K <- commutation.matrix(s, w)
K %*% a
##      [,1]
## [1,]   10
## [2,]    2
## [3,]    5
## [4,]    2
## [5,]    4
## [6,]    1
## [7,]    2
## [8,]    0

En otras palabras, pre-multiplicar \(a\) por \(K\) (matriz de permutación de vectores) es lo mismo que vectorizar \(A\) transpuesto. Verificar:

all(vec(t(A)) == K %*% a)
## [1] TRUE
  • Sistema de ecuaciones lineales:

El álgebra lineal es útil para encontrar un vector \(x\) que, al ser pre-multiplicado por \(A\), produce un vector \(b\), en forma de un sistema de ecuaciones lineales \(Ax=b\), encontrando la solución como \(x=A^{-1}b\) (ver Caswell (2001) para más detalles sobre cuándo esto tiene una solución única, ninguna o infinitas soluciones). Como ejemplo, resolvamos esta situación: “Tengo 6 sobrinos y 10 sobrinas. Mis hermanos tienen en promedio 1 hijo y 2 hijas, y mis hermanas 1.5 hijos y 2 hijas. ¿Cuántos hermanos y hermanas tengo?”.

b = c(6, 10) # Tengo 6 sobrinos y 10 sobrinas
A = matrix(c(1, 1.5, # Mis hermanos tienen en promedio 1 hijo y mis hermanas 1.5
             2, 2),  # Mis hermanos tienen en promedio 2 hijas y mis hermanas 2
          2, 2, byrow = T) # Es una matriz de 2 por 2 dispuesta por filas
x = solve(A) %*% b # vector con hermanos y hermanas

Respuesta: Tengo 3 hermanos y 2 hermanas.

Durante el curso intentaremos nombrar vectores y matrices con una o dos letras como máximo, vectores en minúscula y matrices en mayúscula.

dplyr, tidyr y ggplot

En algunos ejercicios tendremos una tabla larga con muchas variables y necesitaremos obtener indicadores de ella, como por ejemplo la edad media de las hijas cuando Focal tiene 30 años. Los paquetes dplyr y tidyr son muy útiles para eso. Utilicemos los datos de mtcars, obteniendo la media de wt según cyl y am, pero mostrando las categorías de am en columnas:

head(mtcars)
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1
library(dplyr)
library(tidyr)
mtcars %>% 
  summarise(mean_wt = mean(wt), .by = c(cyl, am)) %>% 
  pivot_wider(names_from = am, values_from = mean_wt)
## # A tibble: 3 × 3
##     cyl   `1`   `0`
##   <dbl> <dbl> <dbl>
## 1     6  2.76  3.39
## 2     4  2.04  2.94
## 3     8  3.37  4.10

Estas son las funciones básicas que utilizaremos para mostrar ejemplos. Consulta más sobre la transformación de datos con dplyr y el remodelado con tidyr si tienes curiosidad. Por último, el paquete ggplot2 se utilizará para visualizar los resultados. Un ejemplo muy básico:

library(ggplot2)
mtcars %>% 
ggplot(aes(mpg, wt, colour = hp)) + 
  geom_point()

Aquí te hemos mostrado algunos paquetes y funciones que nos gustan, ¡pero en los ejercicios puedes usar las herramientas que desees!

Cómo crear una matriz subdiagonal

Con \(w\) edades y \(p\) el vector de probabilidades de supervivencia…

U <- matrix(0, nrow = w, ncol = w)
U[row(U)-1 == col(U)] <- p[-w]
U[w, w] <- p[w]

Multiplicar varias veces la misma matriz

Puedes usar una función del paquete expm. Para una matriz aleatoria llamada A:

library(expm)
A <- matrix(1:4,2,2)
A_power_2 <- `%^%`(A,2)

Comprobar si es verdadero:

all(A_power_2 == (A %*% A))
## [1] TRUE

Cadena de Markov para estocasticidad individual

Veamos el caso de Suecia en el primer año:

tiempo de ocupación esperado

load("../data/SWEhist_matrices.Rdata")
y = 1
U <- U[[y]]
w <- ncol(U)
I <- diag(1,w)
N1 <- solve(I-U)
N2 <- (2 * diag(diag(N1))-I) %*% N1
Var <- N2 - N1 * N1

longevidad

ones <- rep(1,w)
ones <- as.matrix(ones) # por si acaso
n1 <- t(t(ones) %*% N1)
n2 <- t(t(n1) %*% (2*N1-I))
var <- n2 - n1 * n1

distribución de la edad al morir

Definamos \(M\) como la matriz con probabilidades de muerte en la diagonal.

M <- diag(1-colSums(U))
B <- M %*% N1
plot(0:(w-1), B[,1], t="l")
lines(B[,51], col=2)
legend("topright", c("desde la edad 0", "desde la edad 50"), col=1:2, lty=1)

vida perdida

n1_dagger <- t(B[,1]) %*% n1
n2_dagger <- t(B[,1]) %*% n2
var_n_dagger <- n2_dagger - n1_dagger * n1_dagger

Lunes 24

Veremos cómo traducir la teoría de los modelos de parentesco de una clase de edad clasificada por tiempo invariable y un solo sexo a código, cómo utilizar el paquete DemoKin para una implementación sin problemas, y finalmente haremos algunos ejercicios. Secciones:

Usando DemoKin

Primero, carga estas bibliotecas:

library(DemoKin)
library(dplyr)
library(tidyr)
library(ggplot2)

1. Datos incorporados

El paquete DemoKin incluye datos de Suecia como ejemplo. Estos datos provienen de la Base de Datos de Mortalidad Humana y de la Base de Datos de Fecundidad Humana.

Primero, tenemos probabilidades de supervivencia por edad:

data("swe_px", package="DemoKin")
swe_px[1:5, 1:5]
##      1900    1901    1902    1903    1904
## 0 0.91060 0.90673 0.92298 0.91890 0.92357
## 1 0.97225 0.97293 0.97528 0.97549 0.97847
## 2 0.98525 0.98579 0.98630 0.98835 0.98921
## 3 0.98998 0.98947 0.99079 0.99125 0.99226
## 4 0.99158 0.99133 0.99231 0.99352 0.99272

Tiene años en las columnas y edades en las filas. Graficar \(q_x\) (complemento de \(p_x\)) en función de la edad para 2015 da:

swe_px %>%
    as.data.frame() %>%
    select(px = `2015`) %>%
    mutate(ages = 1:nrow(swe_px)-1) %>%
    ggplot() +
    geom_line(aes(x = ages, y = 1-px)) +
    scale_y_log10()

Y las tasas de fecundidad específicas por edad:

data("swe_asfr", package="DemoKin")
swe_asfr[26:30, 1:5]
##       1900    1901    1902    1903    1904
## 25 0.18104 0.18322 0.17980 0.17339 0.17595
## 26 0.18762 0.19279 0.19170 0.18754 0.18431
## 27 0.19838 0.20267 0.19365 0.19035 0.19298
## 28 0.20742 0.20543 0.19983 0.19558 0.19680
## 29 0.20192 0.21060 0.20264 0.19938 0.19541

Graficamos:

swe_asfr %>% as.data.frame() %>%
      as.data.frame() %>%
      select(fx = `2015`) %>%
      mutate(age = 1:nrow(swe_asfr)-1) %>%
      ggplot() +
      geom_line(aes(x = age, y = fx))

2. La función kin()

DemoKin se puede utilizar para calcular el número y la distribución por edad de los parientes de Focal bajo una serie de suposiciones, tanto para parientes vivos como fallecidos. La función DemoKin::kin() actualmente realiza la mayor parte del trabajo pesado en términos de implementar los modelos. Esto es cómo se ve en acción, en este caso asumiendo tasas demográficas invariables en el tiempo para el año 2015:

# Primero, obtener vectores para un año dado
swe_surv_2015 <- DemoKin::swe_px[,"2015"]
swe_asfr_2015 <- DemoKin::swe_asfr[,"2015"]
# Ejecutar
swe_2015 <- kin(p = swe_surv_2015, f = swe_asfr_2015, time_invariant = TRUE)

Los principales argumentos de la función kin son:

  • p: numérico. Un vector o matriz de probabilidades de supervivencia con filas como edades (y columnas como años en caso de una matriz).
  • f: numérico. Lo mismo que p, pero para tasas de fecundidad específicas por edad.
  • time_invariant: lógico. Suponer tasas invariables en el tiempo. Valor predeterminado TRUE.
  • output_kin: carácter. Tipos de parentesco para devolver: “m” para madre, “d” para hija, ver demokin_codes.
  • birth_female: numérico. Proporción de nacimientos femeninos. Establecido por defecto como \(1/2.04\). Esto multiplica el argumento f en algún momento, por lo que en caso de que ya estés utilizando tasas de fecundidad solo para descendencia femenina, este parámetro debe establecerse en 1.

Los parientes para el argumento output_kin se identifican mediante un código único.

Nota: los códigos de parentesco utilizados en DemoKin difieren de los de Caswell (2019). La equivalencia entre los dos conjuntos de códigos se muestra en la siguiente tabla, así que tenlo en cuenta en caso de alguna confusión:

demokin_codes
##    DemoKin Caswell               Labels_female                   Labels_male
## 1      coa       t    Cousins from older aunts     Cousins from older uncles
## 2      cya       v  Cousins from younger aunts   Cousins from younger uncles
## 3        c    <NA>                     Cousins                       Cousins
## 4        d       a                   Daughters                      Brothers
## 5       gd       b             Grand-daughters                    Grand-sons
## 6      ggd       c       Great-grand-daughters              Great-grand-sons
## 7      ggm       h          Great-grandmothers            Great-grandfathers
## 8       gm       g                Grandmothers                  Grandfathers
## 9        m       d                      Mother                        Father
## 10     nos       p   Nieces from older sisters   Nephews from older brothers
## 11     nys       q Nieces from younger sisters Nephews from younger brothers
## 12       n    <NA>                      Nieces                       Nephews
## 13      oa       r     Aunts older than mother     Uncles older than fathers
## 14      ya       s   Aunts younger than mother    Uncles younger than father
## 15       a    <NA>                       Aunts                        Uncles
## 16      os       m               Older sisters                Older brothers
## 17      ys       n             Younger sisters              Younger brothers
## 18       s    <NA>                     Sisters                      Brothers
##                          Labels_2sex
## 1    Cousins from older aunts/uncles
## 2  Cousins from younger aunts/uncles
## 3                            Cousins
## 4                           Siblings
## 5                    Grand-childrens
## 6              Great-grand-childrens
## 7                Great-grandfparents
## 8                       Grandparents
## 9                            Parents
## 10      Niblings from older siblings
## 11    Niblings from younger siblings
## 12                          Niblings
## 13   Aunts/Uncles older than parents
## 14 Aunts/Uncles younger than parents
## 15                      Aunts/Uncles
## 16                    Older siblings
## 17                  Younger siblings
## 18                          Siblings

La salida de DemoKin::kin() devuelve una lista que contiene dos data frames: kin_full y kin_summary.

str(swe_2015)
## List of 2
##  $ kin_full   : tibble [142,814 × 7] (S3: tbl_df/tbl/data.frame)
##   ..$ kin      : chr [1:142814] "d" "d" "d" "d" ...
##   ..$ age_kin  : int [1:142814] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ age_focal: int [1:142814] 0 1 2 3 4 5 6 7 8 9 ...
##   ..$ living   : num [1:142814] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ dead     : num [1:142814] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ cohort   : logi [1:142814] NA NA NA NA NA NA ...
##   ..$ year     : logi [1:142814] NA NA NA NA NA NA ...
##  $ kin_summary: tibble [1,414 × 10] (S3: tbl_df/tbl/data.frame)
##   ..$ age_focal     : int [1:1414] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ kin           : chr [1:1414] "coa" "cya" "d" "gd" ...
##   ..$ year          : logi [1:1414] NA NA NA NA NA NA ...
##   ..$ cohort        : logi [1:1414] NA NA NA NA NA NA ...
##   ..$ count_living  : num [1:1414] 0.2752 0.0898 0 0 0 ...
##   ..$ mean_age      : num [1:1414] 8.32 4.05 NaN NaN NaN ...
##   ..$ sd_age        : num [1:1414] 6.14 3.68 NaN NaN NaN ...
##   ..$ count_dead    : num [1:1414] 6.33e-05 3.70e-05 0.00 0.00 0.00 ...
##   ..$ count_cum_dead: num [1:1414] 6.33e-05 3.70e-05 0.00 0.00 0.00 ...
##   ..$ mean_age_lost : num [1:1414] 0 0 NaN NaN NaN 0 0 0 0 NaN ...
  • kin_full: Este data frame contiene el número esperado de parientes por año (o cohorte), edad de Focal y edad del pariente. El número de filas se debe a que tenemos 14 tipos de parientes, 101 edades de Focal y 101 edades de parientes.
head(swe_2015$kin_full)
## # A tibble: 6 × 7
##   kin   age_kin age_focal living  dead cohort year 
##   <chr>   <int>     <int>  <dbl> <dbl> <lgl>  <lgl>
## 1 d           0         0      0     0 NA     NA   
## 2 d           0         1      0     0 NA     NA   
## 3 d           0         2      0     0 NA     NA   
## 4 d           0         3      0     0 NA     NA   
## 5 d           0         4      0     0 NA     NA   
## 6 d           0         5      0     0 NA     NA
  • kin_summary: Este es un data frame ‘resumen’ derivado de kin_full. Para producirlo, sumamos todas las edades de parientes para obtener un data frame del número esperado de parientes por año o cohorte y edad de Focal (pero no por edad del pariente). Así es como se deriva el objeto kin_summary:
kin_by_age_Focal <-
  swe_2015$kin_full %>%
  group_by(cohort

, kin, age_focal) %>%
  summarise(count = sum(living)) %>%
  ungroup()
# Verificar que sean idénticos (solo para parientes vivos aquí)
kin_by_age_Focal %>%
  select(cohort, kin, age_focal, count) %>%
  identical(
    swe_2015$kin_summary %>%
      select(cohort, kin, age_focal, count = count_living) %>%
      arrange(cohort, kin, age_focal)
  )
## [1] TRUE

Hay muchos datos interesantes para explorar. Tómate un momento para interpretar qué información se devuelve en esas tablas. Todo proviene de las matrices que calculamos en la sección a mano.

Responde: Usando tus propias palabras, explica la diferencia entre los objetos kin_full y kin_summary.

Demos más contexto con algunos posibles ejemplos de preguntas de investigación.

3. Ejemplo: recuentos de parientes en poblaciones invariables en el tiempo para Suecia en 2015

Siguiendo a Caswell (2019), asumimos una población cerrada de mujeres en la que todas experimentan las tasas de mortalidad y fecundidad de Suecia en 2015 a cada edad a lo largo de su vida. Luego preguntamos:

¿Cómo podemos caracterizar la red de parentesco de un miembro promedio de la población (llamémosla ‘Focal’)?

Utilicemos los datos pre-cargados de Suecia y volvamos a ejecutar el modelo.

# Primero, obtener vectores para un año dado
swe_surv_2015 <- DemoKin::swe_px[,"2015"]
swe_asfr_2015 <- DemoKin::swe_asfr[,"2015"]
# Ejecutar el modelo de parentesco
swe_2015 <- kin(p = swe_surv_2015, f = swe_asfr_2015, time_invariant = TRUE)

Vamos a crear un vector para combinar algunos tipos de parientes (p. ej, queremos que ‘hermanas menores’ y ‘hermanas mayores’ sean simplemente ‘hermanas’):

consolidate_vec <- c("c", "c", "d", "gd", "ggd", "ggm", "gm", "m", "n", "n", "a", "a", "s", "s")
names(consolidate_vec) <- c("coa", "cya", "d", "gd", "ggd", "ggm", "gm", "m", "nos", "nys", "oa", "ya", "os", "ys")
3.1. Parientes vivos

Ahora, visualicemos cómo cambia el número esperado de hijas, hermanas, primas, etc., a lo largo de la vida de Focal. Utiliza DemoKin::rename_kin() con nombres completos para identificar cada tipo de pariente.

Responde: ¿Por qué algunos recuentos de parientes aumentan y otros disminuyen cuando Focal es joven? ¿Por qué algunos recuentos de parientes aumentan y otros disminuyen cuando Focal es mayor?

swe_2015$kin_summary %>%
  # Las proximas dos lineas simplemente agrupan parientes menore y mayores
  mutate(kin = consolidate_vec[kin]) %>% 
  summarise(count_living = sum(count_living), .by = c(age_focal, kin)) %>% 
  # rename_kin convierte codigos para identificar a parientes a los nombres correspondientes
  rename_kin() %>% 
  ggplot() +
  geom_line(aes(age_focal, count_living))  +
  labs(x = "Edad de Focal") +
  theme_bw() +
  facet_wrap(~kin_label)
## Joining with `by = join_by(kin)`

Puedes pensar en los resultados como análogos a la esperanza de vida (es decir, los años esperados de vida para una cohorte sintética que experimenta un conjunto dado de tasas de mortalidad), un indicador de período. Una diferencia clave es que la medida \(e_x\) es independiente de lo que sucedió en años anteriores. La estructura del parentesco, por otro lado, depende de condiciones anteriores, como la distribución de edades de la madre de Focal.

Reunamos todas las líneas anteriores en un gráfico de áreas para estudiar la composición del parentesco por edad.

swe_2015$kin_summary %>%
  select(age_focal, kin, count_living) %>%
  # Las proximas dos lineas simplemente agrupan parientes menore y mayores
  mutate(kin = consolidate_vec[kin]) %>% 
  summarise(count_living = sum(count_living), .by = c(age_focal, kin)) %>% 
  # rename_kin convierte codigos para identificar a parientes a los nombres correspondientes
  rename_kin() %>% 
  ggplot(aes(x = age_focal, y = count_living)) +
  geom_area(aes(fill = kin_label), colour = "black") +
  labs(x = "Edad de Focal", y = "Número de parientes femeninas vivas") +
  theme_bw() +
  scale_x_continuous(labels = seq(0, 100, 10), breaks = seq(0, 100, 10)) +
  theme(legend.position = "bottom")
## Joining with `by = join_by(kin)`

Responde:

  • ¿Cómo varía el tamaño general de la familia (y la composición de la familia) a lo largo de la vida de una mujer promedio en cada edad?
  • ¿Cuándo tiene Focal más parientes en total?
  • ¿Cómo varía la composición de la familia en las etapas de la vida de Focal?
3.2. Distribución por edad de los parientes vivos cuando Focal tiene cierta edad

¿Qué edad tienen los parientes de Focal en algunos momentos de la vida de Focal? ¿Qué ve a su alrededor cuando se detiene un momento al cruzar su línea diagonal-Lexis? Utilizando el data frame kin_full, podemos visualizar la distribución por edad de los parientes de Focal a lo largo de su vida. Por ejemplo, cuando Focal tiene 35 años, el patrón de edad de sus parientes es:

swe_2015$kin_full %>%
  # Las proximas dos lineas simplemente agrupan parientes menore y mayores
  mutate(kin = consolidate_vec[kin]) %>% 
  summarise(living = sum(living), .by = c(age_focal, age_kin, kin)) %>% 
  # rename_kin convierte codigos para identificar a parientes a los nombres correspondientes
  rename_kin() %>% 
  filter(age_focal == 35) %>%
  ggplot() +
  geom_line(aes(age_kin, living)) +
  geom_vline(xintercept = 35, color=2) +
  labs(y = "Número esperado de parientes vivos") +
  theme_bw() +
  facet_wrap(~kin_label)
## Joining with `by = join_by(kin)`

Responde: Considera la distribución por edad de cada tipo de pariente en relación con la edad actual de Focal (es decir, 35). ¿Cuáles parientes son más jóvenes y cuáles son mayores? ¿Tiene esto sentido intuitivamente?

Si sumamos la densidad para cada tipo de pariente, obtenemos el número total de parientes vivos. Visualicemos esto cuando Focal tiene 35 años en una población invariable en el tiempo utilizando un diagrama de parentesco o diagrama de kinship ‘Keyfitz’ (Keyfitz and Caswell 2005) con la función plot_diagram.

Tómate un momento para interpretar los valores. Responde: ¿Cuál es el número esperado de hermanas (independientemente de su edad) para una Focal de 35 años?

swe_2015$kin_summary %>%
  filter(age_focal == 35) %>%
  select(kin, count = count_living) %>%
  plot_diagram(rounding = 2)