2015-08-30

¿Cómo seleccionar todas las columnas de un data frame con dplyr?

Title

Problema

Queremos seleccionar todas las columnas de un data frame con el paquete dplyr.

Respondemos a una duda planteada en stackoverflow. Otra cuestión sería por qué razón querríamos hacer algo así en lugar simplemente utilizar todo el data frame tecleando su nombre.

Soluciones

select(iris, everything())
# Usando el operador %>%
iris %>% select(everything())
rename(iris)

Notas

select( ) selecciona solamente aquellas variables que indiquemos; rename( ) selecciona todas las variables. Si empleamos select, introducimos everything( ) que es una de las funciones especiales que solamente funcionan dentro de select.

Resultado

Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1           5.1         3.5          1.4         0.2  setosa
2           4.9         3.0          1.4         0.2  setosa
3           4.7         3.2          1.3         0.2  setosa
4           4.6         3.1          1.5         0.2  setosa
5           5.0         3.6          1.4         0.2  setosa
6           5.4         3.9          1.7         0.4  setosa
7           4.6         3.4          1.4         0.3  setosa
8           5.0         3.4          1.5         0.2  setosa
9           4.4         2.9          1.4         0.2  setosa
10          4.9         3.1          1.5         0.1  setosa
..          ...         ...          ...         ...     ...

Referencias

2015-08-24

Seleccionar sólo las columnas que contengan NA en R

Title

Problema

De un data frame deseamos seleccionar aquellas columnas que contengan algún valor NA.

i3 <- c(1, 1, 1, 1, 2, 2)
i2 <- c(NA, 1, 1, 1, 2, 2)
i1 <- c(1, NA, 2, 4, 5, 3)
newdat1 <- data.frame(i3, i2, i1)
newdat1
  i3 i2 i1
1  1 NA  1
2  1  1 NA
3  1  1  2
4  1  1  4
5  2  2  5
6  2  2  3

Soluciones

De mayor a menor eficiencia.

  • sapply
  • newdat1[, sapply(newdat1, anyNA), drop = FALSE]
    
      i2 i1
    1 NA  1
    2  1 NA
    3  1  2
    4  1  4
    5  2  5
    6  2  3
    
  • colSums
  • newdat1[,is.na(colSums(newdat1))]
    
  • complete.cases
  • Mi alternativa propuesta. Transponemos el data frame y con complete.cases obtenemos un índice lógico (TRUE, FALSE, FALSE) con las columnas tienen algún NA. Como son aquellas que deseamos con incluir, con el operador ! invertimos el vector lógico anterior (FALSE, TRUE, TRUE) quedándonos con la segunda y tercera columnas.

    newdat1[!complete.cases(t(newdat1))]
    
  • apply
  • apply(newdat1, 2, function(x) sum(is.na(x)) == 0 )
    

    Referencias

    2015-08-21

    Cómo eliminar el espacio entre los ejes y el área del gráfico en ggplot2

    Title

    Problema

    Deseamos eliminar el espacio que existe entre los ejes y el área del gráfico (plotting area). Como se aprecia en el gráfico de más abajo, hay un espacio entre los ejes y el área gris que no comienza en las coordenadas (0, 0).

    # Datos
    set.seed(0)
    the.df <- data.frame( x = rnorm(800, 50, 10), group = rep(letters[1:8], each = 100))
    
    
    # Gráfico original
    p <- ggplot(the.df) + 
      stat_density(aes(x = x, linetype = group), geom = "line", position = "identity") +
      xlim(10, 90) + ylim(0, 0.06) +
      scale_linetype_manual(values = c("11", "12", "13", "14", "21", "22", "23", "24")) +
      geom_segment(aes(x = 10, y = 0, xend = 90, yend = 0)) +
      geom_segment(aes(x = 10, y = 0, xend = 10, yend = 0.06))
    

    Solución

    Dos opciones:

  • Scale continuous y expand
  • En lugar de xlim(10, 90) + ylim(0, 0.06) empleamos escalas continuas, scale_x_continuous y scale_x_continuous y dentro incluimos expand = c(0, 0).

    p <- ggplot(the.df) + 
      stat_density(aes(x = x, linetype = group), geom = "line", position = "identity") +
      scale_linetype_manual(values = c("11", "12", "13", "14", "21", "22", "23", "24")) +
      scale_x_continuous(limits=c(10, 90), expand = c(0, 0)) +
      scale_y_continuous(limits=c(0, 0.06), expand = c(0, 0)) +
      geom_segment(aes(x = 10, y = 0, xend = 90, yend = 0)) +
      geom_segment(aes(x = 10, y = 0, xend = 10, yend = 0.06))
    
  • coord_cartesian
  • Usar coord_cartesian en lugar de scale_x_continuous y scale_x_continuous.

    p <- ggplot(the.df) + 
      stat_density(aes(x = x, linetype = group), geom = "line", position = "identity") +
      scale_linetype_manual(values = c("11", "12", "13", "14", "21", "22", "23", "24")) +
      geom_segment(aes(x = 10, y = 0, xend = 90, yend = 0)) +
      geom_segment(aes(x = 10, y = 0, xend = 10, yend = 0.06))+
      coord_cartesian(xlim = c(10, 90), ylim = c(0, .06))
    

    Otro ejemplo

    uniq <- structure(list(year = c(1986L, 1987L, 1991L, 1992L, 1993L, 1994L, 1995L, 1996L, 1997L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 1986L, 1987L, 1991L, 1992L, 1993L, 1994L, 1995L, 1996L, 1997L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L, 1986L, 1987L, 1991L, 1992L, 1993L, 1994L, 1995L, 1996L, 1997L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L, 2009L, 2010L, 2011L, 2012L, 2013L, 2014L), uniq.loc = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("u.1", "u.2", "u.3"), class = "factor"), uniq.n = c(1, 1, 1, 2, 5, 4, 2, 16, 16, 10, 15, 14, 8, 12, 20, 11, 17, 30, 17, 21, 22, 19, 34, 44, 56, 11, 0, 0, 3, 3, 7, 17, 12, 21, 18, 10, 12, 9, 7, 11, 25, 14, 11, 17, 12, 24, 59, 17, 36, 50, 59, 12, 0, 0, 0, 1, 4, 6, 3, 3, 9, 3, 4, 2, 5, 2, 12, 6, 8, 8, 3, 2, 9, 5, 20, 7, 10, 8), uniq.p = c(100, 100, 25, 33.3, 31.2, 14.8, 11.8, 40, 37.2, 43.5, 48.4, 56, 40, 48, 35.1, 35.5, 47.2, 54.5, 53.1, 44.7, 24.4, 46.3, 37.8, 43.6, 44.8, 35.5, 0, 0, 75, 50, 43.8, 63, 70.6, 52.5, 41.9, 43.5, 38.7, 36, 35, 44, 43.9, 45.2, 30.6, 30.9, 37.5, 51.1, 65.6, 41.5, 40, 49.5, 47.2, 38.7, 0, 0, 0, 16.7, 25, 22.2, 17.6, 7.5, 20.9, 13, 12.9, 8, 25, 8, 21.1, 19.4, 22.2, 14.5, 9.4, 4.3, 10, 12.2, 22.2, 6.9, 8, 25.8)), .Names = c("year", "uniq.loc", "uniq.n", "uniq.p"), class = "data.frame", row.names = c(NA, -78L))
    
  • Gráfico original
  • ggplot(data = uniq) + 
      geom_area(aes(x = year, y = uniq.p, fill = uniq.loc), stat = "identity", position = "stack") +
      scale_x_continuous(limits=c(1986,2014)) +
      scale_y_continuous(limits=c(0,101)) +
      theme_bw()
    
  • Gráfico sin espacios
  • # Scale_x_continuous y expand = c(0, 0)
    ggplot(data = uniq) + 
      geom_area(aes(x = year, y = uniq.p, fill = uniq.loc), stat = "identity", position = "stack") +
      scale_x_continuous(limits=c(1986,2014), expand = c(0, 0)) +
      scale_y_continuous(limits=c(0,101), expand = c(0, 0)) +
      theme_bw() + theme(panel.grid=element_blank(), panel.border=element_blank())
    
     # coord_cartesian
    ggplot(data = uniq) +  
      geom_area(aes(x = year, y = uniq.p, fill = uniq.loc), stat = "identity", position = "stack") +  
      coord_cartesian(xlim = c(1986,2014), ylim = c(0,101))+
      theme_bw() + theme(panel.grid=element_blank(), panel.border=element_blank())
    

    Referencias

    2015-08-19

    Estadísticas descriptivas en Excel

    Title Deseamos generar estadísticas descriptivas para una tabla de datos en Excel. Utilizaremos la herramienta para el análisis de datos: Estadística descriptiva.

    Partimos de los datos iris, importados desde R, también disponibles aquí.

    Pasos

    1. En la ficha Datos, dentro del grupo Análisis clic en Análisis de datos.
    2. En el cuadro de diálogo Análisis de datos, clic en la herramienta Estadística descriptiva y clic en Aceptar.
    3. Seleccionamos el rango de entrada, activamos la casilla Rótulos en la primera fila si nuestros datos tienen encabezados. Solamente admite un rango numérico
    4. Seleccionamos el rango de salida, por defecto será en una nueva hoja
    5. Marcamos la casilla Resumen de estadísticas y aquellas otros indicadores deseados

    Resultado

    Obtendremos una columna con las estadísticas descriptivas por columna. Puedes comparar los resultados con los que obtuvimos con R.

    Entradas relacionadas

    2015-08-17

    Campo calculado entero en lugar de numérico usando sqldf en R

    Title

    Problema

    Al usar sqldf, al contrario que R, cuando dividimos un número entero entre otro, devuelve un número entero en lugar de uno real. Es decir:

  • R
  • 1/5
    
    [1] 0.2
    
  • sqldf
  • library(sqldf)
    sqldf("SELECT 1/5")
    
      1/5
    1   0
    

    Solución

    Multiplicamos el numerador o el denominador por 1.0 o convertimos uno de los números a real.

    sqldf("SELECT (1.0*1)/5") # Numerador
    sqldf("SELECT 1/(5*1.0)") # Denominador
    sqldf("SELECT CAST(1 AS REAL)/5") # Convertimos numerador
    sqldf("SELECT 1/CAST(5 AS REAL)") # Convertimos denominador
    

    Otro ejemplo

    Veamos un ejemplo práctico que vimos en esta entrada. Calcularemos el porcentaje del total de la columna del siguiente data frame.

        x freq
    1 Jan    7
    2 Feb   23
    3 Mar   86
    4 Apr  281
    
    Código para crear el data frame anterior:

    df <- read.table(text = "x    freq
                            Jan   7
                            Feb   23
                            Mar   86
                            Apr   281", 
                            header =TRUE)
    
  • Solución
  • sqldf('SELECT x, freq, (freq*1.0)/(SELECT SUM(freq) 
          FROM df) AS prob
          FROM df')
    
        x freq       prob
    1 Jan    7 0.01763224
    2 Feb   23 0.05793451
    3 Mar   86 0.21662469
    4 Apr  281 0.70780856
    

    Entradas relacionadas

    2015-08-13

    Analizar subgrupos de un data frame con la función aggregate en R

    Title

    Problema

    Deseamos calcular para varios grupos de un data frame diferentes indicadores. En nuestro ejemplo usaremos los datos de TootGrowth.

    [,1] len numeric Tooth length
    [,2] supp factor Supplement type (VC or OJ).
    [,3] dose numeric Dose in milligrams/day
    
    Calcularemos la media y la mediana de la longitud de los dientes (len) para cada uno de los suplementos (supp) de vitaminas (VC o OJ).

    Solución

    Empleamos la función aggregate.

    aggregate(len ~ supp, data = ToothGrowth, 
              FUN = function(x) c(media =mean(x), mediana = median(x)))
    
    Empleamos la estructura de fórmula y ~ x, donde y es la variable numérica de la que queremos el resultado y x es la variable por la que agruparemos.

    Resultado

      supp len.media len.mediana
    1   OJ  20.66333    22.70000
    2   VC  16.96333    16.50000
    

    Más niveles de agrupación

    Si deseamos añadir el nivel de agrupación por dosis (dose).

    aggregate(len ~ supp + dose, data = ToothGrowth, 
              FUN = function(x) c(media =mean(x), mediana = median(x)))
    
     supp dose len.media len.mediana
    1   OJ  0.5     13.23       12.25
    2   VC  0.5      7.98        7.15
    3   OJ  1.0     22.70       23.45
    4   VC  1.0     16.77       16.50
    5   OJ  2.0     26.06       25.95
    6   VC  2.0     26.14       25.95
    

    Más variables numéricas

    Utilizamos ahora el conjunto de datos iris.

    aggregate(cbind(Sepal.Length, Sepal.Width) ~ Species, data = iris, 
              FUN = function(x) c(media =mean(x), mediana = median(x)))
    
         Species Sepal.Length.media Sepal.Length.mediana Sepal.Width.media
    1     setosa              5.006                5.000             3.428
    2 versicolor              5.936                5.900             2.770
    3  virginica              6.588                6.500             2.974
      Sepal.Width.mediana
    1               3.400
    2               2.800
    3               3.000
    
    Es necesario emplear la función cbind, de lo contrario, nos sumará los resultados de las variables numéricas:
    aggregate(Sepal.Length + Sepal.Width~ Species, data = iris, 
              FUN = function(x) c(media = mean(x), mediana = median(x)))
    
         Species Sepal.Length + Sepal.Width.media Sepal.Length + Sepal.Width.mediana
    1     setosa                            8.434                              8.450
    2 versicolor                            8.706                              8.600
    3  virginica                            9.562                              9.600
    

    Entradas relacionadas

    2015-08-11

    Porcentaje del total de la columna mediante subconsulta en Ms Access

    Title

    Problema

    Queremos calcular el porcentaje del total de la columna mediante subconsulta. Anteriormente vimos como calcular el porcentaje del total de la columna mediante la función DSuma.

    Partimos de la siguiente tabla sacada de la anterior entrada.

    Solución

  • En SQL
  • SELECT Tabla1.x, Tabla1.freq, [freq]/(SELECT Sum(Tabla1.freq) FROM Tabla1) AS prob
    FROM Tabla1
    GROUP BY Tabla1.x, Tabla1.freq;
    
  • En Access
  • Creamos la siguiente consulta.

    1. Añadimos los dos campos x y freq
    2. En la ficha Diseño, en el grupo Mostrar u ocultar, clic en Totales (símbolo del sumatorio, sigma).
    3. Campo calculado prob con la expresión en la que introducimos la subconsulta:
    4. prob: [freq]/(SELECT Sum(Tabla1.freq) FROM Tabla1)
      
  • Resultado
  • Para mostrar el formato anterior, estándar con 4 decimales, en la hoja de propiedades del campo prob seleccionamos las propiedades mencionadas.

    Referencias

    Nube de datos