¿Cómo se reordenan las columnas en un dataframe?

¿Cómo se puede cambiar esta entrada (con la secuencia: tiempo, entrada, salida, archivos):

Time In Out Files 1 2 3 4 2 3 4 5 

A esta salida (con la secuencia: time, out, in, files)?

 Time Out In Files 1 3 2 4 2 4 3 5 

Aquí están los datos ficticios de R:

 table <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5)) table ## Time In Out Files ##1 1 2 3 4 ##2 2 3 4 5 

Su dataframe tiene cuatro columnas como so df[,c(1,2,3,4)] . Tenga en cuenta que la primera coma significa mantener todas las filas, y la 1,2,3,4 se refiere a las columnas.

Para cambiar el orden como en la pregunta anterior, haga df2[,c(1,3,2,4)]

Si desea generar este archivo como un csv, write.csv(df2, file="somedf.csv")

 # reorder by column name data <- data[c("A", "B", "C")] #reorder by column index data <- data[c(1,3,2)] 

También puede usar la función de subconjunto:

 data <- subset(data, select=c(3,2,1)) 

Debería usar mejor el operador [] como en las otras respuestas, pero puede ser útil saber que puede hacer un subconjunto y una operación de reordenación de columna en un solo comando.

Actualizar:

También puede usar la función de selección del paquete dplyr:

 data = data %>% select(Time, out, In, Files) 

No estoy seguro de la eficacia, pero gracias a la syntax de dplyr, esta solución debería ser más flexible, especialmente si tienes muchas columnas. Por ejemplo, lo siguiente reordenará las columnas del conjunto de datos mtcars en el orden opuesto:

 mtcars %>% select(carb:mpg) 

Y lo siguiente reordenará solo algunas columnas y descartará otras:

 mtcars %>% select(mpg:disp, hp, wt, gear:qsec, starts_with('carb')) 

Obtenga más información sobre la syntax de selección de dplyr .

Como se menciona en este comentario , las sugerencias estándar para reordenar columnas en un data.frame son generalmente engorrosas y propensas a errores, especialmente si tiene muchas columnas.

Esta función permite reorganizar columnas por posición: especifique un nombre de variable y la posición deseada, y no se preocupe por las otras columnas.

 ##arrange df vars by position ##'vars' must be a named vector, eg c("var.name"=1) arrange.vars <- function(data, vars){ ##stop if not a data.frame (but should work for matrices as well) stopifnot(is.data.frame(data)) ##sort out inputs data.nms <- names(data) var.nr <- length(data.nms) var.nms <- names(vars) var.pos <- vars ##sanity checks stopifnot( !any(duplicated(var.nms)), !any(duplicated(var.pos)) ) stopifnot( is.character(var.nms), is.numeric(var.pos) ) stopifnot( all(var.nms %in% data.nms) ) stopifnot( all(var.pos > 0), all(var.pos <= var.nr) ) ##prepare output out.vec <- character(var.nr) out.vec[var.pos] <- var.nms out.vec[-var.pos] <- data.nms[ !(data.nms %in% var.nms) ] stopifnot( length(out.vec)==var.nr ) ##re-arrange vars by position data <- data[ , out.vec] return(data) } 

Ahora la solicitud del OP es tan simple como esto:

 table <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5)) table ## Time In Out Files ##1 1 2 3 4 ##2 2 3 4 5 arrange.vars(table, c("Out"=2)) ## Time Out In Files ##1 1 3 2 4 ##2 2 4 3 5 

Para intercambiar columnas de Time y Files , puede hacer esto:

 arrange.vars(table, c("Out"=2, "Files"=1, "Time"=4)) ## Files Out In Time ##1 4 3 2 1 ##2 5 4 3 2 

Quizás es una coincidencia que el orden de las columnas que desea tenga nombres de columnas en orden alfabético descendente. Dado que ese es el caso, puedes hacer lo siguiente:

 df<-df[,order(colnames(df),decreasing=TRUE)] 

Eso es lo que uso cuando tengo archivos grandes con muchas columnas.

Si puede usar el paquete data.table, esto proporciona una forma buena y compacta

Cómo reordenar columnas data.table (sin copiar)

 setcolorder(DT,myOrder) 

Una solución tidyverse es usar select como en:

 select(table, "Time", "Out", "In", "Files") 

Las tres respuestas mejor calificadas tienen una debilidad.

Si su dataframe se ve así

 df <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5)) > df Time In Out Files 1 1 2 3 4 2 2 3 4 5 

entonces es una solución pobre de usar

 > df2[,c(1,3,2,4)] 

Hace el trabajo, pero acaba de introducir una dependencia en el orden de las columnas en su entrada.

Este estilo de progtwigción frágil debe ser evitado.

La nomenclatura explícita de las columnas es una mejor solución

 data[,c("Time", "Out", "In", "Files")] 

Además, si tiene la intención de volver a utilizar su código en un entorno más general, puede simplemente

 out.column.name <- "Out" in.column.name <- "In" data[,c("Time", out.column.name, in.column.name, "Files")] 

que también es bastante bueno porque aísla completamente los literales. Por el contrario, si usa dplyr's select

 data <- data %>% select(Time, out, In, Files) 

entonces estarías configurando a aquellos que leerán tu código más tarde, incluido tú mismo, por un poco de engaño. Los nombres de columna se utilizan como literales sin aparecer en el código como tal.

El único que he visto funcionar bien es desde aquí .

  shuffle_columns <- function (invec, movecommand) { movecommand <- lapply(strsplit(strsplit(movecommand, ";")[[1]], ",|\\s+"), function(x) x[x != ""]) movelist <- lapply(movecommand, function(x) { Where <- x[which(x %in% c("before", "after", "first", "last")):length(x)] ToMove <- setdiff(x, Where) list(ToMove, Where) }) myVec <- invec for (i in seq_along(movelist)) { temp <- setdiff(myVec, movelist[[i]][[1]]) A <- movelist[[i]][[2]][1] if (A %in% c("before", "after")) { ba <- movelist[[i]][[2]][2] if (A == "before") { after <- match(ba, temp) - 1 } else if (A == "after") { after <- match(ba, temp) } } else if (A == "first") { after <- 0 } else if (A == "last") { after <- length(myVec) } myVec <- append(temp, values = movelist[[i]][[1]], after = after) } myVec } 

Use esto:

 new_df <- iris[shuffle_columns(names(iris), "Sepal.Width before Sepal.Length")] 

Funciona de maravilla.

    Intereting Posts