Hoe herschik je kolommen in een dataframe?

Hoe zou men deze invoer veranderen (met de volgorde: tijd, in, uit, bestanden):

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

Naar deze uitgang (met de volgorde: time, out, in, files)?

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

Hier zijn de dummy R-gegevens:

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

Antwoord 1, autoriteit 100%

Je dataframe heeft vier kolommen zoals df[,c(1,2,3,4)].
Merk op dat de eerste komma betekent dat alle rijen behouden blijven, en de 1,2,3,4 verwijst naar de kolommen.

Als u de volgorde wilt wijzigen zoals in de bovenstaande vraag, doet u df2[,c(1,3,2,4)]

Als je dit bestand als csv wilt uitvoeren, doe dan write.csv(df2, file="somedf.csv")


Antwoord 2, autoriteit 49%

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

Antwoord 3, autoriteit 31%

U kunt ook de subset-functie gebruiken:

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

Je kunt beter de operator [] gebruiken zoals in de andere antwoorden, maar het kan handig zijn om te weten dat je een subset en een bewerking voor het opnieuw ordenen van kolommen in één opdracht kunt uitvoeren.

Bijwerken:

U kunt ook de select-functie van het dplyr-pakket gebruiken:

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

Ik ben niet zeker van de efficiëntie, maar dankzij de syntaxis van dplyr zou deze oplossing flexibeler moeten zijn, vooral als je veel kolommen hebt. Het volgende zal bijvoorbeeld de kolommen van de mtcars-dataset in de tegenovergestelde volgorde rangschikken:

mtcars %>% select(carb:mpg)

En het volgende zal slechts enkele kolommen opnieuw ordenen en andere weggooien:

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

Lees meer over dplyr’s select-syntaxis.


Antwoord 4, autoriteit 12%

Zoals vermeld in deze opmerking, zijn de standaardsuggesties voor het opnieuw ordenen van kolommen in een data.framezijn over het algemeen omslachtig en foutgevoelig, vooral als u veel kolommen heeft.

Met deze functie kunt u kolommen op positie herschikken: specificeer een variabelenaam en de gewenste positie, en maak u geen zorgen over de andere kolommen.

##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)
}

Nu wordt het verzoek van de OP zo eenvoudig als dit:

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

Om bovendien Timeen FilesColumns te wisselen, kunt u dit doen:

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

Antwoord 5, Autoriteit 11%

a dplyroplossing (onderdeel van de tidyversePackage Set) is te gebruiken select:

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

Antwoord 6, Autoriteit 7%

Misschien is het toeval dat de gewenste kolomvolgorde kolomnamen heeft in aflopende alfabetische volgorde. Aangezien dat het geval is, kunt u het volgende doen:

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

Dat gebruik ik als ik grote bestanden met veel kolommen heb.


Antwoord 7, autoriteit 6%

dplyrversie 1.0.0bevat de functie relocate()om eenvoudig kolommen opnieuw te ordenen:

dat <- data.frame(Time=c(1,2), In=c(2,3), Out=c(3,4), Files=c(4,5))
library(dplyr) # from version 1.0.0 only
dat %>%
  relocate(Out, .before = In)

of

dat %>%
  relocate(Out, .after = Time)

Antwoord 8, autoriteit 5%

U kunt het pakket data.tablegebruiken:

De volgorde van data.table-kolommen (zonder kopiëren)

require(data.table)
setcolorder(DT,myOrder)

Antwoord 9, autoriteit 4%

De drietop -ratedantwoordenhebben een zwak punt.

Als uw dataframe er zo uitziet

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

dan is het een slechte oplossing om te gebruiken

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

Het doet het werk, maar je hebt zojuist een afhankelijkheid geïntroduceerd van de volgorde van de kolommen in je invoer.

Deze stijl van broos programmeren moet worden vermeden.

De expliciete naamgeving van de kolommen is een betere oplossing

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

Bovendien, als u van plan bent uw code in een meer algemene omgeving opnieuw te gebruiken, kunt u eenvoudig

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

wat ook best aardig is omdat het letterlijke termen volledig isoleert. Als u daarentegen select

. van dplyr gebruikt

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

dan stel je degenen aan die je code later zullen lezen, inclusief jezelf, voor een beetje misleiding. De kolomnamen worden gebruikt als letterlijke waarden zonder als zodanig in de code te verschijnen.


Antwoord 10

data.table::setcolorder(table, c("Out", "in", "files"))

Antwoord 11

De enige die ik goed heb zien werken, is van hier.

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
}

Gebruik als volgt:

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

Werkt als een tierelier.

Other episodes