sort ordenar multiple how data columns column based according r order dataframe

ordenar - ¿Cómo se reordenan las columnas en un marco de datos?



sort order r (9)

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

Esta función permite reorganizar las 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, e.g. 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 se vuelve 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 adicionalmente las 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

¿Cómo cambiaría uno 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: tiempo, salida, entrada, archivos)?

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


El único que he visto funciona bien es desde here .

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 así:

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

Funciona de maravilla.


Las three top-rated answers tienen una debilidad.

Si su marco de datos 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 mala solución para 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 programación frágil debe ser evitado.

El nombramiento explícito de las columnas es una mejor solución.

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

Además, si pretende reutilizar su código en una configuración más general, simplemente puede

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

lo cual 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 las columnas se utilizan como literales sin aparecer en el código como tal.



Su marco de datos tiene cuatro columnas como df[,c(1,2,3,4)] . Tenga en cuenta que la primera coma significa mantener todas las filas, y el 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")


Tal vez sea una coincidencia que el orden de columna que desea tenga nombres de columna en orden alfabético descendente. Ya que ese es el caso, podrías hacer:

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

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


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

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

Debería utilizar 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 columnas 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 eficiencia, pero gracias a la sintaxis de dplyr, esta solución debería ser más flexible, especialmente si tiene muchas columnas. Por ejemplo, lo siguiente reorganizará 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''))

Lea más sobre la sintaxis selecta de dplyr .


Una solución tidyverse es usar select como en:

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


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