El paquete plotly permite la construcción de gráficas de alta calidad y permite incorporar la interactividad en los gráficos, mostrando botones para hacer zoom en una parte de la gráfica, redefinir los ejes X e Y, mostrar la información que contiene cada dato, mostrar datos filtrando por uno o varios factores… Además, son gráficos de tipo “responsive”: se adaptan a las dimensiones de la ventana en que aparecen.

A continuación se presentan cinco ventajas de usar Plotly para gráficos en R:

La interfaz de Plotly es muy intuitiva y fácil de usar. Basta con cargar los datos en la interfaz web de Plotly, seleccionar el tipo de gráfico que se desea crear y hacer clic en el botón «Generar gráfico». Plotly también proporciona una interfaz de programación para R, lo que permite crear gráficos de forma programática.

Los gráficos generados por Plotly son de alta calidad y se pueden personalizar fácilmente. Por ejemplo, es posible ajustar el tamaño, el color y la fuente de los gráficos, agregar etiquetas y leyendas, y agregar elementos interactivos como botones y casillas de verificación.

Plotly es un software de código abierto, lo que significa que es gratuito de usar. Además, Plotly proporciona una versión gratuita y una versión de pago. La versión gratuita tiene todas las funciones de la versión de pago, pero tiene un límite de 1000 gráficos por cuenta.

Plotly es compatible con R, Python, MATLAB, Julia y Perl. Además, se puede integrar con aplicaciones de Shiny y Dash.

Plotly proporciona soporte técnico gratuito a todos sus usuarios. Si tiene algún problema con Plotly, puede ponerse en contacto con el equipo de soporte técnico a través de la interfaz web de Plotly o enviar un correo electrónico a .

¿Qué tipos de gráficos se pueden generar con el paquete plotly en R? ¿Qué tipos de gráficos se pueden generar con el paquete plotly en R?

El paquete plotly en R permite generar una variedad de gráficos y visualizaciones. Algunos de los tipos de gráficos que se pueden generar son:

Los gráficos de barras y de líneas son los más comunes, pero el paquete también permite generar gráficos más avanzados, como gráficos de mapas y de dispersión.

El paquete plotly en R es una herramienta muy útil para la visualización de datos. permite crear gráficos interactivos de alta calidad y exportarlos en diversos formatos.

La forma de construir los gráficos es:

Directamente, cargando la librería y usando el comando plot_ly

# cargamos las librerías
library(plotly)
library(ggplot2)
data("mtcars")
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
mtcars$nombre<-  rownames(mtcars)
plot_ly(  data = mtcars,   x = ~cyl,  y = ~disp)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode

La plot_ly()función inicializó la biblioteca de gráficos mientras data = df indica el marco de datos donde se almacenan los datos. x = ~cyle y = ~dispindicar las columnas a graficar en cada eje.

Es posible que haya recibido algunas advertencias que indican que no se ha especificado el “tipo” y el “modo de dispersión” del gráfico. Estos dos argumentos son opcionales, pero son necesarios para modificar el tipo de gráfico que se está creando. Así es como se ve el código cuando especificamos esos argumentos para crear el mismo gráfico:

mtcars
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
##                                  nombre
## Mazda RX4                     Mazda RX4
## Mazda RX4 Wag             Mazda RX4 Wag
## Datsun 710                   Datsun 710
## Hornet 4 Drive           Hornet 4 Drive
## Hornet Sportabout     Hornet Sportabout
## Valiant                         Valiant
## Duster 360                   Duster 360
## Merc 240D                     Merc 240D
## Merc 230                       Merc 230
## Merc 280                       Merc 280
## Merc 280C                     Merc 280C
## Merc 450SE                   Merc 450SE
## Merc 450SL                   Merc 450SL
## Merc 450SLC                 Merc 450SLC
## Cadillac Fleetwood   Cadillac Fleetwood
## Lincoln Continental Lincoln Continental
## Chrysler Imperial     Chrysler Imperial
## Fiat 128                       Fiat 128
## Honda Civic                 Honda Civic
## Toyota Corolla           Toyota Corolla
## Toyota Corona             Toyota Corona
## Dodge Challenger       Dodge Challenger
## AMC Javelin                 AMC Javelin
## Camaro Z28                   Camaro Z28
## Pontiac Firebird       Pontiac Firebird
## Fiat X1-9                     Fiat X1-9
## Porsche 914-2             Porsche 914-2
## Lotus Europa               Lotus Europa
## Ford Pantera L           Ford Pantera L
## Ferrari Dino               Ferrari Dino
## Maserati Bora             Maserati Bora
## Volvo 142E                   Volvo 142E
plot_ly(  data = mtcars,  x = ~cyl,   y = ~disp,   color = ~factor(cyl),
             type = "scatter", text=~nombre , mode = "markers")
mtcars%>%plot_ly( x = ~hp, y = ~mpg, type = "scatter", 
      color = I("black"), size = ~cyl)  %>%
      add_lines(y = ~fitted(loess(mpg ~ hp)),
            line = list(color = '#07A4B5'),
            name = "Loess Smoother", showlegend = TRUE) %>%
  layout(xaxis = list(title = 'horse power '),
         yaxis = list(title = 'Miles/(US) gallon'),
         legend = list(x = 0.80, y = 0.90))
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.
fig <- ggplot2 :: ggplot ( data = mtcars, aes ( x = cyl, y = disp ) )  + geom_point ( aes ( color = factor ( cyl ) ) ) 
ggplotly ( fig )
PIB vs expectativa de vida
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
library(gapminder)
gapminder=gapminder::gapminder
gapminder_1952<- gapminder %>% filter(year==1952)
gapminder_2007<- gapminder %>% filter(year==2007)
plot_ly(gapminder_1952, x = ~gdpPercap, y = ~lifeExp, type="scatter", text=~country) 
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
plot_ly(gapminder_2007, x =~gdpPercap, y =~ lifeExp, text=~country)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
plot_ly(gapminder, x = ~gdpPercap, y = ~ lifeExp) 
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
Población vs PIB
plot_ly(gapminder_1952, x = ~pop, y = ~gdpPercap)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
plot_ly(gapminder_2007, x = ~pop, y = ~gdpPercap)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode

Poblacion vs Expectativa de vida

plot_ly(gapminder_1952, x = ~pop, y = ~lifeExp)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
plot_ly(gapminder_2007, x = ~pop, y = ~lifeExp)
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode

Cuando las curvas son como en la figura Este!, es razonable aplicar escalamiento de los datos, en este caso, logaritmo base 10 en la variable del eje x.

fig=plot_ly(gapminder_1952, x = ~pop, y = ~lifeExp)
fig
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
fig<-  layout(fig, xaxis = list(type = "log"))
fig
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
log10(1000000000)
## [1] 9
gapminder_2007
## # A tibble: 142 × 6
##    country     continent  year lifeExp       pop gdpPercap
##    <fct>       <fct>     <int>   <dbl>     <int>     <dbl>
##  1 Afghanistan Asia       2007    43.8  31889923      975.
##  2 Albania     Europe     2007    76.4   3600523     5937.
##  3 Algeria     Africa     2007    72.3  33333216     6223.
##  4 Angola      Africa     2007    42.7  12420476     4797.
##  5 Argentina   Americas   2007    75.3  40301927    12779.
##  6 Australia   Oceania    2007    81.2  20434176    34435.
##  7 Austria     Europe     2007    79.8   8199783    36126.
##  8 Bahrain     Asia       2007    75.6    708573    29796.
##  9 Bangladesh  Asia       2007    64.1 150448339     1391.
## 10 Belgium     Europe     2007    79.4  10392226    33693.
## # ℹ 132 more rows
gapminder_2007 %>%  plot_ly(x = ~gdpPercap, y = ~lifeExp, color = ~continent) %>% layout(xaxis=list(type="log")) 
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
gapminder_2007 %>%  plot_ly(x = ~gdpPercap, y = ~lifeExp, color = ~continent, size=~pop, text=~country) %>% layout(xaxis=list(type="log"))
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plotly.com/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plotly.com/r/reference/#scatter-mode
## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.
p1=ggplot(gapminder_1952,aes(x=pop,y=lifeExp))+
  geom_point()+
  scale_x_log10()+
  facet_wrap(~continent)
ggplotly(p1)

FIGURAS CON LíNEAS

by_year <- gapminder %>% group_by(year) %>% summarize(medianGdpPercap=median(gdpPercap))

FIGURAS CON BARPLOTS

by_continent<- gapminder %>% 
  filter(year == 2007) %>% 
  group_by(continent) %>% 
  summarize(meanLifeExp=mean(lifeExp))
plot_ly(by_continent, x = ~continent, y = ~meanLifeExp, type = 'bar') 
by_continent<- gapminder %>% 
  filter(year == 1952) %>% 
  group_by(continent) %>% 
  summarize(medianGdpPercap=median(gdpPercap))
plot_ly(by_continent, x = ~continent, y = ~medianGdpPercap, type = 'bar') %>%
  layout(barmode = 'group')

FIGURAS CON HISTOGRAMAS

library(plotly)

plot_ly(gapminder_2007, x = ~lifeExp, type = 'histogram') 
plot_ly(gapminder_2007, x = ~lifeExp, type = 'histogram', xbins = list(size = 5)) %>%
  layout(title = "Histograma de lifeExp en 2007",
         xaxis = list(title = "Esperanza de vida"),
         yaxis = list(title = "Frecuencia")) 
gapminder_1952 <- gapminder %>%  filter(year == 1952)

FIGURAS CON BOXPLOT

gapminder_2007 <- gapminder %>%
  filter(year == 2007)
ggplot(gapminder_2007,aes(x=continent, y=lifeExp))+
  geom_boxplot()

plot_ly(gapminder_2007, x = ~continent, y = ~lifeExp, type = 'box') 
gapminder_1952 <- gapminder %>%
  filter(year == 1952)

library(plotly)

plot_ly(gapminder_1952, x = ~continent, y = ~gdpPercap, type = 'box') %>%
  layout(yaxis = list(type = 'log'))

Gráfico dinámico

plot_ly(data = gapminder, x = ~gdpPercap, y = ~lifeExp, color = ~continent,
        size = ~pop, frame = ~year, text = ~country, type = 'scatter',
        mode = 'markers') %>%
  layout(xaxis = list(type = 'log'))
colombia=gapminder %>% filter(country=="Colombia")
colombia
## # A tibble: 12 × 6
##    country  continent  year lifeExp      pop gdpPercap
##    <fct>    <fct>     <int>   <dbl>    <int>     <dbl>
##  1 Colombia Americas   1952    50.6 12350771     2144.
##  2 Colombia Americas   1957    55.1 14485993     2324.
##  3 Colombia Americas   1962    57.9 17009885     2492.
##  4 Colombia Americas   1967    60.0 19764027     2679.
##  5 Colombia Americas   1972    61.6 22542890     3265.
##  6 Colombia Americas   1977    63.8 25094412     3816.
##  7 Colombia Americas   1982    66.7 27764644     4398.
##  8 Colombia Americas   1987    67.8 30964245     4903.
##  9 Colombia Americas   1992    68.4 34202721     5445.
## 10 Colombia Americas   1997    70.3 37657830     6117.
## 11 Colombia Americas   2002    71.7 41008227     5755.
## 12 Colombia Americas   2007    72.9 44227550     7007.
library(TSstudio)
dt=seq(as.Date("1952/01/01"), as.Date("2007/01/01"),by="5 year")
length(dt)
## [1] 12
library(xts)
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
## 
## ######################### Warning from 'xts' package ##########################
## #                                                                             #
## # The dplyr lag() function breaks how base R's lag() function is supposed to  #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
## # source() into this session won't work correctly.                            #
## #                                                                             #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
## # dplyr from breaking base R's lag() function.                                #
## #                                                                             #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
## #                                                                             #
## ###############################################################################
## 
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
## 
##     first, last
s1=xts(colombia$lifeExp, dt)
s1
##              [,1]
## 1952-01-01 50.643
## 1957-01-01 55.118
## 1962-01-01 57.863
## 1967-01-01 59.963
## 1972-01-01 61.623
## 1977-01-01 63.837
## 1982-01-01 66.653
## 1987-01-01 67.768
## 1992-01-01 68.421
## 1997-01-01 70.313
## 2002-01-01 71.682
## 2007-01-01 72.889
plot.xts(s1, main = "Esperanza de vida Colombia", ylab="Esperanza de vida en años")

ts_plot(s1,Xtitle = "aÑO",Ytitle = "Esperanza de vida en años",line.mode ="lines+markers", slider = TRUE)
by_year_continent=gapminder %>% group_by(year,continent) %>% summarise(media=median(lifeExp))
## `summarise()` has grouped output by 'year'. You can override using the
## `.groups` argument.
by_year_continent
## # A tibble: 60 × 3
## # Groups:   year [12]
##     year continent media
##    <int> <fct>     <dbl>
##  1  1952 Africa     38.8
##  2  1952 Americas   54.7
##  3  1952 Asia       44.9
##  4  1952 Europe     65.9
##  5  1952 Oceania    69.3
##  6  1957 Africa     40.6
##  7  1957 Americas   56.1
##  8  1957 Asia       48.3
##  9  1957 Europe     67.6
## 10  1957 Oceania    70.3
## # ℹ 50 more rows
ggplot(by_year_continent,aes(x=year,y=media, color=continent))+
  geom_line()

  #expand_limits(y = 30)

El manejo de fechas es tan importante como aprender el manejo de factores u otros tipos de datos de uso común en un análisis de datos,

Creación de fechas

class(as.Date("2020/01/23"))
## [1] "Date"

Date

Se tienen diferentes formas de crear fechas:

as.Date('1998-09-15')
## [1] "1998-09-15"
as.Date('1998/9/15')
## [1] "1998-09-15"

Formato por defecto: AAAA, M(M), D(D)

Si se tiene otro formato de entrada, se puede utilizar las siguientes combinaciones para indicar dicho formato

Símbolo Descripción
%d Día en número
%m Mes en número abreviado
%b Mes abreviado
%B Mes en nombre completo
%y Año en 2 dígitos
%Y Año en 4 dígitos

Aquí algunos ejemplos:

as.Date('Marzo/15: 1992', format = '%B/%d: %Y')
## [1] "1992-03-15"
as.Date("Septiembre 15, 1998", format = "%B %d, %Y")
## [1] "1998-09-15"
as.Date("15JUNIO1998", format = "%d%b%Y")
## [1] "1998-06-15"

La fecha establecida, en general, de origen para el manejo de fechas es el 1 de Enero de 1970 (Unix Epoch), y con este día podemos obtener la representación numérica que entiende el ordenador (Epoch Time). Con días antes obtendremos números negativos y posteriores positivos

Manipulación de fechas

Extracción de componentes

fechitas <- c(birthday = as.Date("SepTIEMBRE 15, 1998", format = "%B %d, %Y"),
              begin = as.Date("Enero 2, 1970", format = "%B %d, %Y"),
              other = as.Date("15JUNIO1998", format = "%d%b%Y"),
              other2 = as.Date('1998-09-15'),
              today = as.Date("2023/06/21")) 

weekdays(fechitas)
##    birthday       begin       other      other2       today 
##    "martes"   "viernes"     "lunes"    "martes" "miércoles"
months(fechitas)
##     birthday        begin        other       other2        today 
## "septiembre"      "enero"      "junio" "septiembre"      "junio"
quarters(fechitas)
## [1] "Q3" "Q1" "Q2" "Q3" "Q2"

OperacionesBásicas

mean(fechitas)
## [1] "1997-11-13"
mean(c(as.Date("2020/01/01"), as.Date("2020/12/31")))
## [1] "2020-07-01"

range: Rango de las fechas (Fecha más antigua, Fecha reciente)

range(fechitas)
## [1] "1970-01-02" "2023-06-21"
#sum: Suma de fechas
as.Date("2020/12/8") + 1
## [1] "2020-12-09"
#Resta
as.Date("2020/12/8") - 8
## [1] "2020-11-30"

Difftime

as.Date("2020/12/8") - as.Date("2020/12/7")
## Time difference of 1 days

Las diferencias entre fechas son un nuevo tipo de objeto

class(as.Date("2020/12/8") - as.Date("2020/12/7"))
## [1] "difftime"

Y podemos decir como es medida esa diferencia:

f1 <- as.Date("2020/12/8")
f2 <- as.Date("2020/12/7")
difftime(f1,f2, units = "secs")
## Time difference of 86400 secs
cat(paste("Minutos: ",difftime(f1,f2, units = "mins"),
"\nHoras: ",difftime(f1,f2, units = "hours"),
"\nDías: ",difftime(f1,f2, units = "days"),
"\nSemanas",difftime(f1,f2, units = "weeks")))
## Minutos:  1440 
## Horas:  24 
## Días:  1 
## Semanas 0.142857142857143

lubridate

Tenemos funciones como today() y now() que nos devuelven la fecha actual.

library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
cat(paste("Fecha actual: ",today(),
          "\nFecha actual con horario: ",now()))
## Fecha actual:  2023-06-21 
## Fecha actual con horario:  2023-06-21 19:01:56.868418
cat(paste("ymd: ",ymd("2020-12-01"),
          "\nmdy: ", mdy("December 1st, 2020"),
          "\ndmy: ", dmy("01-Dec-2020")))
## ymd:  2020-12-01 
## mdy:  2020-12-01 
## dmy:  2020-12-01

Además de poder hacerlas con un objeto numérico:

ymd(20201201)
## [1] "2020-12-01"

Para crear las fechas con las horas, se utilizan funciones muy similares a las anteriores sólo que ahora se agrega un _ y el formato de fecha con h, m y s

cat(paste("Con hora, minutos y segundos: ",ydm_hms("2020-12-01 15:50:56"),
          "\nCon hora y minutos: ", ydm_hm("2020-12-01 15:50"),
          "\nCon hora: ", ydm_h("2020-12-01 15")))
## Con hora, minutos y segundos:  2020-01-12 15:50:56 
## Con hora y minutos:  2020-01-12 15:50:00 
## Con hora:  2020-01-12 15:00:00

Donde la zona horaria puede ser fácil agregada

ydm_hms("2020-12-01 15:50:56", tz = "UTC")
## [1] "2020-01-12 15:50:56 UTC"

lubridate añade lapsos de tiempos más allá de los que se pueden obtener con difftime.

Extracciones

Vamos a tomar el ejemplo dado por ymd(20201201) para obtener algunas componentes con distintas funciones que nos proporciona lubridate.

fecha <- ymd(20201201)
cat(paste("Fecha: ", fecha,
          "\nAño: ", year(fecha),
          "\nMes: ", month(fecha),
          "\nDía: ", mday(fecha),
          "\nDía del año: ", yday(fecha),
          "\nDía de la semana: ", wday(fecha)))
## Fecha:  2020-12-01 
## Año:  2020 
## Mes:  12 
## Día:  1 
## Día del año:  336 
## Día de la semana:  3

Además se puede agregar el nombre abreviado (o no) de algunas componentes

cat(paste("Mes: ", month(fecha, label = TRUE, abbr = TRUE),
          "\nDía de la semana: ", wday(fecha, label = TRUE, abbr = FALSE)))
## Mes:  dic 
## Día de la semana:  martes

Duraciones

Las duraciones son cantidades exactas en segundos

tod_yes <- as.Date("2020/12/8") - as.Date("2020/12/7")
as.duration(tod_yes)
## [1] "86400s (~1 days)"

Además de que se tienen otros constructores:

cat(paste("Segundos: ",dseconds(10),
          "\nMinutos: ",dminutes(10),
          "\nHoras: ", dhours(10),
          "\nDías: ",ddays(10),
          "\nSemanas: ", dweeks(10),
          "\nAños: ",dyears(10)))
## Segundos:  10s 
## Minutos:  600s (~10 minutes) 
## Horas:  36000s (~10 hours) 
## Días:  864000s (~1.43 weeks) 
## Semanas:  6048000s (~10 weeks) 
## Años:  315576000s (~10 years)

Y con esto ya se pueden realizar operaciones:

dyears(c(10, 20, 30)) + dweeks(c(5, 6, 7)) + dhours(c(40, 50, 60))
## [1] "318744000s (~10.1 years)"  "634960800s (~20.12 years)"
## [3] "951177600s (~30.14 years)"

Aunque al estar tratando con segundos exactos, podemos tener resultados inesperados debido a los cambios de horario que ya están considerados en estas funciones

Zoo y xts

Cuando se esta trabajando con una serie de tiempo se acostumbra el uso de los objetos ts proporcionados por el constructor stats::ts(), aunque otra alternativa más amigable para la manipulación de fechas en series de tiempo la proporciona xts, la cual es una librería derivada de zoo. Para una introducción sobre series de tiempo en R, se puede consultar el siguiente link.

Además de proporcionar funciones y filtros para manipular de manera más sencilla que con un objeto ts, se tienen algunas ventajas sobre los objetos ts ya que estos, al distribuir sus tiempos de manera uniforme y de igual longitud, pueden conllevar a problemas cuando no se tenga esta estructura en los datos, como en datos financieros. Con los objetos zoo y xts no se tendrá problema al trata con tiempos espaciados de manera irregular.

Para objetos zoo y xts, se deben dar dos componentes fundamentales: coredata e index, los cuales son suministrados en los argumentos x y order.by respectivamente en los constructores zoo::zoo() y xts::xts(). Se tienen otros argumentos comunes como la frecuencia en objetos ts.

library(zoo)
library(xts)
set.seed(10)

#coredata

data <- rgamma(n = 10, shape = 10, scale = 0.5)

index

dates <- seq(as.Date("2021-01-01"), length = 10, by = "days")
zoo::zoo(x = data, order.by = dates)
## 2021-01-01 2021-01-02 2021-01-03 2021-01-04 2021-01-05 2021-01-06 2021-01-07 
##   4.778934   4.470291   3.659127   5.214769   5.369706   3.070661   4.477540 
## 2021-01-08 2021-01-09 2021-01-10 
##   4.362963   5.212754   4.196428

Además, se permite agregar metadata directamente en el constructor xts().

one_more_data <- lubridate::today()
xts_one <- xts::xts(x = data, order.by = dates, meta = one_more_data)
str(xts_one)
## An xts object on 2021-01-01 / 2021-01-10 containing: 
##   Data:    double [10, 1]
##   Index:   Date [10] (TZ: "UTC")
##   xts Attributes:
##     $ meta: Date[1:1], format: "2023-06-21"

Conversiones

De igual manera, para crear un objeto xts, se puede utiliza la función as.xts() la cual soporta objetos de tipo timeSeries, ts, irts, fts, matrix, data.frame y zoo.

(APxst <- as.xts(AirPassengers) %>% head())
##           [,1]
## ene. 1949  112
## feb. 1949  118
## mar. 1949  132
## abr. 1949  129
## may. 1949  121
## jun. 1949  135

Y se puede convertir un objeto xts en diferentes formatos sin ningún problema. Esto es muy útil ya que pueden existir funciones que R que sólo admitan objetos ts.

cat(paste("as.matrix(): ", class(as.matrix(APxst)),
          "\nas.ts():", class(as.ts(APxst))))
## as.matrix():  matrix 
## as.ts(): ts as.matrix():  array 
## as.ts(): ts

Extración

Los componentes de un objeto zoo o xts se pueden obtener con las siguientes funciones. La primera regresará una matriz y la segunda un vector tipo Date.

zoo::coredata(xts_one)
##           [,1]
##  [1,] 4.778934
##  [2,] 4.470291
##  [3,] 3.659127
##  [4,] 5.214769
##  [5,] 5.369706
##  [6,] 3.070661
##  [7,] 4.477540
##  [8,] 4.362963
##  [9,] 5.212754
## [10,] 4.196428
zoo::index(xts_one)
##  [1] "2021-01-01" "2021-01-02" "2021-01-03" "2021-01-04" "2021-01-05"
##  [6] "2021-01-06" "2021-01-07" "2021-01-08" "2021-01-09" "2021-01-10"

xts tiene algunas funciones para extraer periodos extremos en la serie los cuales se pueden combinar para obtener información interesante. Los periodos pueden ser secs, seconds, mins, minutes, hours, days, weeks, months, quarters, y years. Las funciones son las siguientes:

last : Obtiene el último periodo solicitado. first: Obtiene el primer periodo solicitado.

bad_year <- as.Date("2020-01-01") + 0:365
bad_year_xts <- xts(x = seq_along(bad_year), order.by = bad_year)
  • Del último mes del 2020, se toma la primera semana y todos los días excepto los últimos 3
xts::last(xts::first(xts::last(bad_year_xts, "1 month"), "1 week"), "-3 days")
##            [,1]
## 2020-12-01  336
## 2020-12-02  337
## 2020-12-03  338

Filtros

Referente a los filtros, estos son más sencillos que en un objeto ts, ya que se puede especificar el año, o el mes, el día, etc., mediante los formatos internacionales estandarizados ISO-8601; es decir: AAAA-MM-DD o AAAAMMDD y sus reducciones para obtener sólo un mes, un año o un día en específico

dates <- as.Date("2015-01-01") + 0:1000
some_days_2015_2017 <- xts(x = seq_along(dates), order.by = dates)

Sólo un año

some_days_2015_2017["2016"]
##            m.c.seq.row..seq.n...seq.col..drop...FALSE.
## 2016-01-01                                         366
## 2016-01-02                                         367
## 2016-01-03                                         368
## 2016-01-04                                         369
## 2016-01-05                                         370
## 2016-01-06                                         371
## 2016-01-07                                         372
## 2016-01-08                                         373
## 2016-01-09                                         374
## 2016-01-10                                         375
##        ...                                            
## 2016-12-22                                         722
## 2016-12-23                                         723
## 2016-12-24                                         724
## 2016-12-25                                         725
## 2016-12-26                                         726
## 2016-12-27                                         727
## 2016-12-28                                         728
## 2016-12-29                                         729
## 2016-12-30                                         730
## 2016-12-31                                         731

Un día

some_days_2015_2017["20160808"]
##            [,1]
## 2016-08-08  586

También es posible hacer un rango de fechas separando estas con una diagonal /

some_days_2015_2017["20160201/20160220"]
##            [,1]
## 2016-02-01  397
## 2016-02-02  398
## 2016-02-03  399
## 2016-02-04  400
## 2016-02-05  401
## 2016-02-06  402
## 2016-02-07  403
## 2016-02-08  404
## 2016-02-09  405
## 2016-02-10  406
## 2016-02-11  407
## 2016-02-12  408
## 2016-02-13  409
## 2016-02-14  410
## 2016-02-15  411
## 2016-02-16  412
## 2016-02-17  413
## 2016-02-18  414
## 2016-02-19  415
## 2016-02-20  416

Todos los datos a partir del primero de febrero

some_days_2015_2017["20160201/"]
##            m.c.seq.row..seq.n...seq.col..drop...FALSE.
## 2016-02-01                                         397
## 2016-02-02                                         398
## 2016-02-03                                         399
## 2016-02-04                                         400
## 2016-02-05                                         401
## 2016-02-06                                         402
## 2016-02-07                                         403
## 2016-02-08                                         404
## 2016-02-09                                         405
## 2016-02-10                                         406
##        ...                                            
## 2017-09-18                                         992
## 2017-09-19                                         993
## 2017-09-20                                         994
## 2017-09-21                                         995
## 2017-09-22                                         996
## 2017-09-23                                         997
## 2017-09-24                                         998
## 2017-09-25                                         999
## 2017-09-26                                        1000
## 2017-09-27                                        1001

O bien utilizando rangos normales

dates <- seq(as.Date("2016-01-01"), as.Date("2016-01-10"), by = "day")
some_days_2015_2017[dates]
##            [,1]
## 2016-01-01  366
## 2016-01-02  367
## 2016-01-03  368
## 2016-01-04  369
## 2016-01-05  370
## 2016-01-06  371
## 2016-01-07  372
## 2016-01-08  373
## 2016-01-09  374
## 2016-01-10  375
some_days_2015_2017[as.POSIXct(dates)]
##            [,1]
## 2016-01-01  366
## 2016-01-02  367
## 2016-01-03  368
## 2016-01-04  369
## 2016-01-05  370
## 2016-01-06  371
## 2016-01-07  372
## 2016-01-08  373
## 2016-01-09  374
## 2016-01-10  375