Estoy tratando de subconjunto de un marco de datos, donde puedo obtener múltiples tramas de datos basadas en columnas múltiples valores. Aquí está mi ejemplo

>df
  v1   v2   v3   v4   v5
   A    Z    1    10   12
   D    Y    10   12    8
   E    X    2    12   15
   A    Z    1    10   12
   E    X    2    14   16

El resultado esperado es algo como esto, donde yo soy la división de esta estructura de datos en múltiples marcos de datos basadas en columnas v1 y v2

>df1
 v3   v4   v5
  1   10   12
  1   10   12
>df2
 v3   v4   v5
 10   12    8
>df3
 v3   v4   v5
 2    12   15
 2    14   16

He escrito un código en el que está trabajando ahora, pero no creo que la mejor manera de hacerlo. Debe haber una mejor manera de hacerlo. Suponiendo tab es el de datos.fotograma de tener los datos iniciales. Aquí está mi código:

v1Factors<-levels(factor(tab$v1))
v2Factors<-levels(factor(tab$v2))

for(i in 1:length(v1Factors)){
  for(j in 1:length(v2Factors)){
    subsetTab<-subset(tab, v1==v1Factors[i] & v2==v2Factors[j], select=c("v3", "v4", "v5"))
    print(subsetTab)
  }
}

Puede alguien sugerir un método mejor para hacer lo anterior?

  • ¿Quieres volver a utilizar esos dataframes, o simplemente imprimirlas agrupados por esas columnas?
  • Quiero volver a usarlos…. quiere el trazado de gráficos en los marcos de datos.

2 Comentarios

  1. 31

    Usted está buscando para split

    split(df, with(df, interaction(v1,v2)), drop = TRUE)
    $E.X
      v1 v2 v3 v4 v5
    3  E  X  2 12 15
    5  E  X  2 14 16
    
    $D.Y
      v1 v2 v3 v4 v5
    2  D  Y 10 12  8
    
    $A.Z
      v1 v2 v3 v4 v5
    1  A  Z  1 10 12

    Como se señaló en los comentarios

    cualquiera de los siguientes sería el trabajo

    library(microbenchmark)
    microbenchmark(
                    split(df, list(df$v1,df$v2), drop = TRUE), 
                   split(df, interaction(df$v1,df$v2), drop = TRUE),
                   split(df, with(df, interaction(v1,v2)), drop = TRUE))
    
    
    Unit: microseconds
                                                      expr      min        lq    median       uq      max neval
                split(df, list(df$v1, df$v2), drop = TRUE) 1119.845 1129.3750 1145.8815 1182.119 3910.249   100
         split(df, interaction(df$v1, df$v2), drop = TRUE)  893.749  900.5720  909.8035  936.414 3617.038   100
     split(df, with(df, interaction(v1, v2)), drop = TRUE)  895.150  902.5705  909.8505  927.128 1399.284   100

    Parece interaction es ligeramente más rápido (probablemente debido al hecho de que la f = list(...) se acaba de convertir en una interacción dentro de la función)


    Editar

    Si sólo desea utilizar el subconjunto de datos.marcos, a continuación, me permito sugerir el uso de datos.tabla para facilitar la codificación

    library(data.table)
    
    dt <- data.table(df)
    dt[, plot(v4, v5), by = list(v1, v2)]
    • split puede tomar una lista de f, en lugar de tener que utilizar interaction. No estoy seguro de que es más eficiente sin embargo.
    • He añadido un punto de referencia.
    • Gracias por los puntos de referencia. En ese caso, @Arun, el truco de la (with(df, split(df, f = do.call(paste, df[1:2]))) probablemente sería aún más rápido! Y, que no cree innecesario niveles que deben ser descartados.
    • Gracias por la pronta respuesta. Su sugerencia definitivamente parece que funciona. Pero no se exactamente que obtener la diferencia de los múltiples métodos que se han sugerido.
    • Parece interacción crea todas las combinaciones posibles de los niveles. Pero cuando me encontré con el ejemplo mencionado anteriormente, no de crear todos los niveles. Por qué así?? En el conjunto de datos reales, es la creación de…. Es incomprensible para mí.
  2. 6

    Ahora hay también nest() de tidyr que es bastante agradable.

    library(tidyr)
    nestdf <- df %>% nest(v3:v5)
    nestdf$data
    
    > nestdf$data
    [[1]]
    # A tibble: 2 × 3
         v3    v4    v5
      <int> <int> <int>
    1     1    10    12
    2     1    10    12
    
    [[2]]
    # A tibble: 1 × 3
         v3    v4    v5
      <int> <int> <int>
    1    10    12     8
    
    [[3]]
    # A tibble: 2 × 3
         v3    v4    v5
      <int> <int> <int>
    1     2    12    15
    2     2    14    16

    De acceso a cada tibbles con nestdf$data[1] y así sucesivamente.

Dejar respuesta

Please enter your comment!
Please enter your name here