Coercionar datos

Para poder realizar operaciones con diferentes variables, es importante conocer el tipo de dato de cada variable, puesto que no todos los tipos de dato son compatibles para realizar una operaición. En la clase previa, obervaciones como la cunfión class() nos ayuda a conocer el tipo variable, por ejemplo:

v1<-array(c(1,2,3,4,4,5,6))
class(v1)
## [1] "array"
v1
## [1] 1 2 3 4 4 5 6


Sin embargo, en ocasiones tendremos que modificar la naturaleza de alguna variable para poder ser compatible con otra y entonces por llevar a cabo alguna operación. Esre proceso se conoce como coercionar, que es transformar un tipo de variable a otro que sea de nuestra utilidad, compatible con nuestras operaciones.

v2 <- as.data.frame(v1)
class(v2)
## [1] "data.frame"
v2
##   v1
## 1  1
## 2  2
## 3  3
## 4  4
## 5  4
## 6  5
## 7  6

En este curso utilizaremos principalmente las siguientes:

#as.matrix()
#as.data.frame()
#as.list()
#as.vector()
#as.Date()

Extraccion y modificación de datos desde un archivo excel

En la sesión previa, se demostró como llevar información de un archivo con extensión .csv a una variable, de manera similar es posible extraer información de una archivo en formato de Excel, a una variable en R, sin embargo hay que instalar una librería adicional para este propósito

library(readxl) 
alfa <- read_xlsx('Alfa.xlsx')
str(alfa)
## tibble [373 × 8] (S3: tbl_df/tbl/data.frame)
##  $ Fecha            : chr [1:373] "2020-01-02" "2020-01-03" "2020-01-06" "2020-01-07" ...
##  $ ALFAA.MX.Open    : num [1:373] 15.8 16.2 16.3 16.6 16.1 ...
##  $ ALFAA.MX.High    : num [1:373] 16.3 16.4 16.6 16.6 16.5 ...
##  $ ALFAA.MX.Low     : num [1:373] 15.8 16.1 16.3 16 16 ...
##  $ ALFAA.MX.Close   : num [1:373] 16.2 16.4 16.5 16.1 16.4 ...
##  $ ALFAA.MX.Volume  : num [1:373] 3605877 4177223 2999994 3496828 4687691 ...
##  $ ALFAA.MX.Adjusted: num [1:373] 16.1 16.3 16.5 16.1 16.4 ...
##  $ Dia              : chr [1:373] "Lunes" "Martes" "Miercoles" "Jueves" ...
summary(alfa)
##     Fecha           ALFAA.MX.Open   ALFAA.MX.High    ALFAA.MX.Low  
##  Length:373         Min.   : 6.30   Min.   : 6.74   Min.   : 6.12  
##  Class :character   1st Qu.:12.01   1st Qu.:12.22   1st Qu.:11.80  
##  Mode  :character   Median :13.50   Median :13.75   Median :13.20  
##                     Mean   :13.07   Mean   :13.32   Mean   :12.79  
##                     3rd Qu.:14.36   3rd Qu.:14.62   3rd Qu.:14.11  
##                     Max.   :17.10   Max.   :17.49   Max.   :16.74  
##                                                                    
##  ALFAA.MX.Close  ALFAA.MX.Volume     ALFAA.MX.Adjusted     Dia           
##  Min.   : 6.40   Min.   :   348799   Min.   : 6.387    Length:373        
##  1st Qu.:12.03   1st Qu.:  5026148   1st Qu.:12.010    Class :character  
##  Median :13.47   Median :  7751798   Median :13.442    Mode  :character  
##  Mean   :13.06   Mean   : 11286706   Mean   :13.033                      
##  3rd Qu.:14.34   3rd Qu.: 11154689   3rd Qu.:14.336                      
##  Max.   :16.99   Max.   :538464233   Max.   :16.955                      
##  NA's   :3


Antes de continuar...

#Con estas líneas cambiamos el nombre de las columnas (variables) del Data Frame
colnames(alfa) <- gsub('ALFAA.MX.', '', colnames(alfa))
summary(alfa)
##     Fecha                Open            High            Low       
##  Length:373         Min.   : 6.30   Min.   : 6.74   Min.   : 6.12  
##  Class :character   1st Qu.:12.01   1st Qu.:12.22   1st Qu.:11.80  
##  Mode  :character   Median :13.50   Median :13.75   Median :13.20  
##                     Mean   :13.07   Mean   :13.32   Mean   :12.79  
##                     3rd Qu.:14.36   3rd Qu.:14.62   3rd Qu.:14.11  
##                     Max.   :17.10   Max.   :17.49   Max.   :16.74  
##                                                                    
##      Close           Volume             Adjusted          Dia           
##  Min.   : 6.40   Min.   :   348799   Min.   : 6.387   Length:373        
##  1st Qu.:12.03   1st Qu.:  5026148   1st Qu.:12.010   Class :character  
##  Median :13.47   Median :  7751798   Median :13.442   Mode  :character  
##  Mean   :13.06   Mean   : 11286706   Mean   :13.033                     
##  3rd Qu.:14.34   3rd Qu.: 11154689   3rd Qu.:14.336                     
##  Max.   :16.99   Max.   :538464233   Max.   :16.955                     
##  NA's   :3
fecha_texto <- "09-09-2021"
class(fecha_texto)
## [1] "character"
fecha_date <- as.Date(fecha_texto)
class(fecha_date)
## [1] "Date"


Preguntamos el año de la variable fecha_date

# Cargamospreviamente la librería lubridate para analizar las fechas
library('lubridate')
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
year(fecha_date)
## [1] 9


La variable fecha_date regresa un año un poco extraño

fecha_date
## [1] "0009-09-20"


El error deriva del formato de nuestra fecha original dd/mm/yyyy, cuando as.Date lo lee por defacult como yyyy/mm/dd. Por lo tanto hay que parametrizar la transformación de la variable

fecha_date <- as.Date(fecha_texto, format='%d-%m-%Y')
class(fecha_date)
## [1] "Date"
year(fecha_date)
## [1] 2021
fecha_date
## [1] "2021-09-09"

El formato de la variable fecha_date ya es el correcto

alfa$Fecha <- as.Date(alfa$Fecha, format='%Y-%m-%d')
str(alfa)
## tibble [373 × 8] (S3: tbl_df/tbl/data.frame)
##  $ Fecha   : Date[1:373], format: "2020-01-02" "2020-01-03" ...
##  $ Open    : num [1:373] 15.8 16.2 16.3 16.6 16.1 ...
##  $ High    : num [1:373] 16.3 16.4 16.6 16.6 16.5 ...
##  $ Low     : num [1:373] 15.8 16.1 16.3 16 16 ...
##  $ Close   : num [1:373] 16.2 16.4 16.5 16.1 16.4 ...
##  $ Volume  : num [1:373] 3605877 4177223 2999994 3496828 4687691 ...
##  $ Adjusted: num [1:373] 16.1 16.3 16.5 16.1 16.4 ...
##  $ Dia     : chr [1:373] "Lunes" "Martes" "Miercoles" "Jueves" ...


No olvidemos que hay NA's en Close Si la información se trata de un precio, ¿qué valores podemos usar para sustituir los NA's? Podemos apoyarnos en una gráfica para tomar la mejor decisión

library('ggplot2')
ggplot(data=alfa, mapping = aes(x=Fecha, y=Close, group=1)) + geom_line()

library('ggplot2')
ggplot(data=alfa[1:100,], mapping = aes(x=Fecha, y=Close, group=1)) + geom_line()


- ¿Qué pasa si usamos 0's? - ¿Qué pasa si usamos la media? - ¿Qué pasa si eliminamos los valores?


1. Podemos incluir otro valor de nuestro conjunto de datos como el precio ajustado 2. Podemos incluir el último valor conocido


Antes, cargamos la librería dplyr

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union


# Podemos generar datos ajustados utilizando alguno de los siguientes dos procesos 

# 1. Incluimos el ajustado
alfa <- alfa %>% mutate(Close_adj = ifelse(is.na(Close), Adjusted, Close))

# 2. Incluimos el último conocido
library('zoo')
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
alfa <- alfa %>% mutate(Close_ult_conocido = na.locf(Close))
summary(alfa)
##      Fecha                 Open            High            Low       
##  Min.   :2020-01-02   Min.   : 6.30   Min.   : 6.74   Min.   : 6.12  
##  1st Qu.:2020-05-19   1st Qu.:12.01   1st Qu.:12.22   1st Qu.:11.80  
##  Median :2020-09-28   Median :13.50   Median :13.75   Median :13.20  
##  Mean   :2020-09-28   Mean   :13.07   Mean   :13.32   Mean   :12.79  
##  3rd Qu.:2021-02-11   3rd Qu.:14.36   3rd Qu.:14.62   3rd Qu.:14.11  
##  Max.   :2021-06-25   Max.   :17.10   Max.   :17.49   Max.   :16.74  
##                                                                      
##      Close           Volume             Adjusted          Dia           
##  Min.   : 6.40   Min.   :   348799   Min.   : 6.387   Length:373        
##  1st Qu.:12.03   1st Qu.:  5026148   1st Qu.:12.010   Class :character  
##  Median :13.47   Median :  7751798   Median :13.442   Mode  :character  
##  Mean   :13.06   Mean   : 11286706   Mean   :13.033                     
##  3rd Qu.:14.34   3rd Qu.: 11154689   3rd Qu.:14.336                     
##  Max.   :16.99   Max.   :538464233   Max.   :16.955                     
##  NA's   :3                                                              
##    Close_adj     Close_ult_conocido
##  Min.   : 6.40   Min.   : 6.40     
##  1st Qu.:12.03   1st Qu.:12.03     
##  Median :13.47   Median :13.47     
##  Mean   :13.06   Mean   :13.06     
##  3rd Qu.:14.36   3rd Qu.:14.36     
##  Max.   :16.99   Max.   :16.99     
## 


ggplot(alfa[1:80,], aes(x=Fecha, group=1)) + geom_line(aes(y=Close_adj), color='blue') + geom_line(aes(y=Close), color='black', size=1)     

ggplot(alfa[1:80,], aes(x=Fecha, group=1)) + geom_line(aes(y=Close_ult_conocido), color='red') + geom_line(aes(y=Close), color='black', size=1)


La naturaleza de la fuente de información es de una Serie de Tiempo. Para manipular Series de Tiempo haremos uso de la librería xts

library('xts')
## 
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
## 
##     first, last
# creamos un nuevo conjunto de de datos que no tenga la columna dia (es un valor de texto)
alfa$Dia <- NULL

# Solo incluimos las columnas numéricas y ordenamos por la Fecha del registro
alfa_st <- xts(alfa[,2:9], order.by = as.Date(alfa$Fecha))


El ya clásico summary() y head() para analizar nuestros datos

summary(alfa_st)
##      Index                 Open            High            Low       
##  Min.   :2020-01-02   Min.   : 6.30   Min.   : 6.74   Min.   : 6.12  
##  1st Qu.:2020-05-19   1st Qu.:12.01   1st Qu.:12.22   1st Qu.:11.80  
##  Median :2020-09-28   Median :13.50   Median :13.75   Median :13.20  
##  Mean   :2020-09-28   Mean   :13.07   Mean   :13.32   Mean   :12.79  
##  3rd Qu.:2021-02-11   3rd Qu.:14.36   3rd Qu.:14.62   3rd Qu.:14.11  
##  Max.   :2021-06-25   Max.   :17.10   Max.   :17.49   Max.   :16.74  
##                                                                      
##      Close           Volume             Adjusted        Close_adj    
##  Min.   : 6.40   Min.   :   348799   Min.   : 6.387   Min.   : 6.40  
##  1st Qu.:12.03   1st Qu.:  5026148   1st Qu.:12.010   1st Qu.:12.03  
##  Median :13.47   Median :  7751798   Median :13.442   Median :13.47  
##  Mean   :13.06   Mean   : 11286706   Mean   :13.033   Mean   :13.06  
##  3rd Qu.:14.34   3rd Qu.: 11154689   3rd Qu.:14.336   3rd Qu.:14.36  
##  Max.   :16.99   Max.   :538464233   Max.   :16.955   Max.   :16.99  
##  NA's   :3                                                           
##  Close_ult_conocido
##  Min.   : 6.40     
##  1st Qu.:12.03     
##  Median :13.47     
##  Mean   :13.06     
##  3rd Qu.:14.36     
##  Max.   :16.99     
## 
head(alfa_st)
##             Open  High   Low  Close  Volume Adjusted Close_adj
## 2020-01-02 15.82 16.26 15.81 16.160 3605877 16.10172    16.160
## 2020-01-03 16.16 16.40 16.09 16.360 4177223 16.30100    16.360
## 2020-01-06 16.30 16.61 16.30 16.535 2999994 16.47537    16.535
## 2020-01-07 16.62 16.62 15.96 16.130 3496828 16.07184    16.130
## 2020-01-08 16.13 16.49 15.96 16.440 4687691 16.38072    16.440
## 2020-01-09 16.48 16.48 16.06 16.400 6024214 16.34086    16.400
##            Close_ult_conocido
## 2020-01-02             16.160
## 2020-01-03             16.360
## 2020-01-06             16.535
## 2020-01-07             16.130
## 2020-01-08             16.440
## 2020-01-09             16.400


Como la fecha ahora es el índice, podemos acceder a los renglones mediante intervalos de tiempo

alfa_st['2020-01',]
##             Open  High   Low  Close   Volume Adjusted Close_adj
## 2020-01-02 15.82 16.26 15.81 16.160  3605877 16.10172  16.16000
## 2020-01-03 16.16 16.40 16.09 16.360  4177223 16.30100  16.36000
## 2020-01-06 16.30 16.61 16.30 16.535  2999994 16.47537  16.53500
## 2020-01-07 16.62 16.62 15.96 16.130  3496828 16.07184  16.13000
## 2020-01-08 16.13 16.49 15.96 16.440  4687691 16.38072  16.44000
## 2020-01-09 16.48 16.48 16.06 16.400  6024214 16.34086  16.40000
## 2020-01-10 16.36 16.42 16.00 16.020 22456679 15.96223  16.02000
## 2020-01-13 16.01 16.13 15.86 16.100  6471527 16.04194  16.10000
## 2020-01-14 16.09 16.09 15.74     NA  5061703 15.77291  15.77291
## 2020-01-15 15.80 15.87 15.15     NA  9739995 15.15515  15.15515
## 2020-01-16 15.32 15.69 15.32 15.600  6423771 15.54375  15.60000
## 2020-01-17 15.68 15.93 15.41 15.840  5391571 15.78288  15.84000
## 2020-01-20 15.72 15.93 15.72 15.850  2521043 15.79284  15.85000
## 2020-01-21 15.76 15.76 15.51 15.650  2192267 15.59356  15.65000
## 2020-01-22 15.69 15.82 15.36 15.560  3848436 15.50389  15.56000
## 2020-01-23 15.52 15.52 15.30 15.390  3798998 15.33450  15.39000
## 2020-01-24 15.39 15.56 15.11 15.140  5018638 15.08540  15.14000
## 2020-01-27 14.96 14.96 14.38 14.415  7913313 14.36302  14.41500
## 2020-01-28 14.55 14.75 14.25 14.330  4023380 14.27832  14.33000
## 2020-01-29 14.36 14.45 14.12 14.220  2697000 14.16872  14.22000
## 2020-01-30 14.25 14.35 14.11 14.250  6553877 14.19861  14.25000
## 2020-01-31 14.19 14.37 14.05 14.190 15015856 14.13883  14.19000
##            Close_ult_conocido
## 2020-01-02             16.160
## 2020-01-03             16.360
## 2020-01-06             16.535
## 2020-01-07             16.130
## 2020-01-08             16.440
## 2020-01-09             16.400
## 2020-01-10             16.020
## 2020-01-13             16.100
## 2020-01-14             16.100
## 2020-01-15             16.100
## 2020-01-16             15.600
## 2020-01-17             15.840
## 2020-01-20             15.850
## 2020-01-21             15.650
## 2020-01-22             15.560
## 2020-01-23             15.390
## 2020-01-24             15.140
## 2020-01-27             14.415
## 2020-01-28             14.330
## 2020-01-29             14.220
## 2020-01-30             14.250
## 2020-01-31             14.190


Graficamos con ggplot. La variable x es el índice de nuestra Serie de Tiempo

ggplot(alfa_st, aes(Index, Close)) + geom_line() + xlab('Fecha') + ylab('Open')


Como nuestros datos contienen el formato OHLC, podemos usar el paquete quantmod para obtener una gráfica de velas.

library('quantmod')
## Loading required package: TTR
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
chartSeries(alfa_st['2020-01',])


Calculamos los retornos de la Serie de Tiempo

alfa_returns <- diff(alfa_st, arithmetic=FALSE) - 1
summary(alfa_returns)
##      Index                 Open                 High           
##  Min.   :2020-01-02   Min.   :-0.1601445   Min.   :-0.1722846  
##  1st Qu.:2020-05-19   1st Qu.:-0.0148910   1st Qu.:-0.0124943  
##  Median :2020-09-28   Median :-0.0003519   Median :-0.0012492  
##  Mean   :2020-09-28   Mean   : 0.0003888   Mean   : 0.0002919  
##  3rd Qu.:2021-02-11   3rd Qu.: 0.0133891   3rd Qu.: 0.0101420  
##  Max.   :2021-06-25   Max.   : 0.2595041   Max.   : 0.2219178  
##                       NA's   :1            NA's   :1           
##       Low                 Close               Volume        
##  Min.   :-0.1937075   Min.   :-0.204614   Min.   :-0.96007  
##  1st Qu.:-0.0123638   1st Qu.:-0.012467   1st Qu.:-0.31615  
##  Median : 0.0016331   Median : 0.000000   Median :-0.01542  
##  Mean   : 0.0003709   Mean   : 0.000942   Mean   : 0.43585  
##  3rd Qu.: 0.0129001   3rd Qu.: 0.012271   3rd Qu.: 0.51096  
##  Max.   : 0.2173554   Max.   : 0.275748   Max.   :16.52490  
##  NA's   :1            NA's   :6           NA's   :1         
##     Adjusted            Close_adj          Close_ult_conocido  
##  Min.   :-0.2046145   Min.   :-0.2046144   Min.   :-0.2046144  
##  1st Qu.:-0.0133143   1st Qu.:-0.0133143   1st Qu.:-0.0126775  
##  Median : 0.0000000   Median : 0.0000000   Median : 0.0000000  
##  Mean   : 0.0004583   Mean   : 0.0004491   Mean   : 0.0004613  
##  3rd Qu.: 0.0122182   3rd Qu.: 0.0122181   3rd Qu.: 0.0119824  
##  Max.   : 0.2757474   Max.   : 0.2757475   Max.   : 0.2757475  
##  NA's   :1            NA's   :1            NA's   :1
head(alfa_returns)
##                    Open          High          Low        Close     Volume
## 2020-01-02           NA            NA           NA           NA         NA
## 2020-01-03  0.021491783  0.0086100861  0.017710310  0.012376300  0.1584486
## 2020-01-06  0.008663304  0.0128049390  0.013051523  0.010696760 -0.2818210
## 2020-01-07  0.019632026  0.0006020469 -0.020858836 -0.024493559  0.1656117
## 2020-01-08 -0.029482670 -0.0078219610  0.000000000  0.019218972  0.3405552
## 2020-01-09  0.021698761 -0.0006064281  0.006265602 -0.002433151  0.2851133
##                Adjusted    Close_adj Close_ult_conocido
## 2020-01-02           NA           NA                 NA
## 2020-01-03  0.012376252  0.012376300        0.012376300
## 2020-01-06  0.010696764  0.010696760        0.010696760
## 2020-01-07 -0.024493347 -0.024493559       -0.024493559
## 2020-01-08  0.019218776  0.019218972        0.019218972
## 2020-01-09 -0.002433105 -0.002433151       -0.002433151


Encontramos NA's en el primer renglon, en este caso lo podemos borrar. ¿Por qué el primer registro es NA?

alfa_returns <- na.omit(alfa_returns)
head(alfa_returns)
##                    Open          High          Low        Close     Volume
## 2020-01-03  0.021491783  0.0086100861  0.017710310  0.012376300  0.1584486
## 2020-01-06  0.008663304  0.0128049390  0.013051523  0.010696760 -0.2818210
## 2020-01-07  0.019632026  0.0006020469 -0.020858836 -0.024493559  0.1656117
## 2020-01-08 -0.029482670 -0.0078219610  0.000000000  0.019218972  0.3405552
## 2020-01-09  0.021698761 -0.0006064281  0.006265602 -0.002433151  0.2851133
## 2020-01-10 -0.007281493 -0.0036407767 -0.003735928 -0.023170732  2.7277359
##                Adjusted    Close_adj Close_ult_conocido
## 2020-01-03  0.012376252  0.012376300        0.012376300
## 2020-01-06  0.010696764  0.010696760        0.010696760
## 2020-01-07 -0.024493347 -0.024493559       -0.024493559
## 2020-01-08  0.019218776  0.019218972        0.019218972
## 2020-01-09 -0.002433105 -0.002433151       -0.002433151
## 2020-01-10 -0.023170690 -0.023170732       -0.023170732


Creamos el histograma para tener una primera apreciación de la distribución de los retornos

ggplot(alfa_returns, aes(Close_ult_conocido)) + geom_histogram(bins = 40)


Con una inspección visual, encontramos valores extremos. Graficamos un box plot para corroborar nuestra observación.

#ggplot(alfa_returns, aes(ALFAA.MX.Close_alt_ult_conocido)) + geom_boxplot() + coord_flip()
boxplot(alfa_returns$Close_ult_conocido)

# Otro método para graficar, sin outliers
boxplot(alfa_returns$Close_ult_conocido, outline=FALSE)

# Con Out podemos obtener todos los outliers, debemos indicar el parámetro plot=FALSE para que no regrese la gráfica
outliers <- boxplot(alfa_returns$ALFAA.MX.Close_alt_ult_conocido, plot=FALSE)$Out

Como ejercicio de este punto: - ¿Cómo podemos quitar los outliers de nuestra series de datos? - ¿Tienen algún valor los outliers? - ¿Qué podemos hacer con los outliers?


Por último:

Con la función arrange() podemos ordenar los valores que le especifiquemos de menor a mayor, o bien podemos incluir la función desc() con el nombre de la variable para que los ordene de mayor a menor.

data_arranged <- as.data.frame(alfa_returns) %>% arrange(Open)
head(data_arranged)
##                   Open         High         Low       Close      Volume
## 2020-12-14 -0.16014454 -0.127031961 -0.19370754 -0.20461440  1.50426953
## 2020-03-19 -0.15096154 -0.172284644 -0.06159420 -0.09534620 -0.09760923
## 2020-03-24 -0.12609238 -0.001248439  0.02958580  0.08526012  0.34583065
## 2020-03-20 -0.09399773 -0.062217195 -0.09137709  0.01380176  3.09857766
## 2020-04-01 -0.09221902 -0.089189189 -0.01923077  0.03750000 -0.48471162
## 2021-02-02 -0.07163743 -0.070021882 -0.15559030 -0.06744186  8.86714205
##               Adjusted   Close_adj Close_ult_conocido
## 2020-12-14 -0.20461454 -0.20461440        -0.20461440
## 2020-03-19 -0.09534623 -0.09534620        -0.09534620
## 2020-03-24  0.08526011  0.08526012         0.08526012
## 2020-03-20  0.01380168  0.01380176         0.01380176
## 2020-04-01  0.03749997  0.03750000         0.03750000
## 2021-02-02 -0.06744183 -0.06744186        -0.06744186