web-dev-qa-db-fra.com

Comment réorganiser les colonnes dans un cadre de données?

Comment modifier cette entrée (avec la séquence: heure, entrée, sortie, fichiers):

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

À cette sortie (avec la séquence: time, out, in, files)?

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

Voici les données factices 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
263
Catherine

Votre dataframe a quatre colonnes comme suit df[,c(1,2,3,4)]. Notez que la première virgule signifie que toutes les lignes sont conservées et que 1,2,3,4 fait référence aux colonnes.

Pour changer l'ordre comme dans la question ci-dessus, faites df2[,c(1,3,2,4)]

Si vous voulez sortir ce fichier en tant que csv, faites write.csv(df2, file="somedf.csv")

295
richiemorrisroe
# reorder by column name
data <- data[c("A", "B", "C")]

#reorder by column index
data <- data[c(1,3,2)]
148
Xavier Guardiola

Vous pouvez également utiliser la fonction de sous-ensemble:

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

Vous devriez mieux utiliser l'opérateur [] comme dans les autres réponses, mais il peut être utile de savoir que vous pouvez effectuer une opération de sous-ensemble et de réorganisation de colonne dans une seule commande.

Mise à jour:

Vous pouvez également utiliser la fonction select du package dplyr:

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

Je ne suis pas sûr de l'efficacité, mais grâce à la syntaxe de dplyr, cette solution devrait être plus flexible, surtout si vous avez beaucoup de colonnes. Par exemple, les éléments suivants réorganiseront les colonnes du jeu de données mtcars dans l'ordre inverse:

mtcars %>% select(carb:mpg)

Et les suivants ne réorganiseront que certaines colonnes et en rejeteront d’autres:

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

En savoir plus sur la syntaxe de sélection de dplyr .

93
dalloliogm

Comme mentionné dans ce commentaire , les suggestions standard pour réorganiser les colonnes dans un data.frame sont généralement lourdes et sujettes aux erreurs, en particulier si vous avez beaucoup de colonnes.

Cette fonction permet de réorganiser les colonnes par position: spécifiez un nom de variable et la position souhaitée, sans vous soucier des autres colonnes.

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

Maintenant, la demande de l'OP devient aussi simple que cela:

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

Pour échanger en plus les colonnes Time et Files, procédez comme suit:

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

C’est peut-être une coïncidence si l’ordre des colonnes que vous souhaitez avoir a des noms de colonnes en ordre alphabétique décroissant. Puisque c'est le cas, vous pouvez simplement faire:

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

C'est ce que j'utilise quand j'ai de gros fichiers avec beaucoup de colonnes.

24
user3482899

Une solution tidyverse consiste à utiliser select:

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

# or

select(table, Time, Out, In, Files)
18
Ben G

Si vous pouvez utiliser le package data.table, cela constitue un moyen simple et efficace

Comment réorganiser les colonnes de data.table (sans les copier)

setcolorder(DT,myOrder)
15
usct01

Les troismieux notésréponses ont une faiblesse.

Si votre image de données ressemble à ceci

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

alors c'est une mauvaise solution à utiliser

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

Cela fait le travail, mais vous venez d'introduire une dépendance sur l'ordre des colonnes dans votre entrée.

Ce style de programmation fragile doit être évité.

La dénomination explicite des colonnes est une meilleure solution

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

De plus, si vous avez l’intention de réutiliser votre code dans un contexte plus général, vous pouvez simplement:

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

ce qui est également assez agréable car il isole complètement les littéraux. En revanche, si vous utilisez select de dplyr

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

ensuite, vous configurerez ceux qui liront votre code plus tard, vous-même inclus, pour vous tromper un peu. Les noms de colonne sont utilisés comme des littéraux sans apparaître dans le code en tant que tels.

7
Vrokipal
data.table::setcolorder(table, c("Out", "in", "files"))
2
Hossein Noorazar

Le seul que j'ai vu bien travailler est de ici .

 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
}

Utilisez comme ceci:

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

Fonctionne comme un charme.

1
Cybernetic