Mostrando entradas con la etiqueta formato largo a ancho. Mostrar todas las entradas
Mostrando entradas con la etiqueta formato largo a ancho. Mostrar todas las entradas

2017-05-26

Convertir de formato largo a ancho con sqldf en R

Problema

Deseamos transformar un data frame de formato largo a ancho. Partimos del siguiente data frame:

        name numbers      value
1  firstName       1 -0.3016990
2  firstName       2  0.4782982
3  firstName       3 -0.3274221
4  firstName       4  0.8950889
5 secondName       1 -1.3476795
6 secondName       2 -0.4671124
7 secondName       3 -1.0883609
8 secondName       4  1.8702156

Y queremos llegar a este otro. Con name como nombres de filas, cuatro columnas basadas en numbers y como valores, values.

                  X1         X2         X3        X4
firstName  -0.301699  0.4782982 -0.3274221 0.8950889
secondName -1.347680 -0.4671124 -1.0883609 1.8702156

  • Datos originales
  • dat1 <- structure(list(name = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
    2L), .Label = c("firstName", "secondName"), class = "factor"), 
        numbers = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), value = c(-0.301698990300544, 
        0.47829821507312, -0.327422119821659, 0.895088877410118, 
        -1.3476795169412, -0.467112422933039, -1.08836089961649, 
        1.87021564288651)), .Names = c("name", "numbers", "value"
    ), row.names = c(NA, -8L), class = "data.frame")
    

    Solución

  • Paquete sqldf
  • Empleamos la sintaxis de SQL de sqldf para transformar o pivotar de formato largo a ancho. Empleamos MAX(CASE WHEN.

    library(sqldf)
    sqldf('SELECT name,
          MAX(CASE WHEN numbers = 1 THEN value ELSE NULL END) x1, 
          MAX(CASE WHEN numbers = 2 THEN value ELSE NULL END) x2,
          MAX(CASE WHEN numbers = 3 THEN value ELSE NULL END) x3,
          MAX(CASE WHEN numbers = 4 THEN value ELSE NULL END) x4
          FROM dat1
          GROUP BY name')
    
                      X1         X2         X3        X4
    firstName  -0.301699  0.4782982 -0.3274221 0.8950889
    secondName -1.347680 -0.4671124 -1.0883609 1.8702156
    

    Entradas relacionadas

    Referencias

    2016-05-18

    Convertir de formato largo a ancho con la función unstack en R

    Title

    Problema

    Deseamos transformar un data frame de formato largo a ancho. Partimos del siguiente data frame:

            name numbers      value
    1  firstName       1 -0.3016990
    2  firstName       2  0.4782982
    3  firstName       3 -0.3274221
    4  firstName       4  0.8950889
    5 secondName       1 -1.3476795
    6 secondName       2 -0.4671124
    7 secondName       3 -1.0883609
    8 secondName       4  1.8702156
    

    Y queremos llegar a este otra. Con name como nombres de filas, cuatro columnas basadas en numbers y como valores, values.

                      X1         X2         X3        X4
    firstName  -0.301699  0.4782982 -0.3274221 0.8950889
    secondName -1.347680 -0.4671124 -1.0883609 1.8702156
    

  • Datos originales
  • dat1 <- structure(list(name = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
    2L), .Label = c("firstName", "secondName"), class = "factor"), 
        numbers = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), value = c(-0.301698990300544, 
        0.47829821507312, -0.327422119821659, 0.895088877410118, 
        -1.3476795169412, -0.467112422933039, -1.08836089961649, 
        1.87021564288651)), .Names = c("name", "numbers", "value"
    ), row.names = c(NA, -8L), class = "data.frame")
    

    Solución

  • Paquete base
  • Empleamos la función unstack para transformar de formato largo a ancho. En el primer argumento, indicamos el data frame, en el argumento form una fórmula, a la izquierda de ~ el vector que deseamos desapilar —unstack— (value) y a la derecha los grupos que queremos crear (numbers). Finalmente, renombramos los nombres de las filas.

    df <- unstack(dat1, form = value ~ numbers)
    rownames(df) <- unique(dat1$name)
    df
    
                      X1         X2         X3        X4
    firstName  -0.301699  0.4782982 -0.3274221 0.8950889
    secondName -1.347680 -0.4671124 -1.0883609 1.8702156
    

    Entradas relacionadas

    Referencias

    2015-11-11

    Convertir de formato largo a ancho usando una función de agregación en R

    Title

    Problema

    Deseamos transformar un data frame de formato largo a ancho agrupando por la suma de los valores de una de las variables. Es decir pasar de esta tabla,

     V1 V3     V2
    1  5 10    low
    2  5  3    low
    3  5  6 medium
    4 45 10    low
    5 45  3    low
    6 77  1   high
    

    A esta otra, donde mantenemos la columna V1, la columna V2 contiene los nombres de las nuevas columnas, y la columna V3 será la variable que almacenará los valores y que agregaremos sumando.

      V1 low medium high
    1  5  13      6    0
    2 45  13      0    0
    3 77   0      0    1
    

  • Datos originales
  • V1 <- c(5,5,5,45,45,77)  
    V2 <- c("low", "low", "medium", "low", "low", "high")  
    V3 <- c(10,3,6,10,3,1)  
    df <- as.data.frame(cbind(V1,V3,V2))
    

    Soluciones

    Primero examinamos el data frame que nos dieron.

    str(df)
    'data.frame': 6 obs. of  3 variables:
     $ V1: Factor w/ 3 levels "45","5","77": 2 2 2 1 1 3
     $ V3: Factor w/ 4 levels "1","10","3","6": 2 3 4 2 3 1
     $ V2: Factor w/ 3 levels "high","low","medium": 2 2 3 2 2 1
    

    Las columnas V1 y V3 se han convertido en factores, cuando deberían ser númericas. Si utilizáramos cualquier código obtendríamos el error: Error: ‘sum’ not meaningful for factors. Para solucionarlo, empleamos el siguiente código:

    df <- cbind.data.frame(V1,V3,V2)
    str(df)
    'data.frame': 6 obs. of  3 variables:
     $ V1: num  5 5 5 45 45 77
     $ V3: num  10 3 6 10 3 1
     $ V2: Factor w/ 3 levels "high","low","medium": 2 2 3 2 2 1
    

  • reshape2
  • Empleamos dcast para crear un data frame, usando V3 como la variable valores, e indicamos como función de agregación la suma (sum).

    library(reshape2)
    dcast(df, V1  ~ V2, value.var="V3", fun = sum)
    
      V1 high low medium
    1  5    0  13      6
    2 45    0  13      0
    3 77    1   0      0
    

    Como se puede observar, ordenado las columnas alfabéticamente (high, low y medium) en lugar de respetar el orden de ocurrencia original: low, medium, high.

    dcast(df, V1  ~ factor(V2, levels = unique(V2)), value.var = "V3", sum)
    
    'data.frame': 6 obs. of  3 variables:
     $ V1: num  5 5 5 45 45 77
     $ V3: num  10 3 6 10 3 1
     $ V2: Factor w/ 3 levels "high","low","medium": 2 2 3 2 2 1
    

  • paquete base
  • Empleamos la función xtabs para crear una tabla de contingencia mediante el formato fórmula.

    xtabs(V3 ~ V1 + V2, df)
    
        V2
    V1   high low medium
      5     0  13      6
      45    0  13      0
      77    1   0      0
    

    xtabs(V3 ~ V1 + factor(V2, c("low", "medium", "high")), df)
    
       factor(V2, c("low", "medium", "high"))
    V1   low medium high
      5   13      6    0
      45  13      0    0
      77   0      0    1
    

  • dplyr y tidyr
  • Con dplyr con la función spread, el equivalente a dcast en reshape2.

    df$V2 <- factor(df$V2, levels = c("low", "medium", "high"))
    
    library(tidyr)# Función spread
    library(dplyr)
    
    df %>%
      group_by(V1, V2) %>%
      summarise(sum = sum(V3)) %>%
      spread(V2, sum, fill = 0)
    
    Source: local data frame [3 x 4]
    
         V1   low medium  high
      (dbl) (dbl)  (dbl) (dbl)
    1     5    13      6     0
    2    45    13      0     0
    3    77     0      0     1
    

    Entradas relacionadas

    Referencias

    Nube de datos