web-dev-qa-db-fra.com

Comment trier une base de données par plusieurs colonnes

Je veux trier un data.frame par plusieurs colonnes. Par exemple, avec le data.frame ci-dessous, je voudrais trier par colonne z (décroissant) puis par colonne b (croissant):

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
dd
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2
1245
Christopher DuBois

Vous pouvez utiliser la fonction order() directement sans recourir à des outils complémentaires. Voir cette réponse plus simple qui utilise une astuce tout en haut du code example(order):

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

Éditez quelques années plus tard: Il a simplement été demandé comment procéder par index de colonne. La solution consiste simplement à transmettre les colonnes de tri souhaitées à la fonction order():

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

plutôt que d'utiliser le nom de la colonne (et with() pour un accès plus facile/plus direct).

1550
Dirk Eddelbuettel

Vos choix

  • order sur base
  • arrange sur dplyr
  • setorder et setorderv de data.table
  • arrange sur plyr
  • sort sur taRifx
  • orderBy sur doBy
  • sortData sur Deducer

La plupart du temps, vous devez utiliser les solutions dplyr ou data.table, sauf si l'absence de dépendance est importante, auquel cas utilisez base::order.


J'ai récemment ajouté sort.data.frame à un package CRAN, ce qui le rend compatible avec la classe, comme indiqué ci-après: Meilleure façon de créer une cohérence générique/de méthode pour sort.data.frame?

Par conséquent, étant donné le dd data.frame, vous pouvez trier comme suit:

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )

Si vous êtes l’un des auteurs originaux de cette fonction, contactez-moi. La discussion sur le domaine public est ici: http://chat.stackoverflow.com/transcript/message/1094290#109429


Vous pouvez également utiliser la fonction arrange() de plyr comme Hadley l’a souligné dans le fil de discussion ci-dessus:

library(plyr)
arrange(dd,desc(z),b)

Points de repère: Notez que j'ai chargé chaque paquet dans une nouvelle session R car il y avait beaucoup de conflits. En particulier, lors du chargement du package doBy, sort renvoie "Les objets suivants sont masqués à partir de 'x (position 17)': b, x, y, z", et le chargement du package Deducer écrase sort.data.frame de Kevin Wright ou le paquet taRifx.

#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(microbenchmark)

# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
    dd[order(-dd$z, dd$b),],
    times=1000
)

Temps médians:

dd[with(dd, order(-z, b)), ] 778

dd[order(-dd$z, dd$b),] 788

library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)

Temps médian: 1 567

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)

Temps médian: 862

library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)

Temps médian: 1,694

Notez que doBy prend un bon bout de temps pour charger le paquet.

library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)

Impossible de charger Deducer. Nécessite la console JGR.

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}

microbenchmark(esort(dd, -z, b),times=1000)

Ne semble pas être compatible avec microbenchmark en raison de l'attachement/détachement.


m <- microbenchmark(
  arrange(dd,desc(z),b),
  sort(dd, f= ~-z+b ),
  dd[with(dd, order(-z, b)), ] ,
  dd[order(-dd$z, dd$b),],
  times=1000
  )

uq <- function(x) { fivenum(x)[4]}  
lq <- function(x) { fivenum(x)[2]}

y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05

p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max )) 
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))

microbenchmark plot

(les lignes vont du quartile inférieur au quartile supérieur, le point est la médiane)


Compte tenu de ces résultats et de la simplicité de pondération par rapport à la vitesse, je devrais donner le signe de tête à arrange DANS LE PACKAGE plyr. Il a une syntaxe simple et pourtant, il est presque aussi rapide que les commandes de base R avec leurs machinations compliquées. Hadley Wickham travaille généralement de manière brillante. Mon seul reproche, c'est que cela rompt avec la nomenclature standard R où les objets de tri sont appelés par sort(object), mais je comprends pourquoi Hadley l'a fait ainsi en raison des problèmes abordés dans la question liée ci-dessus.

441
Ari B. Friedman

La réponse de Dirk est excellente. Il met également en évidence une différence clé dans la syntaxe utilisée pour l'indexation _data.frame_ s et _data.table_ s:

_## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]
_

La différence entre les deux appels est faible, mais cela peut avoir des conséquences importantes. Surtout si vous écrivez du code de production et/ou si vous êtes soucieux de l'exactitude de votre recherche, il est préférable d'éviter les répétitions inutiles de noms de variables. _data.table_ vous aide à le faire.

Voici un exemple montrant comment la répétition de noms de variables peut vous causer des problèmes:

Changeons le contexte de la réponse de Dirk et disons que cela fait partie d'un projet plus vaste dans lequel il existe de nombreux noms d'objet, qui sont longs et significatifs. au lieu de dd, il s'appelle quarterlyreport. Il devient :

_quarterlyreport[with(quarterlyreport,order(-z,b)),]
_

OK bien. Aucun problème avec ça. Ensuite, votre patron vous demande d'inclure le rapport du dernier trimestre dans le rapport. Vous parcourez votre code, en ajoutant un objet lastquarterlyreport à divers endroits et en quelque sorte (comment diable?) Vous vous retrouvez avec ceci:

_quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
_

Ce n'est pas ce que vous vouliez dire, mais vous ne l'avez pas repéré parce que vous l'avez fait rapidement et qu'il est niché sur une page de code similaire. Le code ne tombe pas (pas d'avertissement ni d'erreur) car R pense que c'est ce que vous vouliez dire. Vous espérez que quiconque lit votre rapport le remarque, mais peut-être que non. Si vous travaillez beaucoup avec les langages de programmation, cette situation peut vous paraître familière. C'était une "faute de frappe", dites-vous. Je vais réparer la "faute de frappe" que vous direz à votre patron.

Dans data.table nous sommes préoccupés par de petits détails comme celui-ci. Nous avons donc fait quelque chose de simple pour éviter de saisir deux fois les noms de variables. Quelque chose de très simple. i est déjà évalué automatiquement dans le cadre de dd. Vous n'avez pas du tout besoin de with().

Au lieu de

_dd[with(dd, order(-z, b)), ]
_

c'est juste

_dd[order(-z, b)]
_

Et au lieu de

_quarterlyreport[with(lastquarterlyreport,order(-z,b)),]
_

c'est juste

_quarterlyreport[order(-z,b)]
_

C'est une très petite différence, mais cela pourrait vous sauver la tête un jour. Lorsque vous pesez les différentes réponses à cette question, pensez à compter les répétitions de noms de variables parmi vos critères de décision. Certaines réponses ont un certain nombre de répétitions, d'autres n'en ont aucune.

141
Matt Dowle

Il y a beaucoup d'excellentes réponses ici, mais dplyr donne la seule syntaxe dont je puisse me souvenir rapidement et facilement (et que j'utilise maintenant très souvent):

library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)

Pour le problème du PO:

arrange(dd, desc(z),  b)

    b x y z
1 Low C 9 2
2 Med D 3 1
3  Hi A 8 1
4  Hi A 9 1
117
Ben

Le package R data.table fournit à la fois rapide et efficace en mémoire l'ordre de data.tables avec une syntaxe simple (une partie dont Matt a très bien mis en évidence dans sa réponse ). Il y a eu beaucoup d'améliorations et aussi une nouvelle fonction setorder() depuis lors. De v1.9.5+, setorder() fonctionne également avec data.frames.

Tout d'abord, nous allons créer un jeu de données assez volumineux et analyser les différentes méthodes mentionnées dans d'autres réponses, puis répertorier les caractéristiques de data.table.

Les données:

require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)

set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
                 x = sample(c("A", "D", "C"), 1e8, TRUE),
                 y = sample(100, 1e8, TRUE),
                 z = sample(5, 1e8, TRUE), 
                 stringsAsFactors = FALSE)

Benchmarks:

Les temps indiqués proviennent de l'exécution de system.time(...) sur les fonctions indiquées ci-dessous. Les horaires sont présentés ci-dessous (dans l'ordre des plus lents aux plus rapides).

orderBy( ~ -z + b, data = dat)     ## doBy
plyr::arrange(dat, desc(z), b)     ## plyr
arrange(dat, desc(z), b)           ## dplyr
sort(dat, f = ~ -z + b)            ## taRifx
dat[with(dat, order(-z, b)), ]     ## base R

# convert to data.table, by reference
setDT(dat)

dat[order(-z, b)]                  ## data.table, base R like syntax
setorder(dat, -z, b)               ## data.table, using setorder()
                                   ## setorder() now also works with data.frames 

# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package      function    Time (s)  Peak memory   Memory used
# ------------------------------------------------------------
# doBy          orderBy      409.7        6.7 GB        4.7 GB
# taRifx           sort      400.8        6.7 GB        4.7 GB
# plyr          arrange      318.8        5.6 GB        3.6 GB 
# base R          order      299.0        5.6 GB        3.6 GB
# dplyr         arrange       62.7        4.2 GB        2.2 GB
# ------------------------------------------------------------
# data.table      order        6.2        4.2 GB        2.2 GB
# data.table   setorder        4.5        2.4 GB        0.4 GB
# ------------------------------------------------------------
  • La syntaxe de data.tableDT[order(...)] était ~ 10x plus rapide que la plus rapide des autres méthodes (dplyr), tout en consommant même quantité de mémoire que dplyr.

  • data.table's setorder() était ~ 14x plus rapide que la plus rapide des autres méthodes (dplyr), en prenant seulement 0.4GB de mémoire supplémentaire . dat est maintenant dans l'ordre requis (car il est mis à jour par référence).

caractéristiques de data.table:

Vitesse:

  • La commande de data.table est extrêmement rapide car elle implémente commande de base .

  • La syntaxe DT[order(...)] est optimisée en interne pour utiliser également la commande rapide de data.table. Vous pouvez continuer à utiliser la syntaxe habituelle base R mais accélérer le processus (et utiliser moins de mémoire).

Mémoire:

  • La plupart du temps, nous n'avons pas besoin de l'original data.frame ou data.table après la réorganisation. C'est-à-dire que nous associons généralement le résultat au même objet, par exemple:

    DF <- DF[order(...)]
    

    Le problème est que cela nécessite au moins deux fois (2x) la mémoire de l'objet d'origine. Être efficace de la mémoire, data.table fournit donc également une fonction setorder().

    setorder() réordonne data.tablesby reference (in-place), sans effectuer de copies supplémentaires. Il utilise uniquement de la mémoire supplémentaire égale à la taille d'une colonne.

Autres caractéristiques:

  1. Il supporte les types integer, logical, numeric, character et même bit64::integer64.

    Notez que les classes factor, Date, POSIXct etc .. sont toutes des types integer/numeric avec des attributs supplémentaires et sont donc également prises en charge.

  2. En base R, nous ne pouvons pas utiliser - sur un vecteur de caractère pour trier par colonne en ordre décroissant. Au lieu de cela, nous devons utiliser -xtfrm(.).

    Cependant, dans data.table, nous pouvons simplement faire, par exemple, dat[order(-x)] ou setorder(dat, -x).

77
Arun

Avec cette fonction (très utile) de Kevin Wright , publiée dans la section conseils du wiki R, cela est facilement réalisable.

sort(dd,by = ~ -z + b)
#     b x y z
# 4 Low C 9 2
# 2 Med D 3 1
# 1  Hi A 8 1
# 3  Hi A 9 1
67
Christopher DuBois

ou vous pouvez utiliser package doBy

library(doBy)
dd <- orderBy(~-z+b, data=dd)
35
George Dontas

Supposons que vous ayez un data.frameA et que vous souhaitiez le trier à l'aide de la colonne appelée x ordre décroissant. Appelez le data.frame _ trié newdata

newdata <- A[order(-A$x),]

Si vous voulez un ordre croissant, remplacez "-" par rien. Vous pouvez avoir quelque chose comme

newdata <- A[order(-A$x, A$y, -A$z),]

x et z sont des colonnes dans data.frameA. Cela signifie que vous triez data.frameA par x décroissant, y croissant et z croissant.

34
Khayelihle

si SQL vous vient naturellement, sqldf gère ORDER BY comme prévu par Codd.

27
malecki

Alternativement, en utilisant le package Deducer

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))
27
Ian Fellows

En réponse à un commentaire ajouté dans l'OP sur la manière de trier par programme:

Utiliser dplyr et data.table

library(dplyr)
library(data.table)

dplyr

Utilisez simplement arrange_, qui est la version d'évaluation standard pour arrange.

df1 <- tbl_df(iris)
#using strings or formula
arrange_(df1, c('Petal.Length', 'Petal.Width'))
arrange_(df1, ~Petal.Length, ~Petal.Width)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.4         3.9          1.3         0.4  setosa
7           5.5         3.5          1.3         0.2  setosa
8           4.4         3.0          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...


#Or using a variable
sortBy <- c('Petal.Length', 'Petal.Width')
arrange_(df1, .dots = sortBy)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.5         3.5          1.3         0.2  setosa
7           4.4         3.0          1.3         0.2  setosa
8           4.4         3.2          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...

#Doing the same operation except sorting Petal.Length in descending order
sortByDesc <- c('desc(Petal.Length)', 'Petal.Width')
arrange_(df1, .dots = sortByDesc)

plus d'infos ici: https://cran.r-project.org/web/packages/dplyr/vignettes/nse.html

Il est préférable d’utiliser une formule car elle capture également l’environnement pour évaluer une expression en

data.table

dt1 <- data.table(iris) #not really required, as you can work directly on your data.frame
sortBy <- c('Petal.Length', 'Petal.Width')
sortType <- c(-1, 1)
setorderv(dt1, sortBy, sortType)
dt1
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
  1:          7.7         2.6          6.9         2.3 virginica
  2:          7.7         2.8          6.7         2.0 virginica
  3:          7.7         3.8          6.7         2.2 virginica
  4:          7.6         3.0          6.6         2.1 virginica
  5:          7.9         3.8          6.4         2.0 virginica
 ---                                                            
146:          5.4         3.9          1.3         0.4    setosa
147:          5.8         4.0          1.2         0.2    setosa
148:          5.0         3.2          1.2         0.2    setosa
149:          4.3         3.0          1.1         0.1    setosa
150:          4.6         3.6          1.0         0.2    setosa
15
info_seekeR

La réponse de Dirk est bonne, mais si vous avez besoin que le tri persiste, vous voudrez le ré-appliquer sur le nom de ce bloc de données. En utilisant l'exemple de code:

dd <- dd[with(dd, order(-z, b)), ] 
15
Andrew

J'ai appris à propos de order avec l'exemple suivant qui m'a ensuite confondu pendant longtemps:

set.seed(1234)

ID        = 1:10
Age       = round(rnorm(10, 50, 1))
diag      = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)

data = data.frame(ID, Age, Diagnosis)

databyAge = data[order(Age),]
databyAge

Cet exemple ne fonctionne que parce que order trie par vector Age, et non par la colonne nommée Age dans data frame data.

Pour le voir, créez un bloc de données identique en utilisant read.table avec des noms de colonne légèrement différents et sans utiliser aucun des vecteurs ci-dessus:

my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)

La structure de ligne ci-dessus pour order ne fonctionne plus car il n'y a pas de vecteur nommé age:

databyage = my.data[order(age),]

La ligne suivante fonctionne parce que order trie sur la colonne age dans my.data.

databyage = my.data[order(my.data$age),]

Je pensais que cela valait la peine d’être publié étant donné la confusion que j'ai accumulée pendant si longtemps avec cet exemple. Si ce message n'est pas jugé approprié pour le fil, je peux le supprimer.

EDIT: 13 mai 2014

Vous trouverez ci-dessous une manière généralisée de trier un cadre de données pour chaque colonne sans spécifier de noms de colonne. Le code ci-dessous montre comment trier de gauche à droite ou de droite à gauche. Cela fonctionne si chaque colonne est numérique. Je n'ai pas essayé avec une colonne de caractères ajoutée.

J'ai trouvé le code do.call il y a un mois ou deux dans un ancien billet sur un site différent, mais seulement après une recherche longue et difficile. Je ne suis pas sûr de pouvoir déplacer ce poste maintenant. Le fil actuel est le premier hit pour la commande d'un data.frame dans R. J'ai donc pensé que ma version développée de ce code do.call original pourrait être utile.

set.seed(1234)

v1  <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2  <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3  <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4  <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)

df.1 <- data.frame(v1, v2, v3, v4) 
df.1

rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1

order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1

order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2

rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1) 
rdf.3

order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3
15
Mark Miller

Arrange () dans dplyer est mon option préférée. Utilisez l'opérateur de tuyauterie et passez de l'aspect le moins important à l'aspect le plus important

dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))
9
Kaden Killpack

Par souci d’exhaustivité, vous pouvez également utiliser la fonction sortByCol() du package BBmisc:

library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

Comparaison de performance:

library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872
5
Lars Kotthoff

Tout comme les trieuses de cartes mécaniques d’il ya très longtemps, commencez par trier les clés les moins importantes, puis les plus importantes, etc. Aucune bibliothèque requise, fonctionne avec un nombre quelconque de clés et n’importe quelle combinaison de touches ascendante et descendante.

 dd <- dd[order(dd$b, decreasing = FALSE),]

Nous sommes maintenant prêts à faire la clé la plus significative. Le tri est stable et tous les liens dans la clé la plus significative ont déjà été résolus.

dd <- dd[order(dd$z, decreasing = TRUE),]

Ce n'est peut-être pas le plus rapide, mais c'est certainement simple et fiable

4
Rick

Une autre alternative, utilisant le paquetage rgr:

> library(rgr)
> gx.sort.df(dd, ~ -z+b)
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
3

Par souci d’exhaustivité, peu de choses ont été dites sur le tri par numéro de colonne ... On peut certes affirmer que cela n’est souvent pas souhaitable (car l’ordre des colonnes pourrait changer, ouvrant la voie à des erreurs), mais Dans certaines situations spécifiques (par exemple, lorsque vous avez besoin d'un travail rapide et que les colonnes ne changent pas d'ordres de ce type), cela peut s'avérer la chose la plus sensée à faire, en particulier lorsque vous utilisez un grand nombre de colonnes.

Dans ce cas, do.call() vient à la rescousse:

ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]

##        Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
##    14           4.3         3.0          1.1         0.1     setosa
##    9            4.4         2.9          1.4         0.2     setosa
##    39           4.4         3.0          1.3         0.2     setosa
##    43           4.4         3.2          1.3         0.2     setosa
##    42           4.5         2.3          1.3         0.3     setosa
##    4            4.6         3.1          1.5         0.2     setosa
##    48           4.6         3.2          1.4         0.2     setosa
##    7            4.6         3.4          1.4         0.3     setosa
##    (...)
2
Dominic Comtois

Je me débattais avec les solutions ci-dessus lorsque je souhaitais automatiser mon processus de commande pour n colonnes, dont les noms de colonne pouvaient être différents à chaque fois. J'ai trouvé une fonction très utile du paquetage psych pour le faire de manière simple:

dfOrder(myDf, columnIndices)

columnIndices sont des index d'une ou de plusieurs colonnes, dans l'ordre dans lequel vous souhaitez les trier. Plus d'informations ici:

fonction dfOrder du paquet 'psych'

2
AHegde