2018-02-04

Representar serie continua con geom_ribbon de ggplot2

Title

Problema

Cuando intentamos representar una serie continua, en nuestro ejemplo WS (Winter Solstice), ggplot2 une el último dato de WS (invierno) en marzo con el primero en diciembre, obteniendo el siguiente resultado indeseado.

  • Datos
library(ggplot2)

getSeason <- function(DATES) {
#found here https://stackoverflow.com/questions/9500114/find-which-season-a-particular-date-belongs-to
WS <- as.Date("2012-12-15", format = "%Y-%m-%d") # Winter Solstice
SE <- as.Date("2012-3-15",  format = "%Y-%m-%d") # Spring Equinox
SS <- as.Date("2012-6-15",  format = "%Y-%m-%d") # Summer Solstice
FE <- as.Date("2012-9-15",  format = "%Y-%m-%d") # Fall Equinox

# Convert dates from any year to 2012 dates
d <- as.Date(strftime(DATES, format="2012-%m-%d"))

ifelse (d >= WS | d < SE, "Winter",
  ifelse (d >= SE & d < SS, "Spring",
    ifelse (d >= SS & d < FE, "Summer", "Fall")))
}

zz <- sample(1:10000,365)/1000
dag <- seq(as.Date("2014-01-01"), as.Date("2014-12-31"), by = "day")
seas <-  getSeason(dag)
test <- data.frame(zz,dag,seas)

ggplot(data=test, aes(x=dag,ymax=zz,ymin=0,fill=seas))+
geom_ribbon()

Solución

Dividimos los datos con dplyr en dos subconjuntos, igual o mayor que el 2014-12-15 y por debajo de dicha fecha. Así convertimos la serie WS en dos secciones discretas, evitando que una los dos extremos de WS.

library(dplyr)
ggplot() +
  geom_ribbon(data = filter(test, dag >= "2014-12-15") ,
              aes(x = dag, ymax = zz, ymin = 0, fill = seas)) +
  geom_ribbon(data = filter(test, dag < "2014-12-15") ,
              aes(x = dag, ymax = zz, ymin = 0, fill = seas))

Resultados

Referencias

2018-02-01

Representar cuartiles con geom_pointrange de ggplot2

Title

Problema

Deseamos representar con una recta el rango intercuartílico marcando la mediana con un punto.

Solución

Empleamos la función geom_pointrange del paquete ggplot2. Delimitamos el min y máximo de y con fun.ymin y fun.ymin respectivamente. Con fun.y marcamos la coordinada del punto y para la mediana.

library(ggplot2)
ggplot(data = diamonds) +
  geom_pointrange(mapping = aes(x = cut, y = depth),
                  stat = "summary",
                  fun.ymin = function(z) {quantile(z,0.25)},
                  fun.ymax = function(z) {quantile(z,0.75)},
                  fun.y = median)

Resultados

Referencias

2018-01-25

Media móvil en R

Title

Problema

¿Cómo podemos calcular la media móvil en R? Es decir, calcular la media aritmética de n datos anteriores. En el siguiente ejemplo, la media de los 4 datos anteriores. En el primer cálculo la media de los 4 primeros términos: del 1 al 4. En el segundo del 2 al 5, y así sucesivamente.

   num media_movil
1       1          NA
2       2          NA
3       3          NA
4       4         2.5
5       5         3.5
6       6         4.5

Solución

Muestro dos alternativas, con los paquetes zoo y RcppRoll, con sintáxis casi idéntica. En ambas utilizo dplyr para crear la nueva columna con la función mutate.

  • Alternativa 1: zoo
  • Con el argumento k (4 en este ejemplo) suministramos un número entero que indica el intervalo de la media móvil.

    library(zoo) 
    library(dplyr)
    df <- data.frame(num = 1:20)
      df %>% mutate(media_movil = rollmean(num, k = 4 , fill = NA, align = "right"))
    
  • Alternativa 2: RcppRoll
  • Con el argumento n (4 en este ejemplo) suministramos un número entero que indica el intervalo de la media móvil.

    library(RcppRoll)
    df %>% mutate(media_movil = roll_mean(num, n = 4, fill = NA, align = "right"))
    

Resultados

   num media_movil
1    1          NA
2    2          NA
3    3          NA
4    4         2.5
5    5         3.5
6    6         4.5
7    7         5.5
8    8         6.5
9    9         7.5
10  10         8.5
11  11         9.5
12  12        10.5
13  13        11.5
14  14        12.5
15  15        13.5
16  16        14.5
17  17        15.5
18  18        16.5
19  19        17.5
20  20        18.5

Referencias

2018-01-20

Rellenar área con teselas en ggplot2

Title

Problema

Con ggplot2 queremos rellenar una región cuadrada con teselas cuadradas. El intento original del usuario que plantéo la pregunta fue:

  • Datos
set.seed(1)
library(ggplot2)
# Datos
l = 1000
a = seq(0, 1, 1 / (l - 1))
x = rep(a, each = length(a))
y = rep(a, length(a))
k = length(x)
c = sample(1:10, k, replace = TRUE)
data <- data.frame(x, y, c)
# Gráfico
ggplot(data, aes(x = x, y = y)) + geom_point(shape = 15, color = c)

Solución

  • Alternativa 1
  • Reducimos el tamaño del data frame, l = 10 en el código anterior para poder apreciar los cuadrados. Y usamos el argumento "white" como colour p para resaltar las teselas con un contorno blanco.

    ggplot(data, aes(x = x, y = y, fill = c)) + geom_tile(colour = "white")
    
  • Alternativa 2
  • Creamos manualmente una paleta, y empleamos coord_equal para generar cuadrados, forzando a que una unidad en el eje x tenga la misma longitud que una unidad en el eje y.

    colors<-c("peachpuff", "yellow", "orange", "orangered", "red", 
              "darkred","firebrick", "royalblue", "darkslategrey", "black")
    ggplot(data, aes(x = x, y = y)) +
      geom_tile(aes(fill = factor(c)), colour = "white") +
      scale_fill_manual(values = colors, name = "Colours") +
      coord_equal()
    

Notas

Para apreciar lo que sucede cuando creamos el gráfico original con geom_point, reducimos el tamaño del data frame, a 10 x 10. Lo representamos seguido de las dos alternativas propuestas.

  • Nuevo data frame
  • l = 100
    a = seq(0, 1, 1 / (l - 1))
    x = rep(a, each = length(a))
    y = rep(a, length(a))
    k = length(x)
    c = sample(1:10, k, replace = TRUE)
    data <- data.frame(x, y, c)
    
  • Gráfico original
  • ggplot(data, aes(x = x, y = y)) + geom_point(shape = 15, color = c)
    
  • Alternativa 1
  • ggplot(data, aes(x = x, y = y, fill = c)) + geom_tile(colour = "white")
    
  • Alternativa 2
  • colors<-c("peachpuff", "yellow", "orange", "orangered", "red", 
              "darkred","firebrick", "royalblue", "darkslategrey", "black")
    ggplot(data, aes(x = x, y = y)) +
      geom_tile(aes(fill = factor(c)), colour = "white") +
      scale_fill_manual(values = colors, name = "Colours") +
      coord_equal()
    

Referencias

2018-01-16

Abrir simultáneamente múltiples hipervículos en Excel


Problema

Queremos abrir simultáneamente múltiples hipervículos en Excel.

Solución

  1. Abrimos el Editor de Microsoft Visual Basic: Alt+F11.
  2. Creamos la siguiente función en un módulo.
    • Sub Abrir_Hipervinculos()
          On Error Resume Next
          Dim hl As Hyperlink
          For Each hl In Selection.Hyperlinks
              hl.Follow
          Next hl
      End Sub
      
  3. Seleccionamos el rango de celdas que contiene los enlaces y presionamos Alt+F8.
  4. Tecleamos Alt+F8 y presionamos Ejecutar.
  5. Los enlaces se abrirán en el navegador predeterminado. Si alguna celda está vacía, o contiene un hipervínculo no válido, no se abrirán y no generará error pues hemos especificado On Error Resume Next.

Entradas relacionadas

Referencias

2018-01-14

Gráfico y tabla subyacente en una misma página en R

Problema

Queremos mostrar un gráfico junto con su tabla subyacente en una misma página en R.

  • Datos y gráfico original
df <- data.frame(
  group = c("A", "A", "A", "B", "B", "B"),
  x = c(1, 2, 3, 1, 2, 3),
  y = c(2, 5, 7, 7, 5, 3)
)
library(ggplot2)
p <- ggplot(data = df, aes(
  x = x,
  y = y,
  group = group,
  color = group
)) +
  geom_line() +
  geom_point()

Solución

Empleamos el paquete gridExtra, con tableGrob creamos la tabla y con grid.arrange ordenamos los dos elementos, la tabla y el gráfico, en una misma página.

library(gridExtra)
tbl <- tableGrob(t(df), rows = NULL , theme = ttheme_minimal())
grid.arrange(p,
             tbl,
             nrow = 2,
             as.table = TRUE,
             heights = c(3, 1))

Referencias

2018-01-12

Filtrar entre dos fechas con dplyr

Problema

Queremos filtra entre dos fechas utilizando el paquete dplyr.

    Patch       Date Prod_DL
1    BVG1   9/4/2015    3.43
2   BVG11  9/11/2015    3.49
3   BVG12  9/18/2015    3.45
4   BVG13  12/6/2015    3.57
5   BVG14 12/13/2015    3.43
6   BVG15 12/20/2015    3.47
  • Datos
df <- read.table(
  text = "Patch,Date,Prod_DL
  BVG1,9/4/2015,3.43
  BVG11,9/11/2015,3.49
  BVG12,9/18/2015,3.45
  BVG13,12/6/2015,3.57
  BVG14,12/13/2015,3.43
  BVG15,12/20/2015,3.47",
  sep = ",",
  stringsAsFactors = FALSE,
  header = TRUE,
  row.names = NULL
)

Solución

  • Alternativa 1
  • Formateamos la fecha correctamente y filtramos entre las dos fechas deseadas.

    library("dplyr")
    df$Date <-as.Date(df$Date,"%m/%d/%Y")
    df %>%
      select(Patch, Date, Prod_DL) %>%
      filter(Date > "2015-09-04" & Date < "2015-09-18")
    
        Patch       Date Prod_DL
    1   BVG11 2015-09-11    3.49
    
  • Alternativa 2
  • Formateamos la fecha correctamente y empleamos la función between: 'This is a shortcut for x >= left & x <= right, implemented efficiently in C++ for local values, and translated to the appropriate SQL for remote tables.'. Por tanto es necesario ajustar las fechas pues incluye ambas fechas en los dos lados. Necesitamos usar as.Date, explicación aquí.

    df$Date <- as.Date(df$Date, "%m/%d/%Y")
    df %>% 
      select(Patch, Date, Prod_DL) %>%
      filter(between(Date, as.Date("2015-09-05"), as.Date("2015-09-17")))
    
        Patch       Date Prod_DL
    1   BVG11 2015-09-11    3.49
    

    Referencias

    Nube de datos