Capítulo 2 Base de datos

En esta clase nos vamos a centrar en el uso de tidyverse. Además vamos a utilizar funciones de lubridate y zoo que tienen algunas funciones especiales para trabajar con fechas.

En R existen dos tipos de bases de datos data.frame() y tibble() que son las bases de datos de tidyverse el mejor paquete para manipulación y transformación de datos (ver Wickham y Grolemund (2017)). Un data.frame (objeto df) se convierte fácilmente a tibble (y viceversa).

# Un data.frame (objeto df) se convierte fácilmente a tibble
tib = as_tibble(df)

Las tibbles tienen algunas funciones especiales como poder usar nombres de variables con espacio o números (se deben utilizar back ticks).

library(tidyverse)
tb <- tibble(
  `Plazo Fijo` = "espacio", 
  `2000` = "numero"
)
tb
## # A tibble: 1 × 2
##   `Plazo Fijo` `2000`
##   <chr>        <chr> 
## 1 espacio      numero

2.1 Directorio de trabajo

# Para ver en que directorio estamos trabajando
getwd() 
# Definir directorio. Notar barras invertidas en la ruta
setwd('C:/Documentos/CianciaDatos') 

2.2 Cargar datos

La función fread() del paquete data.table es la más eficiente para grandes volúmenes de datos porque permite paralelizar con multithread.

# CSV
bd = read.csv("b_datos.csv", header=TRUE, stringsAsFactors=TRUE, sep=",")

bd = data.table::fread('b_datos.txt', header=TRUE, stringsAsFactors=F, sep='\t', nThread=2)

bd = read.delim('./datos/b_datos.txt', header=TRUE, stringsAsFactors=F, sep='\t')
# Excel
# También puede suministrarse la ruta de acceso completa 
bd = readxl::read_excel('./data/datos_WB.xlsx', sheet='1')
str(bd)
## tibble [60 × 11] (S3: tbl_df/tbl/data.frame)
##  $ year      : num [1:60] 2011 2011 2011 2011 2011 ...
##  $ cname     : chr [1:60] "Argentina" "Brazil" "Chile" "France" ...
##  $ ccode     : chr [1:60] "ARG" "BRA" "CHL" "FRA" ...
##  $ gdp_pc2010: num [1:60] 10883 11628 13456 41369 36228 ...
##  $ gdp_pc2017: num [1:60] 24648 15323 22338 42864 42892 ...
##  $ gdp_2010  : num [1:60] 4.49e+11 2.30e+12 2.32e+11 2.70e+12 2.15e+12 ...
##  $ credit_ps : num [1:60] 14 58.1 101.3 96.8 94.1 ...
##  $ inv       : num [1:60] 17.2 20.6 23.1 22.4 19.7 ...
##  $ exports   : num [1:60] 18.4 11.6 37.8 28.4 26.9 ...
##  $ imports   : num [1:60] 16.8 12.4 34.4 30.4 28.3 ...
##  $ popu      : num [1:60] 4.13e+07 1.98e+08 1.72e+07 6.53e+07 5.94e+07 ...
Tabla 2.1: Vista de la base de datos (World Bank)
year cname ccode gdp_pc2010 gdp_pc2017
2,011 Argentina ARG 10,883 24,648
2,011 Brazil BRA 11,628 15,323
2,011 Chile CHL 13,456 22,338
2,011 France FRA 41,369 42,864
2,011 Italy ITA 36,228 42,892
2,011 United Kingdom GBR 39,729 42,294

2.2.1 Ingrasar datos con tidyverse

Comando Separador
read_csv() coma
read_csv2() punto y coma
read_tsv() tab
read_delim() otros

2.2.2 Bases de Stata

library(heaven)
read_dta(...)
write_dta(...)

2.3 Problemas de imputación

En esta sección se presentan algunas alternativas para solucionar problemas de imputación de datos, es decir, al cargar el archivo original el formato de alguna variable es distinto del esperado. Las funciones parse_*() toman un vector character y devuelven un vector del tipo indicado como lógico, entero o fecha.5

# Parsear vectores
library(readr)
str(parse_logical(c("TRUE", "FALSE", "NA")))
##  logi [1:3] TRUE FALSE NA
str(parse_integer(c("1", "2", "3")))
##  int [1:3] 1 2 3
str(parse_date(c("2010-01-01", "1979-10-14")))
##  Date[1:2], format: "2010-01-01" "1979-10-14"
parse_integer(c("1", "231", ".", "456"), na = ".")
## [1]   1 231  NA 456
parse_double("1,23", locale = locale(decimal_mark = ","))
## [1] 1.23

Al parsear un archivo readr adivina el formato mirando las primeras 1000 filas. Puede haber dos problemas básicos:

  • Las primeras mil filas pueden ser un caso especial, y readr adivina un tipo que no es suficientemente general. Por ejemplo, puede tener una columna de dobles que sólo contenga enteros en las primeras 1000 filas.

  • La columna puede contener muchos valores missing. Si las primeras 1000 filas contienen sólo NAs, readr adivinará que se trata de un vector lógico, mientras que probablemente sea algo más específico.

El ejemplo de abajo dejo de funcionar ya que antes mostraba otro error pero de todas formas ilustra como indicar el tipo de dato de cada variable.

challenge <- read_csv(readr_example('challenge.csv'))
## Rows: 2000 Columns: 2
## ── Column specification ─────────────────────────────
## Delimiter: ","
## dbl  (1): x
## date (1): y
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
tail(challenge)
## # A tibble: 6 × 2
##       x y         
##   <dbl> <date>    
## 1 0.805 2019-11-21
## 2 0.164 2018-03-29
## 3 0.472 2014-08-04
## 4 0.718 2015-08-16
## 5 0.270 2020-02-04
## 6 0.608 2019-01-06
problems(challenge)
## # A tibble: 0 × 5
## # ℹ 5 variables: row <int>, col <int>, expected <chr>, actual <chr>, file <chr>
challenge <- read_csv(
  readr_example('challenge.csv'), 
  col_types = cols(x = col_double(),
                   y = col_date()))
tail(challenge)
## # A tibble: 6 × 2
##       x y         
##   <dbl> <date>    
## 1 0.805 2019-11-21
## 2 0.164 2018-03-29
## 3 0.472 2014-08-04
## 4 0.718 2015-08-16
## 5 0.270 2020-02-04
## 6 0.608 2019-01-06

2.4 Exportar datos

# CSV
write.csv(bd,"b_datos.csv")
write_csv()
write_excel_csv()
# TXT 
write_delim()
write_tsv()

# Excel
library("xlsx")
out <- list('bd' = BD1, 't1' = TAB1, 't2' = TAB2)
write.xlsx(out, file = 'resutados.xlsx')

2.5 Pipe

Se llama pipe al símbolo %>% (shortcut con: Ctrl/Cmd + Shift + M) que cumple la función de una función compuesta. Es decir, una secuencia de operaciones del tipo: \(h(g(f(x)))\).

A partir de la versión de R 4.1 se puede utilizar |>.

Dicho de otra forma: \(x\) %>% \(f\) %>% \(g\) %>% \(h\).

La sintaxis general de una función es FN(OBJETO, ...) y lo que hace la pipa es enviar el objeto a la posición correspondiente sin necesidad de expresarlo explícitamente. Por lo tanto, la sintaxis anterior puede expresarse equivalentemente con una pipa de la siguiente manera: OBJETO %>% FN( , ...).

2.6 Variables

library(tidyverse)
bd1 = bd %>% 
  mutate(gdp_pc2010bis = gdp_2010 / popu, # crear variable
         logGDP_pc2010 = log(gdp_pc2010),
         open = exports + imports,
         inv_demean = inv - mean(inv)) %>%
  rename(poblacion = popu) %>%  # rename (newname = oldname)
  mutate(gdp_2010 = NULL)       # drop (también con select(-gdp_2010))
year cname gdp_pc2010 gdp_pc2010bis open inv_demean
2,011 Argentina 10,883 10,883 35.2 -2
2,011 Brazil 11,628 11,628 23.9 2
2,011 Chile 13,456 13,456 72.2 4
2,011 France 41,369 41,369 58.8 4
2,011 Italy 36,228 36,228 55.1 1
2,011 United Kingdom 39,729 39,729 62.4 -3

2.7 Merge

meta = readxl::read_excel('./data/datos_WB.xlsx', sheet='2')
bd = left_join(bd, meta, by=c('ccode')) # clave de union character no suele ser la mejor
year cname region
2011 Argentina Latin America & Caribbean
2011 Brazil Latin America & Caribbean
2011 Chile Latin America & Caribbean
2011 France Europe & Central Asia
2011 Italy Europe & Central Asia
2011 United Kingdom Europe & Central Asia

2.8 Variables: group_by, mutate

# Si quiero usar una función propia
demean = function(x) {x - mean(x, na.rm = TRUE)}
bd = bd %>% 
  mutate(open = exports + imports) %>%
  dplyr::select(ccode, year, region, gdp_pc2017, credit_ps, inv, open) %>%
    arrange(ccode, year) %>%
  group_by(ccode) %>%
  mutate(obs = seq(1,length(ccode)),     # igual con row_number()
         gdp_gr = 100 * (gdp_pc2017 / dplyr::lag(gdp_pc2017, 1) - 1),
         credit_ps_mean = mean(credit_ps, na.rm = TRUE),
         dev = ifelse(region=='Latin America & Caribbean', 0, 1),
         gdp_dem = demean(gdp_pc2017)) %>%
  ungroup()
head(bd[c('ccode', 'dev', 'year', 'gdp_pc2017', 'gdp_gr', 'gdp_dem')],10)
## # A tibble: 10 × 6
##    ccode   dev  year gdp_pc2017 gdp_gr  gdp_dem
##    <chr> <dbl> <dbl>      <dbl>  <dbl>    <dbl>
##  1 ARG       0  2011     24648.  NA     1451.  
##  2 ARG       0  2012     24119.  -2.15   922.  
##  3 ARG       0  2013     24424.   1.27  1227.  
##  4 ARG       0  2014     23550.  -3.58   353.  
##  5 ARG       0  2015     23934.   1.63   737.  
##  6 ARG       0  2016     23190.  -3.11    -7.58
##  7 ARG       0  2017     23597.   1.76   400.  
##  8 ARG       0  2018     22759.  -3.55  -438.  
##  9 ARG       0  2019     22064.  -3.06 -1133.  
## 10 ARG       0  2020     19687. -10.8  -3511.
# case_when() permite evaluar más de 2 alternativas
# En el caso de tener solo 2 se puede usar la funcion ifelse()

df <- tibble(
  a = seq(1,5)
)
df = df %>% mutate(b = case_when(a <= 2 ~ 1,
                                 a > 2 & a <= 4 ~ 2,
                                 TRUE ~ as.double(a)))
df
## # A tibble: 5 × 2
##       a     b
##   <int> <dbl>
## 1     1     1
## 2     2     1
## 3     3     2
## 4     4     2
## 5     5     5

2.9 Guardar datos

bd = bd %>% select(ccode, year, region, gdp_gr, credit_ps, inv, open)
save(bd, file="datos_wb.rda")
ccode year region gdp_gr credit_ps inv open
ARG 2018 Latin America & Caribbean -3.6 NA 14.7 31.2
ARG 2019 Latin America & Caribbean -3.1 NA 13.5 32.6
ARG 2020 Latin America & Caribbean -10.8 NA 13.4 30.5
BRA 2018 Latin America & Caribbean 1.0 60.2 15.1 28.9
BRA 2019 Latin America & Caribbean 0.7 62.6 15.3 28.5
BRA 2020 Latin America & Caribbean -4.7 70.2 16.4 32.4
GBR 2018 Europe & Central Asia 0.6 134.6 17.8 63.0
GBR 2019 Europe & Central Asia 0.8 133.5 18.0 63.4
GBR 2020 Europe & Central Asia -10.3 146.4 17.6 55.1
ITA 2018 Europe & Central Asia 1.1 76.7 17.8 60.3
ITA 2019 Europe & Central Asia 1.5 74.3 18.0 60.1
ITA 2020 Europe & Central Asia -8.6 83.6 17.8 55.3

2.10 Valores missing

Son tratados como los valores más grandes de todos pero el replace no los considera. Notar la diferencia de comportamiento entre este último y el arrange().

df2 <- tibble(
  a = sample(1:5, 5, replace = F),
  b = seq(5,1),
)
df2
## # A tibble: 5 × 2
##       a     b
##   <int> <int>
## 1     1     5
## 2     3     4
## 3     2     3
## 4     5     2
## 5     4     1
df2 = df2 %>% mutate(b = ifelse(b == 2, NA, b)) 
df2 = df2 %>% mutate(c = ifelse(b > 3, 0, b))
df2 = df2 %>% arrange(b)
df2
## # A tibble: 5 × 3
##       a     b     c
##   <int> <int> <dbl>
## 1     4     1     1
## 2     2     3     3
## 3     3     4     0
## 4     1     5     0
## 5     5    NA    NA

2.10.1 Eliminar valores missing

Se debe tener presente que se elimina la fila completa, por lo tanto, antes de descartarlos hay considerar si los valores missing son aleatorios o contienen algo de información.

#  Volvemos a la base de WB. Recordamos la estructura
str(bd)
## tibble [60 × 7] (S3: tbl_df/tbl/data.frame)
##  $ ccode    : chr [1:60] "ARG" "ARG" "ARG" "ARG" ...
##  $ year     : num [1:60] 2011 2012 2013 2014 2015 ...
##  $ region   : chr [1:60] "Latin America & Caribbean" "Latin America & Caribbean" "Latin America & Caribbean" "Latin America & Caribbean" ...
##  $ gdp_gr   : num [1:60] NA -2.15 1.27 -3.58 1.63 ...
##  $ credit_ps: num [1:60] 14 15.2 15.7 13.8 14.4 ...
##  $ inv      : num [1:60] 17.2 15.9 16.3 16 15.6 ...
##  $ open     : num [1:60] 35.2 30.5 29.3 28.4 22.5 ...
summary(bd[,1:4])
##     ccode                year         region              gdp_gr        
##  Length:60          Min.   :2011   Length:60          Min.   :-10.7750  
##  Class :character   1st Qu.:2013   Class :character   1st Qu.: -2.7656  
##  Mode  :character   Median :2016   Mode  :character   Median :  0.7100  
##                     Mean   :2016                      Mean   : -0.6777  
##                     3rd Qu.:2018                      3rd Qu.:  1.4095  
##                     Max.   :2020                      Max.   :  4.3092  
##                                                       NA's   :6
# cuenta valores missing de 
# Crecimiento del PIB y Credito al SPriv.
sum(is.na(bd$gdp_gr)) 
## [1] 6
sum(is.na(bd$credit_ps))
## [1] 4
sum(ifelse(is.na(bd$gdp_gr&bd$credit_ps),1,0))
## [1] 10
bd1 = na.omit(bd)
nrow(bd1)
## [1] 50
rm('bd1')

2.11 Loop

set.seed(1234)
df <- tibble(
  a = runif(100, min=0, max=100),
  b = rnorm(100, 0, 1),
  c = rnorm(100, mean=5, sd=3),
)
head(df,3)
## # A tibble: 3 × 3
##       a      b     c
##   <dbl>  <dbl> <dbl>
## 1  11.4 -1.81   3.87
## 2  62.2 -0.582  5.29
## 3  60.9 -1.11   9.92
# Reemplazar variables existentes
vars = names(df)
for (v in vars) {
  df[v] = df[v] * 100
}

head(df,3)
## # A tibble: 3 × 3
##       a      b     c
##   <dbl>  <dbl> <dbl>
## 1 1137. -181.   387.
## 2 6223.  -58.2  529.
## 3 6093. -111.   992.
# Generar varaibles nuevas (estilo Stata, no se usa en R)
# Dividir las dos ultimas (b y c) por la primera (a)
set.seed(1234)
df1 <- tibble(
  a = rep(2, 100),
  b = rnorm(100, 0, 1),
  c = rnorm(100, 5, 3),
)
vars = names(df1[2:length(df1)])
for (v in vars) {
  df1[paste0(v,'_a')] = df1[v] / df1[['a']]
}
head(df1,3)
## # A tibble: 3 × 5
##       a      b     c    b_a   c_a
##   <dbl>  <dbl> <dbl>  <dbl> <dbl>
## 1     2 -1.21   6.24 -0.604  3.12
## 2     2  0.277  3.58  0.139  1.79
## 3     2  1.08   5.20  0.542  2.60

2.12 Pivot (Reshape)

# Long
bdAR = bd %>% 
         dplyr::filter(ccode=='ARG') %>%
         dplyr::select(year, credit_ps, inv) %>%
         pivot_longer(cols=-year, names_to="Var", values_to="Val") %>%
         arrange(year, desc(Var))    # Sort
year Var Val
2011 inv 17.2
2011 credit_ps 14.0
2012 inv 15.9
2012 credit_ps 15.2
2013 inv 16.3
2013 credit_ps 15.7
# Wide
bdAR2 = bdAR %>% 
         dplyr::filter(Var=='credit_ps', year <=2015) %>%
         mutate(ccode = 'ARG') %>%
         pivot_wider(id_cols=ccode, names_from=year, values_from=Val) %>%
         rename_with(~paste0("CREDIT", 2011:2015), where(is.numeric))
ccode CREDIT2011 CREDIT2012 CREDIT2013 CREDIT2014 CREDIT2015
ARG 14 15.2 15.7 13.8 14.4
# Otra forma de llevar a long starts_with()
bdAR3 = bdAR2 %>% 
       pivot_longer(cols = starts_with("CREDIT"), names_to="Var", values_to="Val") %>% 
       separate(Var, c("V","year"), sep = 6)
# unite() para concatenar variables
ccode V year Val
ARG CREDIT 2011 14.0
ARG CREDIT 2012 15.2
ARG CREDIT 2013 15.7
ARG CREDIT 2014 13.8
ARG CREDIT 2015 14.4

2.13 Row bind (Append)

bdAR = bd %>%
  dplyr::filter(ccode=="ARG",
         year>=2018) %>%
  dplyr::select(year, ccode, gdp_gr)
bdBR = bd %>%
  dplyr::filter(ccode=="BRA",
         year>=2018) %>%
  dplyr::select(year, ccode, gdp_gr)
bdARBR = rbind(bdAR, bdBR)
# Ver bind_rows() de tidyverse
year ccode gdp_gr
2018 ARG -3.6
2019 ARG -3.1
2020 ARG -10.8
2018 BRA 1.0
2019 BRA 0.7
2020 BRA -4.7

2.14 Strings

Se presentan algunas funciones básicas. Para más alternativas ver el paquete stringr.

words = c('uno', 'dos', 'tres')
length(words)   # cuenta los elementos del vector
## [1] 3
str_length(words)
## [1] 3 3 4
words = gsub('tres', 'cinco', words)
words
## [1] "uno"   "dos"   "cinco"
words = str_replace(words, 'uno', 'diez')
words
## [1] "diez"  "dos"   "cinco"
hi = 'hola'
nchar(hi)
## [1] 4

2.15 Fechas

Formato de fechas.

Year Month Day
%Y (4 dígitos) %m (2 dígitos) %d (2 dígitos)
%y (2 dígitos) %b (nombre “Jan”)
%B (nombre “January”)

Nota: %y 00-69 hace referencia a 2000-2069 y, 70-99 indica 1970-1999.

library(zoo)
library(lubridate)
datos = readxl::read_excel('./data/datos_ts.xlsx', sheet='datos')
datos$fecha = as.Date(datos$fecha, format = '%Y-%m-%d')
datos$fecha2 = datos$fecha + days(15)
datos$fecha3 = floor_date(datos$fecha2, 'month')
datos$mes = month(datos$fecha)
datos$year = year(datos$fecha)
datos = datos[,c(1,5,6,7,8,2,3,4)] # reordena la base de datos
fecha fecha2 fecha3 mes year ipc tcn emae_sa
2015-01-01 2015-01-16 2015-01-01 1 2015 57.6 8.6 144.2
2015-02-01 2015-02-16 2015-02-01 2 2015 58.5 8.7 148.0
2015-03-01 2015-03-16 2015-03-01 3 2015 59.5 8.8 147.7
2015-04-01 2015-04-16 2015-04-01 4 2015 60.9 8.9 149.8
2015-05-01 2015-05-16 2015-05-01 5 2015 62.2 9.0 149.7
2015-06-01 2015-06-16 2015-06-01 6 2015 63.0 9.1 150.6

2.15.1 Manipulación de fechas

Utilizamos el paquete zoo.

datosq <- readxl::read_excel('./data/datos_ts.xlsx', sheet='trim')  %>%
  mutate(fecha=as.Date(as.yearqtr(paste(year, trim), format="%Y %q")))
year trim ipc tcn emae_sa fecha
2015 1 57.6 8.6 144.2 2015-01-01
2015 2 60.9 8.9 149.8 2015-04-01
2015 3 64.3 9.2 150.8 2015-07-01
2015 4 67.7 9.5 149.4 2015-10-01
2016 1 74.7 13.9 147.8 2016-01-01
2016 2 85.5 14.3 145.0 2016-04-01

2.16 Análisis de datos

str(bd)
## tibble [60 × 7] (S3: tbl_df/tbl/data.frame)
##  $ ccode    : chr [1:60] "ARG" "ARG" "ARG" "ARG" ...
##  $ year     : num [1:60] 2011 2012 2013 2014 2015 ...
##  $ region   : chr [1:60] "Latin America & Caribbean" "Latin America & Caribbean" "Latin America & Caribbean" "Latin America & Caribbean" ...
##  $ gdp_gr   : num [1:60] NA -2.15 1.27 -3.58 1.63 ...
##  $ credit_ps: num [1:60] 14 15.2 15.7 13.8 14.4 ...
##  $ inv      : num [1:60] 17.2 15.9 16.3 16 15.6 ...
##  $ open     : num [1:60] 35.2 30.5 29.3 28.4 22.5 ...
dim(bd)
## [1] 60  7
names(bd)
## [1] "ccode"     "year"      "region"    "gdp_gr"    "credit_ps" "inv"      
## [7] "open"
glimpse(bd)
## Rows: 60
## Columns: 7
## $ ccode     <chr> "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG", "ARG…
## $ year      <dbl> 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, …
## $ region    <chr> "Latin America & Caribbean", "Latin America & Caribbean", "L…
## $ gdp_gr    <dbl> NA, -2.1452844, 1.2656852, -3.5785805, 1.6296643, -3.1100639…
## $ credit_ps <dbl> 14.00872, 15.21282, 15.72909, 13.82377, 14.41423, 13.66763, …
## $ inv       <dbl> 17.24828, 15.85753, 16.28951, 15.97995, 15.56475, 14.27236, …
## $ open      <dbl> 35.20615, 30.52654, 29.33393, 28.40679, 22.48623, 26.09389, …
head(bd)
## # A tibble: 6 × 7
##   ccode  year region                    gdp_gr credit_ps   inv  open
##   <chr> <dbl> <chr>                      <dbl>     <dbl> <dbl> <dbl>
## 1 ARG    2011 Latin America & Caribbean  NA         14.0  17.2  35.2
## 2 ARG    2012 Latin America & Caribbean  -2.15      15.2  15.9  30.5
## 3 ARG    2013 Latin America & Caribbean   1.27      15.7  16.3  29.3
## 4 ARG    2014 Latin America & Caribbean  -3.58      13.8  16.0  28.4
## 5 ARG    2015 Latin America & Caribbean   1.63      14.4  15.6  22.5
## 6 ARG    2016 Latin America & Caribbean  -3.11      13.7  14.3  26.1

2.16.1 Tablas

Los valores NA afectan a todas las estadísticas. Opción na.rm = F / T.

bd %>% summarise(
  credit_ps_media = mean(credit_ps),
  inv_max = max(inv),
  open_min = min(open)
)
## # A tibble: 1 × 3
##   credit_ps_media inv_max open_min
##             <dbl>   <dbl>    <dbl>
## 1              NA    24.9     22.5

2.17 group_by, summarise

tab = bd %>% 
  dplyr::select_if(is.numeric) %>% 
  pivot_longer(everything(), names_to = 'Variable', values_to = 'Value') %>%
  group_by(Variable) %>% 
  summarise(
    Obs = n(),
    Media = mean(Value, na.rm = T),
    Mediana = median(Value, na.rm = T),
    SD = sd(Value, na.rm = T),
    Min = min(Value, na.rm = T),
    Max = max(Value, na.rm = T)) %>% 
  ungroup()
tab
## # A tibble: 5 × 7
##   Variable    Obs    Media  Mediana    SD    Min     Max
##   <chr>     <int>    <dbl>    <dbl> <dbl>  <dbl>   <dbl>
## 1 credit_ps    60   89.7     94.6   38.9    13.7  171.  
## 2 gdp_gr       60   -0.678    0.710  3.34  -10.8    4.31
## 3 inv          60   18.8     17.8    3.19   13.4   24.9 
## 4 open         60   49.1     56.2   15.7    22.5   72.2 
## 5 year         60 2016.    2016.     2.90 2011   2020
tab = bd %>% 
  dplyr::filter(year>=2015) %>% 
  group_by(year, region) %>% 
  summarise(
    inv_sum = sum(inv, na.rm = T),
    inv_sd = sd(inv, na.rm = T),
    credit_ps_p50 = median(credit_ps, na.rm = T),
    obs = n()
    ) %>% 
  arrange(year) %>% 
  ungroup()
tab
## # A tibble: 12 × 6
##     year region                    inv_sum inv_sd credit_ps_p50   obs
##    <dbl> <chr>                       <dbl>  <dbl>         <dbl> <int>
##  1  2015 Europe & Central Asia        55.7   2.55          95.1     3
##  2  2015 Latin America & Caribbean    57.2   4.24          66.8     3
##  3  2016 Europe & Central Asia        56.7   2.54          97.4     3
##  4  2016 Latin America & Caribbean    52.5   4.57          62.2     3
##  5  2017 Europe & Central Asia        58.0   2.76         101.      3
##  6  2017 Latin America & Caribbean    50.7   3.57          59.5     3
##  7  2018 Europe & Central Asia        58.6   2.93         104.      3
##  8  2018 Latin America & Caribbean    51.2   3.81          88.6     3
##  9  2019 Europe & Central Asia        59.6   3.26         108.      3
## 10  2019 Latin America & Caribbean    51.8   4.98          93.2     3
## 11  2020 Europe & Central Asia        58.2   3.02         124.      3
## 12  2020 Latin America & Caribbean    50.7   3.78          70.2     3
tab = tab %>% 
 mutate(region = str_replace_all(region, (c("Europe & Central Asia" = "EU", "Latin America & Caribbean" = "LA")))) %>%
 pivot_longer(cols=-c(year, region), names_to='Var', values_to='Val') %>%
 unite(id,region, Var) %>% 
 pivot_wider(id_cols=year, names_from=id, values_from=Val)
tab
## # A tibble: 6 × 9
##    year EU_inv_sum EU_inv_sd EU_credit_ps_p50 EU_obs LA_inv_sum LA_inv_sd
##   <dbl>      <dbl>     <dbl>            <dbl>  <dbl>      <dbl>     <dbl>
## 1  2015       55.7      2.55             95.1      3       57.2      4.24
## 2  2016       56.7      2.54             97.4      3       52.5      4.57
## 3  2017       58.0      2.76            101.       3       50.7      3.57
## 4  2018       58.6      2.93            104.       3       51.2      3.81
## 5  2019       59.6      3.26            108.       3       51.8      4.98
## 6  2020       58.2      3.02            124.       3       50.7      3.78
## # ℹ 2 more variables: LA_credit_ps_p50 <dbl>, LA_obs <dbl>

2.18 Vector de resultados

set.seed(1234)
df <- tibble(
  a = runif(100, min=0, max=100),
  b = rnorm(100,0,1),
  c = rnorm(100, mean=5, sd=3),
)

output <- vector("double", ncol(df)) # 1. verctor de resultados (vacio)
for (i in seq_along(df)) {           # 2. secuencia
  output[[i]] <- mean(df[[i]])       # 3. cuerpo
}
output
## [1] 43.74972619  0.07975381  5.40972645

Bibliografia

Wickham, Hadley, y Garrett Grolemund. 2017. R for Data Science. O’REILLY. https://r4ds.had.co.nz/.

  1. Ver más especificaciones aquí.↩︎