class: center, middle, inverse, title-slide # El uso de múltiples lenguajes en Rmarkdown ## ︿
R-Ladies Puebla ### Karina Bartolomé --- # ¿Quién soy? .pull-left[ <br> <img src="images/imagen.jpg" width="50%" style="display: block; margin: auto;" /> ] .pull-right[ ### Karina Bartolomé - Economista - Especialista en métodos cuantitativos - Data Scientist en Ualá (Fintech) ] --- background-position: 50% 50% class: center, inverse <img src="images/multilingual.png" width="500px" height="500px" style="position:center;"> # Múltiples idiomas --- background-position: 50% 50% class: center, inverse <img src="images/multilingual_code.png" width="500px" height="500px" style="position:center;"> # Múltiples lenguajes
<style type="text/css"> /* Table width = 100% max-width */ .remark-slide table{ width: 100%; } /* background-color blanco siempre */ .remark-slide thead, .remark-slide tr:nth-child(2n) { background-color: white; } /* Incremento en transparencia del color de highlight del código ya que lo uso mucho y así se lee mejor */ .remark-code-line-highlighted { background-color: rgba(136, 57, 138, 0.1); } </style> --- # ¿Qué vamos a ver hoy? -- - El uso de **`python en Rmarkdown`** -- - Similitudes / diferencias entre R y python, haciendo énfasis en `{tidyverse}`📦 y `{pandas}`📦 -- - `{reticulate}` 📦 para utilizar objetos de python en R y de R en python
--- background-position: 50% 50% class: inverse, center, middle # { espacio de memes } .pull-left[ <img src="memes/r_python.jpg" width="100%" height="100%" style="display: block; margin: auto;" /> ] .pull-right[ <img src="memes/byelingual.jpg" width="100%" height="100%" style="display: block; margin: auto;" /> ] --- class: inverse, center, middle # Antes de empezar -- ¿se puede ejecutar código R o python sin tener que instalar nada en nuestra computadora? --- # ☁️ Trabajar en la nube ☁️ Existen **recursos gratuitos**: 🔹 `RStudio Cloud`: https://rstudio.cloud/ 🔹 `Google Colab`: https://colab.research.google.com/ 🔹 `AWS Sagemaker Studio Lab`: https://studiolab.sagemaker.aws/ <br> <br> También hay **recursos pagos** si se busca mayor capacidad de cómputo o almacenamiento --- # El uso de diversos lenguajes en Rmarkdown 📝 Para trabajar con distintos lenguajes en Rmarkdown, se utilizan **`chunks`** que indiquen el lenguaje que se quiere utilizar: ```` ```{r} # Acá se escribe código R ``` ```` ```` ```{python} # Acá se escribe código Python ``` ```` ```` ```{julia} # Acá se escribe código Julia ``` ```` ```` ```{sql} # Acá se escribe sql ``` ```` Etc. --- # R en Rmarkdown 🔹 En **Rmarkdown**, se utiliza un `chunk R` para cargar los paquetes R 📦 ```r library(reticulate) # python library(tidyverse) # manipulación de datos library(gt) # tablas ``` --- # Python en Rmarkdown 🔹 Definir un `conda environment` a utilizar: ```r reticulate::conda_create(envname='rladies', python_version="3.8.8") ``` ------------------------------------- 🔹 Desde la terminal, ejecutar los siguientes comandos: .panelset[ .panel[.panel-name[conda env list] Se visualizan los environments con `conda env list` ] .panel[.panel-name[conda activate] Se activa con: `conda activate rladies` ] .panel[.panel-name[conda remove] Si se quiere remover el environment, primero es necesario activar el environment base, y luego se remueve el environment creado: - Se activa el environment base: `conda activate` - Se remueve el environment: `conda remove --name rladies --all` ] ] --- class: inverse, center, middle # {cómo se ve lo anterior desde RStudio} 👉 [🔗 Archivo .Rmd para ejecutar python en rmarkdown desde un conda environment](https://github.com/karbartolome/rladies_charlas/blob/main/01_r_python/03_condaenvs/03_conda_envs.md) --- # Python en Rmarkdown 🔹 Se instalan los paquetes 📦 a utilizar. En este caso, lo hice desde la terminal, teniendo activado el environment: - [x] ➕ numpy: conda install -c conda-forge numpy - [x] 🐼 pandas: conda install -c conda-forge pandas - [x] 📊 seaborn: conda install -c conda-forge seaborn - [x] 🔬 statsmodels: conda install -c conda-forge statsmodels También es posible realizar la instalación de paquetes con la función `conda_install` de {reticulate} 📦 , aunque yo siempre lo hice desde la terminal. --- 🔹Se define que el environment a utilizar es el que ha sido creado: ```r reticulate::use_condaenv(condaenv = 'rladies', required = TRUE) ``` <img src="images/its_happening.gif" width="45%" style="display: block; margin: auto;" /> 🔹Se utiliza un `chunk python` para cargar los paquetes `python` 📦: ```python import pandas as pd # manipulación de datos import numpy as np # manipulación de datos import matplotlib.pyplot as plt # visualización import seaborn as sns # visualización ``` --- # 📝 Diferentes objetos: | R | Python | Examples | |:-----------------------|:------------------|:-------------------------------------------------| | Single-element vector | Scalar | `1`, `1L`, `TRUE`, `"foo"` | | Multi-element vector | List | `c(1.0, 2.0, 3.0)`, `c(1L, 2L, 3L)` | | List of multiple types | Tuple | `list(1L, TRUE, "foo")` | | Named list | Dict | `list(a = 1L, b = 2.0)`, `dict(x = x_data)` | | Matrix/Array | NumPy ndarray | `matrix(c(1,2,3,4), nrow = 2, ncol = 2)` | | Data Frame | Pandas DataFrame | `data.frame(x = c(1,2), y = c("a", "b"))` | | Function | Python function | `function(x) x + 1` | | NULL, TRUE, FALSE | None, True, False | `NULL`, `TRUE`, `FALSE` | --- class: inverse, center, middle # 0. Datos Se utilizarán datos del comercio bilateral entre Argentina y México <img src="images/arg_mx.jpg" width="50%" /> --- # Aclaraciones 🔹 Los datos provienen del paquete 🔗 [{opentradestatistics}](https://docs.ropensci.org/tradestatistics/index.html). 🔹 Los ejemplos pueden no tener sentido real (agrupaciones de ramas de actividades que podrían no tener relación, etc.). 🔹 El objetivo es utilizar datos reales para mostrar diferentes funcionalidades, **no el análisis de los datos en sí**. --- # Lectura de datos con R Se realiza la **lectura de 3 dataframes** 📂. Los dataframes de secciones y commodities contienen las descripciones de los ids que aparecen en el dataframe de expo / impo. ```r df_comercio <- readr::read_csv('data/df_arg_mx.csv') df_secciones <- readr::read_csv('data/df_secciones.csv') df_commodities <- readr::read_csv('data/df_commodities.csv') ``` # Lectura de datos con python ```python df_comercio_pd = pd.read_csv('data/df_arg_mx.csv') ``` --- Se observan las primeras 2 observaciones: ```r df_comercio %>% head(2) ``` ``` # A tibble: 2 x 7 year reporter partner commodity_code section_code trade_value_usd_exp <dbl> <chr> <chr> <chr> <chr> <dbl> 1 2017 Argentina Mexico 010121 01 15000 2 2019 Argentina Mexico 010121 01 0 # ... with 1 more variable: trade_value_usd_imp <dbl> ``` ⚡ Objetos cross lenguaje **R -> Python** ⚡ ```python r.df_comercio.head(2) ``` ``` year reporter partner commodity_code section_code trade_value_usd_exp \ 0 2017.00 Argentina Mexico 010121 01 15000.00 1 2019.00 Argentina Mexico 010121 01 0.00 trade_value_usd_imp 0 0.00 1 37091.00 ``` --- Se crea una lista de variables relevantes en un chunk python: ```python variables = ['year','commodity_code','trade_value_usd_exp'] ``` ------------------------------------------- 🔹 Dos chunks que generan el mismo output: .panelset[ .panel[.panel-name[R con objeto Python ] ```` ```{r} py$df_comercio_pd %>% select(all_of(py$variables)) %>% head(2) ``` ```` ``` year commodity_code trade_value_usd_exp 1 2017 10121 15000 2 2019 10121 0 ``` ] .panel[.panel-name[Python con objeto R] ```` ```{python} (r.df_comercio .filter(variables) .head(2)) ``` ```` ``` year commodity_code trade_value_usd_exp 0 2017.00 010121 15000.00 1 2019.00 010121 0.00 ``` ] ] --- class: inverse, center, middle # 1. Estadística descriptiva <img src="images/numbers.gif" width="45%" style="display: block; margin: auto;" /> --- .panelset[ .panel[.panel-name[R summary] ```r df_comercio %>% summary() ``` ``` year reporter partner commodity_code Min. :2017 Length:5687 Length:5687 Length:5687 1st Qu.:2017 Class :character Class :character Class :character Median :2018 Mode :character Mode :character Mode :character Mean :2018 3rd Qu.:2019 Max. :2020 section_code trade_value_usd_exp trade_value_usd_imp Length:5687 Min. : 0 Min. : 0 Class :character 1st Qu.: 0 1st Qu.: 1892 Mode :character Median : 0 Median : 25909 Mean : 437500 Mean : 1060187 3rd Qu.: 5392 3rd Qu.: 239566 Max. :342756705 Max. :450264324 ``` ] .panel[.panel-name[Python .describe()] Variables que no son object: ```python r.df_comercio.describe(exclude='object') ``` ``` year trade_value_usd_exp trade_value_usd_imp count 5687.00 5687.00 5687.00 mean 2018.38 437500.39 1060187.19 std 1.13 6709261.81 9271817.03 min 2017.00 0.00 0.00 25% 2017.00 0.00 1892.00 50% 2018.00 0.00 25909.00 75% 2019.00 5392.00 239566.00 max 2020.00 342756705.00 450264324.00 ``` Variables tipo object: ```python r.df_comercio.describe(include='object') ``` ``` reporter partner commodity_code section_code count 5687 5687 5687 5687 unique 1 1 2032 22 top Argentina Mexico 999999 16 freq 5687 5687 4 1401 ``` ] .panel[.panel-name[R skim(df)] ```r py$df_comercio_pd %>% select(where(is.numeric)) %>% * skimr::skim() %>% select(-skim_type, -complete_rate) %>% gt() %>% tab_header(title=md('**Comercio exterior**: Argentina y México'), subtitle='Estadística descriptiva') %>% opt_align_table_header('left') %>% fmt_number(columns=3:4) ```
Comercio exterior
: Argentina y México
Estadística descriptiva
skim_variable
n_missing
numeric.mean
numeric.sd
numeric.p0
numeric.p25
numeric.p50
numeric.p75
numeric.p100
numeric.hist
year
0
2,018.38
1.13
2017
2017.0
2018
2019
2020
▇▆▁▆▆
commodity_code
0
617,540.05
256,685.16
10121
381105.5
720230
848280
999999
▁▆▁▃▇
section_code
4
11.86
5.04
1
6.0
15
16
21
▂▆▃▇▂
trade_value_usd_exp
0
437,500.39
6,709,261.81
0
0.0
0
5392
342756705
▇▁▁▁▁
trade_value_usd_imp
0
1,060,187.19
9,271,817.03
0
1892.0
25909
239566
450264324
▇▁▁▁▁
] ] --- class: inverse, center, middle # 2. Unión de dataframes <img src="images/union.gif" width="50%" /> --- .panelset[ .panel[.panel-name[R] ```r df <- df_comercio %>% * # Left join con datos de commodities * left_join(df_commodities %>% * select(commodity_code, * commodity_fullname_english, * group_fullname_english), * by='commodity_code') %>% * * # Left join con secciones * left_join(df_secciones) %>% # Selección de variables y renombrarlas select( año = year, pais = reporter, socio = partner, commodity = commodity_fullname_english, grupo = group_fullname_english, seccion = section_shortname_english, expo = trade_value_usd_exp, impo = trade_value_usd_imp ) ``` ``` Joining, by = "section_code" ``` ] .panel[.panel-name[Python] ```python df_py = (r.df_comercio * # Left join con datos de commodities * .merge(r.df_commodities[['commodity_code', * 'commodity_fullname_english', * 'group_fullname_english']], * on='commodity_code', how='left') * * # Left join con secciones * .merge(r.df_secciones, on='section_code', how='left') # Renombrar variables .rename({ 'year' : 'año', 'reporter' : 'pais', 'partner' : 'socio', 'commodity_fullname_english' : 'commodity', 'group_fullname_english' : 'grupo', 'section_shortname_english' : 'seccion', 'trade_value_usd_exp' : 'expo', 'trade_value_usd_imp' : 'impo' }, axis=1) # Selección de las columnas relevantes (mismas que df anterior en r) [r.df.columns] ) ``` ] .panel[.panel-name[Dataframes generados] 🔹 R dataframe: ```r df %>% head(1) %>% gt::gt() ```
año
pais
socio
commodity
grupo
seccion
expo
impo
2017
Argentina
Mexico
Horses; live, pure-bred breeding animals
Animals; live
Animal Products
15000
0
🔹 Pandas dataframe: ```r py$df_py %>% head(1) %>% gt::gt() ```
año
pais
socio
commodity
grupo
seccion
expo
impo
2017
Argentina
Mexico
Horses; live, pure-bred breeding animals
Animals; live
Animal Products
15000
0
] .panel[.panel-name[Comparación] Se utiliza el paquete waldo para comparar los filtros generados: ```r waldo::compare(data.frame(df), data.frame(py$df_py)) ``` ``` v No differences ``` <img src="images/party1.gif" width="30%" style="display: block; margin: auto;" /> ] .panel[.panel-name[Waldo] Cómo funciona el paquete {waldo}? (lo vamos a usar mucho). Se cuenta con un df_a y un df_b y se quiere verificar si son iguales: ```r df_a <- data.frame(var1=c(1,2), var2=c(2,3)) df_a ``` ``` var1 var2 1 1 2 2 2 3 ``` ```r df_b <- data.frame(var1=c('1','2'), var2=c(3,4)) df_b ``` ``` var1 var2 1 1 3 2 2 4 ``` Waldo muestra las diferencias: ```r waldo::compare(df_a, df_b) ``` ``` `old$var1` is a double vector (1, 2) `new$var1` is a character vector ('1', '2') `old$var2`: 2 3 `new$var2`: 3 4 ``` ] ] --- class: inverse, center, middle # 3. Filtros ![](images/filter.gif)<!-- --> --- .panelset[ .panel[.panel-name[R] ```r filtro_r <- df %>% * filter( * * # Condición simple (equivalencia) * año == 2019 & * * # Condición OR con función quantile() * (expo > quantile(df$expo,0.6) | * impo > quantile(df$impo,0.6) ) & * * # Filtro por expresión regular * str_detect(tolower(commodity), 'metal') ) ``` ] .panel[.panel-name[Python] ```python filtro_py = (r.df .query(""" año == 2019 and \ \ (expo > expo.quantile(0.6) or \ impo > impo.quantile(0.6)) and \ \ commodity.str.lower().str.contains('metal') """, engine='python') .reset_index(drop=True) ) ``` ] .panel[.panel-name[Dataframes generados] 🔹 R dataframe: ```r filtro_r %>% head(1) %>% gt::gt() ```
año
pais
socio
commodity
grupo
seccion
expo
impo
2019
Argentina
Mexico
Alkali or alkali-earth metals; calcium
Inorganic chemicals; organic and inorganic compounds of precious metals; of rare earth metals, of radio-active elements and of isotopes
Chemical Products
0
105154
🔹 Pandas dataframe: ```r py$filtro_py %>% head(1) %>% gt::gt() ```
año
pais
socio
commodity
grupo
seccion
expo
impo
2019
Argentina
Mexico
Alkali or alkali-earth metals; calcium
Inorganic chemicals; organic and inorganic compounds of precious metals; of rare earth metals, of radio-active elements and of isotopes
Chemical Products
0
105154
] .panel[.panel-name[Comparación] Se utiliza el paquete waldo para comparar los filtros generados: ```r waldo::compare(data.frame(filtro_r), data.frame(py$filtro_py)) ``` ``` v No differences ``` <img src="images/party2.gif" width="30%" style="display: block; margin: auto;" /> ] ] --- class: inverse, center, middle # 3. Nuevas columnas <img src="images/more.gif" width="50%" /> --- .panelset[ .panel[.panel-name[R] ```r columnas_r <- df %>% mutate( # Cálculo * expo_netas = expo - impo, * * # If else * d_2020 = ifelse(año==2020,1,0), * * # Case when * categoria_extra = case_when( * * str_detect(commodity,'metal|machines') ~ 'Metal & maquinarias', * str_detect(commodity,'animal|food|vegetable') ~ 'Cultivos y animales', * TRUE ~ 'Otros' ) ) ``` ] .panel[.panel-name[Python] ```python columnas_py = (r.df .assign( * # Cálculo * expo_netas = lambda x: x['expo'] - x['impo'], * * # If else * d_2020 = lambda x: np.where(x['año']==2020,1,0), * * # Case when * categoria_extra = lambda x: np.select( * * [x['commodity'].str.contains('metal|machines'), * x['commodity'].str.contains('animal|food|vegetable')], * * ['Metal & maquinarias', * 'Cultivos y animales'], * * default = 'Otros') ) ) ``` ] .panel[.panel-name[Dataframes generados] 🔹 R dataframe: ```r columnas_r %>% head(1) %>% gt::gt() ```
año
pais
socio
commodity
grupo
seccion
expo
impo
expo_netas
d_2020
categoria_extra
2017
Argentina
Mexico
Horses; live, pure-bred breeding animals
Animals; live
Animal Products
15000
0
15000
0
Cultivos y animales
🔹 Pandas dataframe: ```r py$columnas_py %>% head(1) %>% gt::gt() ```
año
pais
socio
commodity
grupo
seccion
expo
impo
expo_netas
d_2020
categoria_extra
2017
Argentina
Mexico
Horses; live, pure-bred breeding animals
Animals; live
Animal Products
15000
0
15000
0
Cultivos y animales
] .panel[.panel-name[Comparación] ```r waldo::compare(data.frame(columnas_r), data.frame(py$columnas_py)) ``` ``` v No differences ``` <img src="images/party3.gif" width="30%" style="display: block; margin: auto;" /> ] ] --- class: inverse, center, middle # 5. Agregación / Group by <img src="images/group.gif" width="45%" style="display: block; margin: auto;" /> --- .panelset[ .panel[.panel-name[R] ```r agg_r <- df %>% * group_by(seccion) %>% * * summarise( * expo_total = sum(expo), * impo_total = sum(impo), * expo_prom = mean(expo), * impo_prom = mean(impo), * ) %>% * * ungroup() ``` ] .panel[.panel-name[Python] ```python agg_py = (df_py * .groupby('seccion', as_index=False) * * .agg( * expo_total = ('expo','sum' ), * impo_total = ('impo','sum' ), * expo_prom = ('expo','mean'), * impo_prom = ('impo','mean') * ) ) ``` ] .panel[.panel-name[Dataframes generados] 🔹 R dataframe: ```r agg_r %>% head(2) %>% gt::gt() ```
seccion
expo_total
impo_total
expo_prom
impo_prom
Unspecified
769921184
48065
192480296
12016.25
Transportation
397349013
1883795611
2631450
12475467.62
🔹 Pandas dataframe: ```r py$agg_py %>% head(2) %>% gt::gt() ```
seccion
expo_total
impo_total
expo_prom
impo_prom
Unspecified
769921184
48065
192480296
12016.25
Transportation
397349013
1883795611
2631450
12475467.62
] .panel[.panel-name[Comparación] ```r waldo::compare(data.frame(agg_r), data.frame(py$agg_py)) ``` ``` v No differences ``` <img src="images/party4.gif" width="30%" style="display: block; margin: auto;" /> ] ] --- class: inverse, center, middle # 6. Formato wide a long / long a wide (pivot) <img src="images/changes.gif" width="50%" /> --- Las transformaciones del formato de los datos permiten visualizar la misma información de diferentes formas: <img src="images/pivot.png" width="70%" /> --- # Pivot wider .panelset[ .panel[.panel-name[R] ```r wider_r <- df %>% group_by(seccion, año) %>% summarise(expo = sum(expo), .groups = 'keep') %>% ungroup() %>% * pivot_wider(names_from=año, * names_prefix='y_', * values_from=expo) ``` ] .panel[.panel-name[Python] ```python wider_py = (r.df .assign(año=lambda x: ['y_'+str(int(i)) for i in x['año']]) .groupby(['seccion','año'], as_index=False) .agg(expo = ('expo','sum')) *.pivot(index='seccion', * columns='año', * values='expo') ) ``` ] .panel[.panel-name[Dataframes generados] 🔹 R dataframe: ```r wider_r %>% head(2) %>% gt::gt() ```
seccion
y_2017
y_2018
y_2019
y_2020
Unspecified
96332
225954813
342756705
201113334
Chemical Products
114416816
73527737
65993570
65111224
🔹 Pandas dataframe: ```r py$wider_py %>% head(2) %>% gt::gt() ```
seccion
y_2017
y_2018
y_2019
y_2020
Unspecified
96332
225954813
342756705
201113334
Chemical Products
114416816
73527737
65993570
65111224
] .panel[.panel-name[Comparación] ```r waldo::compare(data.frame(wider_r), data.frame(py$wider_py)) ``` ``` v No differences ``` <img src="images/party5.gif" width="30%" style="display: block; margin: auto;" /> ] ] --- # Pivot longer .panelset[ .panel[.panel-name[R] ```r longer_r <- wider_r %>% * pivot_longer(-seccion, * names_to='año', * values_to='expo') %>% mutate(año=str_replace(año, 'y_','')) ``` ] .panel[.panel-name[Python] ```python longer_py = (wider_py * .melt( * id_vars='seccion', * value_vars=['y_2017','y_2018','y_2019','y_2020'], * value_name='expo' * ) .assign(año = lambda x: [i.replace('y_','') for i in x['año']]) ) ``` ] .panel[.panel-name[Dataframes generados] 🔹 R dataframe: ```r longer_r %>% head(2) %>% gt::gt() ```
seccion
año
expo
Animal and Vegetable Bi-Products
2017
17689911
Animal and Vegetable Bi-Products
2018
90227077
🔹 Pandas dataframe: ```r py$longer_py %>% head(2) %>% gt::gt() ```
seccion
año
expo
Animal and Vegetable Bi-Products
2017
17689911
Animal and Vegetable Bi-Products
2018
90227077
] .panel[.panel-name[Comparación] ```r waldo::compare(data.frame(longer_r), data.frame(py$longer_py)) ``` ``` v No differences ``` <img src="images/party6.gif" width="30%" style="display: block; margin: auto;" /> ] ] --- class: inverse, center, middle # 7. Visualización ![](images/viz.gif)<!-- --> --- Se definen las **secciones relevantes**: Top 5️⃣ según monto de exportaciones: ```r secciones_relevantes <- longer_r %>% group_by(seccion) %>% summarise(expo_4y=sum(expo)) %>% ungroup() %>% arrange(desc(expo_4y)) %>% * top_n(5) %>% pull(seccion) ``` ``` Selecting by expo_4y ``` --- .panelset[ .panel[.panel-name[R] ```r longer_r %>% filter(seccion %in% secciones_relevantes) %>% * ggplot(aes(x=expo, y=reorder(seccion, expo)))+ * geom_boxplot()+ scale_x_continuous(labels = scales::unit_format(unit = "M", scale = 1e-6))+ labs(title='Variación en las principales exportaciones entre 2017 y 2020', x='Exportaciones (USD)', y='Sección') + theme_bw() ``` ![](rladies_r_python_files/figure-html/unnamed-chunk-73-1.png)<!-- --> ] .panel[.panel-name[Python] ```python plt.figure(figsize=(13,4)) ``` ```{=html} (longer_py[longer_py['seccion'].isin(r.secciones_relevantes)] * .pipe((sns.boxplot,"data"), * x="expo", y="seccion", order=orden, color='white') .set(xlabel = "Exportaciones (USD)", ylabel='Sección', title = 'Variación en las principales exportaciones entre 2017 y 2020') ) plt.show() ``` <img src="rladies_r_python_files/figure-html/Librerías python-1.png" width="100%" height="60%" style="display: block; margin: auto;" /> ] ] --- class: inverse, center, middle # 8. Modelos <img src="images/yeah_science.gif" width="50%" /> --- Se utiliza el paquete `{AER}` 📦 (Applied Econometric with R), que contiene un gran número de datasets econométricos. En este caso, los datos contienen información sobre resultados educativos,Stock & Watson (2007) `\(^1\)`. Incluyen características sociodemográficas de estudiantes y escuelas en distritos de California. <div style="position: absolute;left:60px;bottom:11px;color:gray;font-size:10px"> `\(^1\)` Stock JH, Watson MW (2007). Introduction to Econometrics. 2nd edition. Addison-Wesley, Reading, MA. </div> ```r library(AER) #data(package='AER') # Lista los datasets disponibles en el paquete AER ``` Se cargan los datos, generando una variable adicional de tamaño de la clase: ```r data("CASchools") CASchools <- CASchools %>% * mutate(tamaño = (students/teachers)) ```
Tamaño de clase y desempeño en matemática
Distribución de las variables relevantes
Variable
Prom
SD
Min
p25
Mediana
Max
Distribución
N faltantes
math
653.34
18.75
605.40
639.38
652.45
709.50
▁▆▇▃▁
0
tamaño
19.64
1.89
14.00
18.58
19.72
25.80
▁▃▇▃▁
0
--- Se busca estimar el coeficiente asociado al tamaño de la clase, definido como la cantidad de estudiantes por la cantidad de profesores. ```r reg_lineal <- lm(formula = math ~ tamaño, data = CASchools) ``` Con {equatiomatic} se visualiza la ecuación del modelo: ```r equatiomatic::extract_eq(reg_lineal) ``` $$ \operatorname{math} = {\color{black}{\alpha}} + {\color{#e490e8}{\beta}}_{{\color{#e490e8}{1}}}(\operatorname{tamaño}) + {\color{black}{\epsilon}} $$ También es posible visualizar la regresión lineal estimada (con los coeficientes correspondientes): ```r equatiomatic::extract_eq(reg_lineal, use_coefs=TRUE) ``` $$ \operatorname{\widehat{math}} = 691.42 - 1.94(\operatorname{tamaño}) $$ El error de estimación es la diferencia entre el valor observado y el valor predicho: $$ \operatorname{math} - \operatorname{\widehat{math}} = \epsilon $$ --- # Visualmente: .panelset[ .panel[.panel-name[Modelo] ![](rladies_r_python_files/figure-html/plot_reg-1.png)<!-- --> ] .panel[.panel-name[Predicción] ![](rladies_r_python_files/figure-html/plot_reg_pred-1.png)<!-- --> ] ] --- ```python import statsmodels.formula.api as smf *reg = smf.ols ("math ~ tamaño", r.CASchools).fit() modelo = reg.summary2() ``` .panelset[ .panel[.panel-name[Tabla 1] ```python modelo.tables[0] ``` ``` 0 1 2 3 0 Model: OLS Adj. R-squared: 0.036 1 Dependent Variable: math AIC: 3640.9217 2 Date: 2022-04-30 12:05 BIC: 3649.0022 3 No. Observations: 420 Log-Likelihood: -1818.5 4 Df Model: 1 F-statistic: 16.62 5 Df Residuals: 418 Prob (F-statistic): 5.47e-05 6 R-squared: 0.038 Scale: 339.08 ``` ] .panel[.panel-name[Tabla 2] ```python modelo.tables[1] ``` ``` Coef. Std.Err. t P>|t| [0.025 0.975] Intercept 691.42 9.38 73.69 0.00 672.97 709.86 tamaño -1.94 0.48 -4.08 0.00 -2.87 -1.00 ``` ] .panel[.panel-name[Tabla 3] ```python modelo.tables[2] ``` ``` 0 1 2 3 0 Omnibus: 5.043 Durbin-Watson: 0.216 1 Prob(Omnibus): 0.080 Jarque-Bera (JB): 4.199 2 Skew: 0.155 Prob(JB): 0.123 3 Kurtosis: 2.620 Condition No.: 207 ``` ] ] --- Comparando los `coeficientes` ajustando el modelo de regresión lineal con python o R: .panelset[ .panel[.panel-name[Regresión en Python] ```r py$modelo$tables[[2]] %>% tibble::rownames_to_column('Variable') %>% gt() %>% fmt_number(where(is.numeric), decimals = 3) %>% tab_header(title=md('**Tabla:** Modelo OLS'), subtitle = 'Statsmodels (python) a R') %>% opt_align_table_header('left') ```
Tabla:
Modelo OLS
Statsmodels (python) a R
Variable
Coef.
Std.Err.
t
P>|t|
[0.025
0.975]
Intercept
691.417
9.382
73.692
0.000
672.975
709.860
tamaño
−1.939
0.476
−4.077
0.000
−2.873
−1.004
] .panel[.panel-name[Regresión en R] ```r *lm(formula = math ~ tamaño, data = CASchools) %>% gtsummary::tbl_regression(intercept=TRUE) %>% gtsummary::modify_header(statistic="**Statistic**", std.error="**SE**") %>% gtsummary::as_gt() %>% tab_header(title=md('**Tabla:** Modelo OLS'), subtitle='R Base') %>% opt_align_table_header('left') ```
Tabla:
Modelo OLS
R Base
Característica
Beta
SE
1
Statistic
95% CI
1
p-valor
(Intercept)
691
9.38
73.7
673, 710
<0.001
tamaño
-1.9
0.476
-4.08
-2.9, -1.0
<0.001
1
SE = Standard Error, CI = Intervalo de confianza
] .panel[.panel-name[Comparación] 🔹 Modelo python:
Tabla:
Modelo OLS
Statsmodels (python) a R
Variable
Coef.
Std.Err.
t
P>|t|
[0.025
0.975]
Intercept
691.417
9.382
73.692
0.000
672.975
709.860
tamaño
−1.939
0.476
−4.077
0.000
−2.873
−1.004
🔹 Modelo R:
Tabla:
Modelo OLS
R Base
Característica
Beta
SE
1
Statistic
95% CI
1
p-valor
(Intercept)
691
9.38
73.7
673, 710
<0.001
tamaño
-1.9
0.476
-4.08
-2.9, -1.0
<0.001
1
SE = Standard Error, CI = Intervalo de confianza
] ] --- class: inverse, center, middle # {Algunas cosas adicionales} [1. 🔗 {rpy2}: paquete para ejecutar código R en python, notebook en Google Colab](https://colab.research.google.com/drive/11mIPeZQ_cDyECoR-57KUunDb_1av3NXJ#scrollTo=EiWnfQ7k0zad) [2. 🔗 Renderizar Rmarkdowns parametrizados que incluyen código R y python](https://github.com/karbartolome/rladies_charlas/blob/main/01_r_python/05_rmarkdown_param/05_r_python_parametrizado.md) --- class: center, middle # Comentarios finales --- # Cosas que quiero que se lleven de este workshop -- - R y python pueden ser complementarios, se puede usar lo mejor de ambos mundos 💜 <img src="images/hm.gif" width="30%" style="display: block; margin: auto;" /> -- - Tidyverse y pandas son bastante similares (: -- - **El lenguaje utilizado no es un fin en sí mismo**, sino que es un medio para resolver algo -- - 👉 Algunas configuraciones que mostré en segundos me llevaron tiempo de googlear y stackoverflow. Si quieren trabajar con conda environments en Rstudio de manera local no se frustren si no sale tan rápido --- # Links utiles - 🔗 [TidyPandas: post que escribì con Rafael Zambrano detallando algunas similitudes entre tidyverse y pandas](https://karbartolome-blog.netlify.app/posts/tidypandas/) <img src="https://karbartolome-blog.netlify.app/posts/tidypandas/preview2.png" width="30%" style="display: block; margin: auto;" /> - 🔗 [Guía de conversión entre R y python para manipulación de datos](https://www.mit.edu/~amidi/teaching/data-science-tools/conversion-guide/r-python-data-manipulation/) - 🔗 [R & python: a love story](https://www.rstudio.com/resources/webinars/r-python-a-data-science-love-story/) - 🔗 [Hilo de twitter sobre R y Python](https://twitter.com/AmeliaMN/status/1507484430113378307) - [Otro link (:](https://www.youtube.com/watch?v=dQw4w9WgXcQ) --- class: inverse, center, middle # Contacto <a href="https://karbartolome-blog.netlify.com"><i class="fa fa-link fa-fw"></i> karbartolome-blog.netlify.com</a><br> <a href="http://twitter.com/karbartolome"><i class="fa fa-twitter fa-fw"></i> @karbartolome</a><br> <a href="http://github.com/karbartolome"><i class="fa fa-github fa-fw"></i> @karbartolome</a><br> --- class: center, middle # Muchas gracias!! Las slides fueron creadas con el paquete [**xaringan**](https://github.com/yihui/xaringan), utilizando el template de Rladies