Creo que estoy en busca de un análogo de la rbind.fill (en Hadley del plyr paquete) para cbind. Miré, pero no hay cbind.fill.

Lo que yo quiero hacer es la siguiente:

#set these just for this example
one_option <- TRUE
diff_option <- TRUE

return_df <- data.frame()

if (one_option) {
    #do a bunch of calculations, produce a data.frame, for simplicity the following small_df
    small_df <- data.frame(a=1, b=2)
    return_df <- cbind(return_df,small_df)
}

if (diff_option) {
    #do a bunch of calculations, produce a data.frame, for simplicity the following small2_df
    small2_df <- data.frame(l="hi there", m=44)
    return_df <- cbind(return_df,small2_df)
}

return_df

Comprensiblemente, esto produce un error:

Error in data.frame(..., check.names = FALSE) : 
arguments imply differing number of rows: 0, 1

Mi solución actual es sustituir la línea return_df <- data.frame() con return_df <- data.frame(dummy=1) y, a continuación, el código funciona. Entonces me acaba de quitar el maniquí de la return_df al final. Después de agregar el maniquí y la de ejecutar el código anterior, tengo

      dummy a b        l  m
1     1 1 2 hi there 44

A continuación, sólo hay que deshacerse de las maquetas, por ejemplo:

> return_df[,2:ncol(return_df)]
  a b        l  m
1 1 2 hi there 44

Estoy seguro de que me estoy perdiendo una manera más fácil de hacer esto.

edit: supongo que yo no estoy buscando un cbind.llenar, porque eso significaría que un NA valor sería creado después de la cbind, que no es lo que quiero.

  • Sin un conjunto de datos y una salida que se espera es difícil saber exactamente lo que usted desea.
  • estás en lo correcto. Hice describir mi solución actual, pero yo no lo dicen explícitamente lo que el resultado de mi deseo fue. He añadido que la información en la actualidad.
InformationsquelleAutor Xu Wang | 2011-11-01

7 Comentarios

  1. 42

    Aquí un cbind relleno:

    cbind.fill <- function(...){
        nm <- list(...) 
        nm <- lapply(nm, as.matrix)
        n <- max(sapply(nm, nrow)) 
        do.call(cbind, lapply(nm, function (x) 
            rbind(x, matrix(, n-nrow(x), ncol(x))))) 
    }

    Vamos a intentarlo:

    x<-matrix(1:10,5,2)
    y<-matrix(1:16, 4,4)
    z<-matrix(1:12, 2,6)
    
    cbind.fill(x,y)
    cbind.fill(x,y,z)
    cbind.fill(mtcars, mtcars[1:10,])

    Creo que me robaron este desde algún lugar.

    EDITAR ROBÓ DESDE AQUÍ: ENLACE

    • Gracias Tyler. Pero tengo un marco de datos y no de una matriz, y creo que no alteran esta aplicación. También, he editado mi post, porque creo que me equivoqué … no creo que quiero un cbind.llenar, ya que crearía una NA, mientras que no hay nada que desee crear.
    • He editado mi post para que el código funcione en ambos dataframes y matrices. Yo no creo que sea posible a la salida de un dataframe de la desigualdad en las filas. Por definición, un dataframe es una lista de igualdad de longitud n, por lo que un dataframe no en una forma rectangular no sería posible.
    • Wang, hay funciones como.de datos.marco() y como.de la matriz (a), por lo que no es problema de que se tienen datos.marco y no de la matriz.
    • Sólo una rápida sitenote: El código está disponible también en Gist.
  2. 11

    Tiempo, creo que Tyler la solución es directa y los mejores aquí, me acabo de dar a los demás, mediante el uso de rbind.fill() que ya tenemos.

    require(plyr) # requires plyr for rbind.fill()
    cbind.fill <- function(...) {                                                                                                                                                       
      transpoted <- lapply(list(...),t)                                                                                                                                                 
      transpoted_dataframe <- lapply(transpoted, as.data.frame)                                                                                                                         
      return (data.frame(t(rbind.fill(transpoted_dataframe))))                                                                                                                          
    } 
    • Gracias Max! Me gusta tu solución. He de señalar (para los lectores futuros) que esta solución requiere cargar el paquete de plyr, donde Tyler no depende de los paquetes adicionales (creo).
    • Wang, agregó requieren(plyr) declaración.
    • Uno nota es que Max es la solución devuelve una estructura de datos donde como el mío devuelve una matriz. Si realmente quería que la función devuelva una matriz que podría envolver la última línea con as.data.frame()
  3. 4

    Utilizando rowr::cbind.fill

    rowr::cbind.fill(df1,df2,fill = NA)
       A B
    1  1 1
    2  2 2
    3  3 3
    4  4 4
    5  5 5
    6 NA 6
  4. 1

    cbind.na de la qpcR paquete se puede hacer eso.

        install.packages("qpcR")
        library(qpcR)
        qpcR:::cbind.na(1, 1:7)
    • la función cbind.na ya no parece ser una parte del paquete de qpcR
  5. 0

    Me sugieren una modificación de Tyler respuesta. Mi función permite cbind-ción de datos.marcos y/o matrices con vectores sin perder su columna nombres, como sucede en Tyler solución

    cbind.fill <- function(...){
      nm <- list(...) 
      dfdetect <- grepl("data.frame|matrix", unlist(lapply(nm, function(cl) paste(class(cl), collapse = " ") )))
      # first cbind vectors together 
      vec <- data.frame(nm[!dfdetect])
      n <- max(sapply(nm[dfdetect], nrow)) 
      vec <- data.frame(lapply(vec, function(x) rep(x, n)))
      if (nrow(vec) > 0) nm <- c(nm[dfdetect], list(vec))
      nm <- lapply(nm, as.data.frame)
    
      do.call(cbind, lapply(nm, function (df1) 
        rbind(df1, as.data.frame(matrix(NA, ncol = ncol(df1), nrow = n-nrow(df1), dimnames = list(NULL, names(df1))))) )) 
    }
    
    cbind.fill(data.frame(idx = numeric()), matrix(0, ncol = 2), 
               data.frame(qwe = 1:3, rty = letters[1:3]), type = "GOOD", mark = "K-5")
    #       idx V1 V2 qwe rty type mark
    #     1  NA  0  0   1   a GOOD  K-5
    #     2  NA NA NA   2   b GOOD  K-5
    #     3  NA NA NA   3   c GOOD  K-5
  6. 0

    Acabo de encontrar un truco que cuando queremos añadir columnas en un vacío dataframe, sólo rbind que en un primer momento, que cbind más tarde.

        newdf <- data.frame()
        # add the first column
        newdf <- rbind(newdf,data.frame("col1"=c("row1"=1,"row2"=2)))
        # add the second column
        newdf <- cbind(newdf,data.frame("col2"=c("row1"=3,"row2"=4)))
        # add more columns
        newdf <- cbind(newdf,data.frame("col3"=c("row1"=5,"row2"=6)))
        # result
        #     col1 col2 col3
        #row1    1    3    5
        #row2    2    4    6

    No sé por qué, pero a mí me funciona.

  7. 0

    Podríamos añadir id columna, a continuación, utilizar combinación de:

    df1 <- mtcars[1:5, 1:2]
    #                    mpg cyl id
    # Mazda RX4         21.0   6  1
    # Mazda RX4 Wag     21.0   6  2
    # Datsun 710        22.8   4  3
    # Hornet 4 Drive    21.4   6  4
    # Hornet Sportabout 18.7   8  5
    
    df2 <- mtcars[6:7, 3:4]
    #            disp  hp
    # Valiant     225 105
    # Duster 360  360 245
    
    #Add id column then merge
    df1$id <- seq(nrow(df1)) 
    df2$id <- seq(nrow(df2)) 
    
    merge(df1, df2, by = "id", all.x = TRUE, check.names = FALSE)
    #   id  mpg cyl disp  hp
    # 1  1 21.0   6  225 105
    # 2  2 21.0   6  360 245
    # 3  3 22.8   4   NA  NA
    # 4  4 21.4   6   NA  NA
    # 5  5 18.7   8   NA  NA

Dejar respuesta

Please enter your comment!
Please enter your name here