Esta parte se basa en el libro de Hadley Wickham:
5/4/2018
Esta parte se basa en el libro de Hadley Wickham:
dplyrFunciones para las tareas más comunes:
filterselectarrangemutatesummarisegroup_bylibrary(dplyr)
dplyr es un estándar que simplifica.
msleep <- read.csv("../data/msleep_ggplot2.csv")
names(msleep)
## [1] "name" "genus" "vore" "order" ## [5] "conservation" "sleep_total" "sleep_rem" "sleep_cycle" ## [9] "awake" "brainwt" "bodywt"
selectSelecciona columnas.
head(select(msleep, name, sleep_total))
## name sleep_total ## 1 Cheetah 12.1 ## 2 Owl monkey 17.0 ## 3 Mountain beaver 14.4 ## 4 Greater short-tailed shrew 14.9 ## 5 Cow 4.0 ## 6 Three-toed sloth 14.4
select (2)head(select(msleep, -name))
## genus vore order conservation sleep_total sleep_rem ## 1 Acinonyx carni Carnivora lc 12.1 NA ## 2 Aotus omni Primates <NA> 17.0 1.8 ## 3 Aplodontia herbi Rodentia nt 14.4 2.4 ## 4 Blarina omni Soricomorpha lc 14.9 2.3 ## 5 Bos herbi Artiodactyla domesticated 4.0 0.7 ## 6 Bradypus herbi Pilosa <NA> 14.4 2.2 ## sleep_cycle awake brainwt bodywt ## 1 NA 11.9 NA 50.000 ## 2 NA 7.0 0.01550 0.480 ## 3 NA 9.6 NA 1.350 ## 4 0.1333333 9.1 0.00029 0.019 ## 5 0.6666667 20.0 0.42300 600.000 ## 6 0.7666667 9.6 NA 3.850
select (3)head(select(msleep, starts_with("sl")))
## sleep_total sleep_rem sleep_cycle ## 1 12.1 NA NA ## 2 17.0 1.8 NA ## 3 14.4 2.4 NA ## 4 14.9 2.3 0.1333333 ## 5 4.0 0.7 0.6666667 ## 6 14.4 2.2 0.7666667
Existen muchas variaciones:
ends_withcontainsmatchesone_ofSfilterSelecciona filas.
head(filter(msleep, sleep_total >= 16))
## name genus vore order conservation ## 1 Owl monkey Aotus omni Primates <NA> ## 2 Long-nosed armadillo Dasypus carni Cingulata lc ## 3 North American Opossum Didelphis omni Didelphimorphia lc ## 4 Big brown bat Eptesicus insecti Chiroptera lc ## 5 Thick-tailed opposum Lutreolina carni Didelphimorphia lc ## 6 Little brown bat Myotis insecti Chiroptera <NA> ## sleep_total sleep_rem sleep_cycle awake brainwt bodywt ## 1 17.0 1.8 NA 7.0 0.01550 0.480 ## 2 17.4 3.1 0.3833333 6.6 0.01080 3.500 ## 3 18.0 4.9 0.3333333 6.0 0.00630 1.700 ## 4 19.7 3.9 0.1166667 4.3 0.00030 0.023 ## 5 19.4 6.6 NA 4.6 NA 0.370 ## 6 19.9 2.0 0.2000000 4.1 0.00025 0.010
filter (2)Selecciona filas.
head(filter(msleep, sleep_total >= 16, bodywt >= 1))
## name genus vore order conservation ## 1 Long-nosed armadillo Dasypus carni Cingulata lc ## 2 North American Opossum Didelphis omni Didelphimorphia lc ## 3 Giant armadillo Priodontes insecti Cingulata en ## sleep_total sleep_rem sleep_cycle awake brainwt bodywt ## 1 17.4 3.1 0.3833333 6.6 0.0108 3.5 ## 2 18.0 4.9 0.3333333 6.0 0.0063 1.7 ## 3 18.1 6.1 NA 5.9 0.0810 60.0
filter (3)head(filter(msleep, order %in% c("Perissodactyla")))
## name genus vore order conservation sleep_total ## 1 Horse Equus herbi Perissodactyla domesticated 2.9 ## 2 Donkey Equus herbi Perissodactyla domesticated 3.1 ## 3 Brazilian tapir Tapirus herbi Perissodactyla vu 4.4 ## sleep_rem sleep_cycle awake brainwt bodywt ## 1 0.6 1.0 21.1 0.655 521.000 ## 2 0.4 NA 20.9 0.419 187.000 ## 3 1.0 0.9 19.6 0.169 207.501
%in%arrangeOrdena las filas.
msleep %>% arrange(sleep_total) %>% head
## name genus vore order conservation ## 1 Giraffe Giraffa herbi Artiodactyla cd ## 2 Pilot whale Globicephalus carni Cetacea cd ## 3 Horse Equus herbi Perissodactyla domesticated ## 4 Roe deer Capreolus herbi Artiodactyla lc ## 5 Donkey Equus herbi Perissodactyla domesticated ## 6 African elephant Loxodonta herbi Proboscidea vu ## sleep_total sleep_rem sleep_cycle awake brainwt bodywt ## 1 1.9 0.4 NA 22.10 NA 899.995 ## 2 2.7 0.1 NA 21.35 NA 800.000 ## 3 2.9 0.6 1 21.10 0.6550 521.000 ## 4 3.0 NA NA 21.00 0.0982 14.800 ## 5 3.1 0.4 NA 20.90 0.4190 187.000 ## 6 3.3 NA NA 20.70 5.7120 6654.000
%>%Sirve para combinar funciones y poder leerlas de izquierda a derecha.
x %>% f(y) #es equivalente a f(x,y)
%>% (2)El nombre de los omnívoros que duermen más de 15 horas:
select(filter(msleep, sleep_total > 15), name)
## name ## 1 Owl monkey ## 2 Long-nosed armadillo ## 3 North American Opossum ## 4 Big brown bat ## 5 Thick-tailed opposum ## 6 Little brown bat ## 7 Tiger ## 8 Giant armadillo ## 9 Arctic ground squirrel ## 10 Golden-mantled ground squirrel ## 11 Eastern american chipmunk ## 12 Tenrec
Es equivalente a:
msleep %>% filter(sleep_total > 15) %>% select(name)
## name ## 1 Owl monkey ## 2 Long-nosed armadillo ## 3 North American Opossum ## 4 Big brown bat ## 5 Thick-tailed opposum ## 6 Little brown bat ## 7 Tiger ## 8 Giant armadillo ## 9 Arctic ground squirrel ## 10 Golden-mantled ground squirrel ## 11 Eastern american chipmunk ## 12 Tenrec
Una tarea concreta: Datos de ZZFF.
| rut | razon_social | empleados | |
|---|---|---|---|
| 20 | 213154420012 | AAAAA BBBBBBBBB | 5 |
| 21 | 215085700011 | CCCCCCCC S.A. | 2 |
| 22 | 214203290014 | DDDDDDD S.A. | 1 |
| 23 | 212152060010 | EEEEE FFFFFF S.A. | 185 |
| 24 | 1215917590016 | HHHHHH S.A. | 6 |
| 25 | 2215917590016 | HHHHHH S.A. | 1 |
Importantes:
mutate, select, filter, arrangeifelseAuxiliares:
ncharas.charactersubstrruts <- c("214203290014",
"212152060010",
"1215917590016",
"2215917590016")
Necesitamos una función que nos de el RUT y el local por separado.
¡Son vectoriales!
ruts
## [1] "214203290014" "212152060010" "1215917590016" "2215917590016"
nchar(ruts)
## [1] 12 12 13 13
substr(ruts, 1, 2)
## [1] "21" "21" "12" "22"
ifelseruts
## [1] "214203290014" "212152060010" "1215917590016" "2215917590016"
ifelse(nchar(ruts)==13, "Trece", "Distinto de Trece")
## [1] "Distinto de Trece" "Distinto de Trece" "Trece" ## [4] "Trece"
¿Cómo definirían una función que toma un vector de números y devuelve un vector de caracteres "Distinto de trece", "Trece" ?
ruts
## [1] "214203290014" "212152060010" "1215917590016" "2215917590016"
trece <- function(vector) {
ifelse(nchar(ruts)>13, "Trece", "Distinto de Trece")
}
trece(ruts)
## [1] "Distinto de Trece" "Distinto de Trece" "Distinto de Trece" ## [4] "Distinto de Trece"
Una función que recibe un vector de ruts y me da un vector con el número de local:
extrae_local <- function(ruts) {
ifelse(nchar(ruts) == 13,
substr(ruts,1,1),
1)
}
ruts
## [1] "214203290014" "212152060010" "1215917590016" "2215917590016"
extrae_local(ruts)
## [1] "1" "1" "1" "2"
Una función que recibe un vector de ruts y me da un vector con el número de rut:
extrae_rut <- function(ruts) {
ifelse(nchar(ruts) == 13,
substr(ruts,2,13),
ruts)
}
ruts
## [1] "214203290014" "212152060010" "1215917590016" "2215917590016"
extrae_rut(ruts)
## [1] "214203290014" "212152060010" "215917590016" "215917590016"
Abro los datos:
library(readr)
test <- read_csv('../data/ruts_ejemplo.csv', col_types= list(rut=col_character(), razon_social=col_character(), empleados=col_double(), ciiu=col_character()))
test
## # A tibble: 6 x 4 ## rut razon_social empleados ciiu ## <chr> <chr> <dbl> <chr> ## 1 213154420012 AAAAA BBBBBBBBB 5.00 111 ## 2 215085700011 CCCCCCCC S.A. 2.00 112 ## 3 214203290014 DDDDDDD S.A. 1.00 3311 ## 4 212152060010 EEEEE FFFFFF S.A. 185 112 ## 5 1215917590016 HHHHHH S.A. 6.00 3510 ## 6 2215917590016 HHHHHH S.A. 1.00 111
final <- test %>% mutate(rut_nuevo=extrae_rut(rut),
local=as.numeric(extrae_local(rut)))
final
## # A tibble: 6 x 6 ## rut razon_social empleados ciiu rut_nuevo local ## <chr> <chr> <dbl> <chr> <chr> <dbl> ## 1 213154420012 AAAAA BBBBBBBBB 5.00 111 213154420012 1.00 ## 2 215085700011 CCCCCCCC S.A. 2.00 112 215085700011 1.00 ## 3 214203290014 DDDDDDD S.A. 1.00 3311 214203290014 1.00 ## 4 212152060010 EEEEE FFFFFF S.A. 185 112 212152060010 1.00 ## 5 1215917590016 HHHHHH S.A. 6.00 3510 215917590016 1.00 ## 6 2215917590016 HHHHHH S.A. 1.00 111 215917590016 2.00
final <- test %>%
mutate(rut_nuevo = extrae_rut(rut),
extrae_local = extrae_local(rut)) %>%
group_by(rut_nuevo) %>%
summarize(razon_social=first(razon_social),
empleados = sum(empleados),
locales = n())
final
## # A tibble: 5 x 4 ## rut_nuevo razon_social empleados locales ## <chr> <chr> <dbl> <int> ## 1 212152060010 EEEEE FFFFFF S.A. 185 1 ## 2 213154420012 AAAAA BBBBBBBBB 5.00 1 ## 3 214203290014 DDDDDDD S.A. 1.00 1 ## 4 215085700011 CCCCCCCC S.A. 2.00 1 ## 5 215917590016 HHHHHH S.A. 7.00 2
Corrección de las exportaciones a Uruguay:
ej <- readRDS('../data/ejemplo_expors.rds')
head(ej$N2) # N1 tiene las exportaciones
## [1] 3382879166 4735149 161700000 1015457002 0 327324647
head(ej$N2_1, 20) # N2_1, N2_2, ... tiene el destino
## [1] "Brasil" "Republica Domi" "Brasil" "Venezuela" ## [5] "Seleccionar" "Paraguay" "Chile" "Seleccionar" ## [9] "Seleccionar" "Seleccionar" "Seleccionar" "Brasil" ## [13] "Seleccionar" "Venezuela" "Seleccionar" "Seleccionar" ## [17] "Seleccionar" "Mexico" "Brasil" "Seleccionar"
head(ej$NP1_2, 20) # NP1_2, NP2_2, ... tiene porcentaje a ese destino
## [1] 41 50 25 98 0 99 50 0 0 0 0 98 0 84 0 0 0 ## [18] 61 100 0
Agrego la tasa de exportaciones a Uruguay:
tasa_expor_uy <- function(N2_1, N2_2, N2_3, N2_4, N2_5, N2_6, N2_7,
N2_8, NP1_2, NP2_2, NP3_2, NP4_2, NP5_2, NP6_2,
NP7_2, NP8_2) {
case_when(
N2_1 == "Uruguay" ~ NP1_2,
N2_2 == "Uruguay" ~ NP2_2,
N2_3 == "Uruguay" ~ NP3_2,
N2_4 == "Uruguay" ~ NP4_2,
N2_5 == "Uruguay" ~ NP5_2,
N2_6 == "Uruguay" ~ NP6_2,
N2_7 == "Uruguay" ~ NP7_2,
N2_8 == "Uruguay" ~ NP8_2,
TRUE ~ 0L)
}
con_tasa <- ej %>% mutate(tasa_expor_uy = tasa_expor_uy(N2_1, N2_2,
N2_3, N2_4, N2_5, N2_6, N2_7, N2_8, NP1_2, NP2_2,
NP3_2, NP4_2, NP5_2, NP6_2, NP7_2, NP8_2),
export_corregidas=N2*(100-tasa_expor_uy)/100)
con_tasa[c(229, 695),c("N2", "export_corregidas", "tasa_expor_uy")]
## N2 export_corregidas tasa_expor_uy ## 229 76099922 71533927 6 ## 695 95398121 62008779 35
Además de usar las funciones que nos da R, podemos crear las nuestras.
sum.of.squares <- function(x,y) {
x^2 + y^2
}
sum.of.squares(3, 4)
## [1] 25
sum.of.squares(c(3, 2), c(2, 9))
## [1] 13 85
¡x e y son vectores!
Bucles - Permiten repetir una acción:
es_par <- function(num) {
if (num %% 2 == 0) print("par")
else print("impar")
}
¿Cuál es la diferencia con ifelse?
my_list <- c(2, 3, 4, 5, 6, 7, 8)
n <- length(my_list)
for(i in 1:n) {
es_par(my_list[[i]])
}
## [1] "par" ## [1] "impar" ## [1] "par" ## [1] "impar" ## [1] "par" ## [1] "impar" ## [1] "par"
my_list <- c(2, 3, 4, 5, 6, 7, 8) sapply(my_list, es_par)
## [1] "par" ## [1] "impar" ## [1] "par" ## [1] "impar" ## [1] "par" ## [1] "impar" ## [1] "par"
## [1] "par" "impar" "par" "impar" "par" "impar" "par"
Tenemos un archivo con una tabla de correspondencias entre códigos CIIUs y clasificaciones
| ciiu | clasif |
|---|---|
| 111 | Bienes |
| 112 | Comercial |
| 113 | Bienes |
| 114 | Trading |
buscar_clasificaciones <- function(vector) {
buscar_clasificacion <- function(ciiu) {
read_tsv("../data/ciius.csv", col_types = list(col_character(), col_character())) %>%
filter(CIIU==ciiu) %>%
select(Clasificacion) %>%
as.character
}
sapply(vector, buscar_clasificacion)
}
buscar_clasificaciones(c("111", "112", "3311", "3510"))
## 111 112 ## "Bienes" "Bienes" ## 3311 3510 ## "Instalacion y reparacion" "Bienes Naturales"
test$clasif <- buscar_clasificaciones(test$ciiu) test
## # A tibble: 6 x 5 ## rut razon_social empleados ciiu clasif ## <chr> <chr> <dbl> <chr> <chr> ## 1 213154420012 AAAAA BBBBBBBBB 5.00 111 Bienes ## 2 215085700011 CCCCCCCC S.A. 2.00 112 Bienes ## 3 214203290014 DDDDDDD S.A. 1.00 3311 Instalacion y reparacion ## 4 212152060010 EEEEE FFFFFF S.A. 185 112 Bienes ## 5 1215917590016 HHHHHH S.A. 6.00 3510 Bienes Naturales ## 6 2215917590016 HHHHHH S.A. 1.00 111 Bienes
Verbos para dos tablas:
left_join, right_join, full_joinsemi_join, anti_joinintersect, union, setdiffx está en los dos \(data\) \(frames\).
df1 <- data_frame(x = c(1, 2), y = 2:1) df2 <- data_frame(x = c(1, 3), a = 10, b = "a") df1
## # A tibble: 2 x 2 ## x y ## <dbl> <int> ## 1 1.00 2 ## 2 2.00 1
df2
## # A tibble: 2 x 3 ## x a b ## <dbl> <dbl> <chr> ## 1 1.00 10.0 a ## 2 3.00 10.0 a
La opción by permite elegir los campos cuando tienen distinto nombre o hay varios que coinciden.
left_joinSe queda con todas las filas del primer arg (right_join lo opuesto).
left_join(df1, df2)
## Joining, by = "x"
## # A tibble: 2 x 4 ## x y a b ## <dbl> <int> <dbl> <chr> ## 1 1.00 2 10.0 a ## 2 2.00 1 NA <NA>
Pone NA en los que no aplican y todas las columnas.
inner_joinSe queda con todas las filas que están en df1 que tienen un \(match\) en df2 y todas las columnas de df1 y df2.
inner_join(df1, df2)
## Joining, by = "x"
## # A tibble: 1 x 4 ## x y a b ## <dbl> <int> <dbl> <chr> ## 1 1.00 2 10.0 a
full_joinSe queda con todas las filas y columnas que están en los dos df.
full_join(df1, df2)
## Joining, by = "x"
## # A tibble: 3 x 4 ## x y a b ## <dbl> <int> <dbl> <chr> ## 1 1.00 2 10.0 a ## 2 2.00 1 NA <NA> ## 3 3.00 NA 10.0 a
semi_joinSe queda con todas las filas del df1 que tienen un \(match\) en df2 y las columnas de df1.
semi_join(df1, df2)
## Joining, by = "x"
## # A tibble: 1 x 2 ## x y ## <dbl> <int> ## 1 1.00 2
anti_joinSaca las filas de df1 que están en df2.
anti_join(df1, df2)
## Joining, by = "x"
## # A tibble: 1 x 2 ## x y ## <dbl> <int> ## 1 2.00 1
tabla <- read_tsv("../data/ciius.csv",
col_types = list(col_character(), col_character()))
test %>% left_join(tabla, c("ciiu"="CIIU"))
test
## # A tibble: 6 x 5 ## rut razon_social empleados ciiu clasif ## <chr> <chr> <dbl> <chr> <chr> ## 1 213154420012 AAAAA BBBBBBBBB 5.00 111 Bienes ## 2 215085700011 CCCCCCCC S.A. 2.00 112 Bienes ## 3 214203290014 DDDDDDD S.A. 1.00 3311 Instalacion y reparacion ## 4 212152060010 EEEEE FFFFFF S.A. 185 112 Bienes ## 5 1215917590016 HHHHHH S.A. 6.00 3510 Bienes Naturales ## 6 2215917590016 HHHHHH S.A. 1.00 111 Bienes
"Happy families are all alike, every unhappy family is unhappy in its own way." - Leo Tolstoy
"Tidy datasets are all alike, but every messy dataset is messy in its own way." - Hadley Wickham
library(tidyverse)
table1
## # A tibble: 6 x 4 ## country year cases population ## <chr> <int> <int> <int> ## 1 Afghanistan 1999 745 19987071 ## 2 Afghanistan 2000 2666 20595360 ## 3 Brazil 1999 37737 172006362 ## 4 Brazil 2000 80488 174504898 ## 5 China 1999 212258 1272915272 ## 6 China 2000 213766 1280428583
library(tidyverse)
table1 %>% mutate(tasa=cases/population)
## # A tibble: 6 x 5 ## country year cases population tasa ## <chr> <int> <int> <int> <dbl> ## 1 Afghanistan 1999 745 19987071 0.0000373 ## 2 Afghanistan 2000 2666 20595360 0.000129 ## 3 Brazil 1999 37737 172006362 0.000219 ## 4 Brazil 2000 80488 174504898 0.000461 ## 5 China 1999 212258 1272915272 0.000167 ## 6 China 2000 213766 1280428583 0.000167
library(tidyverse)
table1 %>% group_by(year) %>% summarize(n=sum(cases))
## # A tibble: 2 x 2 ## year n ## <int> <int> ## 1 1999 250740 ## 2 2000 296920
table2
## # A tibble: 12 x 4 ## country year type count ## <chr> <int> <chr> <int> ## 1 Afghanistan 1999 cases 745 ## 2 Afghanistan 1999 population 19987071 ## 3 Afghanistan 2000 cases 2666 ## 4 Afghanistan 2000 population 20595360 ## 5 Brazil 1999 cases 37737 ## 6 Brazil 1999 population 172006362 ## 7 Brazil 2000 cases 80488 ## 8 Brazil 2000 population 174504898 ## 9 China 1999 cases 212258 ## 10 China 1999 population 1272915272 ## 11 China 2000 cases 213766 ## 12 China 2000 population 1280428583
table3
## # A tibble: 6 x 3 ## country year rate ## * <chr> <int> <chr> ## 1 Afghanistan 1999 745/19987071 ## 2 Afghanistan 2000 2666/20595360 ## 3 Brazil 1999 37737/172006362 ## 4 Brazil 2000 80488/174504898 ## 5 China 1999 212258/1272915272 ## 6 China 2000 213766/1280428583
table4a
## # A tibble: 3 x 3 ## country `1999` `2000` ## * <chr> <int> <int> ## 1 Afghanistan 745 2666 ## 2 Brazil 37737 80488 ## 3 China 212258 213766
table4b
## # A tibble: 3 x 3 ## country `1999` `2000` ## * <chr> <int> <int> ## 1 Afghanistan 19987071 20595360 ## 2 Brazil 172006362 174504898 ## 3 China 1272915272 1280428583
Se pueden lograr los mismos resultados a partir del resto de las tablas. Pero si primero llevamos los datos a una forma "canónica", podemos usarlas funciones de dplyr.
spreadtable2
## # A tibble: 12 x 4 ## country year type count ## <chr> <int> <chr> <int> ## 1 Afghanistan 1999 cases 745 ## 2 Afghanistan 1999 population 19987071 ## 3 Afghanistan 2000 cases 2666 ## 4 Afghanistan 2000 population 20595360 ## 5 Brazil 1999 cases 37737 ## 6 Brazil 1999 population 172006362 ## 7 Brazil 2000 cases 80488 ## 8 Brazil 2000 population 174504898 ## 9 China 1999 cases 212258 ## 10 China 1999 population 1272915272 ## 11 China 2000 cases 213766 ## 12 China 2000 population 1280428583
spread(table2, key=type, value=count )
## # A tibble: 6 x 4 ## country year cases population ## * <chr> <int> <int> <int> ## 1 Afghanistan 1999 745 19987071 ## 2 Afghanistan 2000 2666 20595360 ## 3 Brazil 1999 37737 172006362 ## 4 Brazil 2000 80488 174504898 ## 5 China 1999 212258 1272915272 ## 6 China 2000 213766 1280428583
gathert4a <- gather(table4a,"1999","2000", key="year", value="cases") t4b <- gather(table4b,"1999","2000", key="year", value="population") left_join(t4a, t4b)
## Joining, by = c("country", "year")
## # A tibble: 6 x 4 ## country year cases population ## <chr> <chr> <int> <int> ## 1 Afghanistan 1999 745 19987071 ## 2 Brazil 1999 37737 172006362 ## 3 China 1999 212258 1272915272 ## 4 Afghanistan 2000 2666 20595360 ## 5 Brazil 2000 80488 174504898 ## 6 China 2000 213766 1280428583
swirllibrary(swirl)
install_course("Getting and Cleaning Data")