web-dev-qa-db-fra.com

Comment commander un bloc de données en une colonne ascendante et ascendante?

J'ai un cadre de données, qui ressemble à cela:

    P1  P2  P3  T1  T2  T3  I1  I2
1   2   3   5   52  43  61  6   "b"
2   6   4   3   72  NA  59  1   "a"
3   1   5   6   55  48  60  6   "f"
4   2   4   4   65  64  58  2   "b"

Je souhaite le trier par ordre décroissant selon I1, et les lignes de même valeur dans I1 par I2 selon un ordre croissant, en obtenant les lignes dans l'ordre 1 3 4 2. Mais la fonction order semble ne prendre qu'un seul argument decreasing, qui est alors TRUE ou FALSE pour tous les vecteurs de commande à la fois. Comment puis-je obtenir mon genre correct?

48
rumtscho

J'ai utilisé ce code pour produire la sortie souhaitée. Est-ce ce que vous recherchiez?

rum <- read.table(textConnection("P1  P2  P3  T1  T2  T3  I1  I2
2   3   5   52  43  61  6   b
6   4   3   72  NA  59  1   a
1   5   6   55  48  60  6   f
2   4   4   65  64  58  2   b"), header = TRUE)
rum$I2 <- as.character(rum$I2)
rum[order(rum$I1, rev(rum$I2), decreasing = TRUE), ]

  P1 P2 P3 T1 T2 T3 I1 I2
1  2  3  5 52 43 61  6  b
3  1  5  6 55 48 60  6  f
4  2  4  4 65 64 58  2  b
2  6  4  3 72 NA 59  1  a
44
Roman Luštrik

J'utilise rank:

rum <- read.table(textConnection("P1  P2  P3  T1  T2  T3  I1  I2
2   3   5   52  43  61  6   b
6   4   3   72  NA  59  1   a
1   5   6   55  48  60  6   f
2   4   4   65  64  58  2   b
1   5   6   55  48  60  6   c"), header = TRUE)

> rum[order(rum$I1, -rank(rum$I2), decreasing = TRUE), ]
  P1 P2 P3 T1 T2 T3 I1 I2
1  2  3  5 52 43 61  6  b
5  1  5  6 55 48 60  6  c
3  1  5  6 55 48 60  6  f
4  2  4  4 65 64 58  2  b
2  6  4  3 72 NA 59  1  a
28
Michele

Je crains que la réponse de Roman Luštrik soit fausse. Cela fonctionne sur cette entrée par hasard. Considérons par exemple sa sortie sur une entrée très similaire (avec une ligne supplémentaire similaire à la ligne 3 d'origine avec "c" dans la colonne I2):

rum <- read.table(textConnection("P1  P2  P3  T1  T2  T3  I1  I2
2   3   5   52  43  61  6   b
6   4   3   72  NA  59  1   a
1   5   6   55  48  60  6   f
2   4   4   65  64  58  2   b
1   5   6   55  48  60  6   c"), header = TRUE)

rum$I2 <- as.character(rum$I2)
rum[order(rum$I1, rev(rum$I2), decreasing = TRUE), ]

  P1 P2 P3 T1 T2 T3 I1 I2
3  1  5  6 55 48 60  6  f
1  2  3  5 52 43 61  6  b
5  1  5  6 55 48 60  6  c
4  2  4  4 65 64 58  2  b
2  6  4  3 72 NA 59  1  a

Ce n'est pas le résultat souhaité: les trois premières valeurs de I2 sont f b c au lieu de b c f, ce à quoi on pourrait s’attendre puisque le tri secondaire est I2 par ordre croissant.

Pour obtenir l'ordre inverse de I2, vous voulez que les grandes valeurs soient petites et inversement. Pour les valeurs numériques, multiplier par -1 fera l'affaire, mais pour les caractères, c'est un peu plus compliqué. Une solution générale pour les caractères/chaînes consiste à passer en revue les facteurs, à inverser les niveaux (pour créer de grandes valeurs petites et grandes) et à remplacer le facteur par des caractères:

rum <- read.table(textConnection("P1  P2  P3  T1  T2  T3  I1  I2
2   3   5   52  43  61  6   b
6   4   3   72  NA  59  1   a
1   5   6   55  48  60  6   f
2   4   4   65  64  58  2   b
1   5   6   55  48  60  6   c"), header = TRUE)

f=factor(rum$I2)
levels(f) = rev(levels(f))
rum[order(rum$I1, as.character(f), decreasing = TRUE), ]

  P1 P2 P3 T1 T2 T3 I1 I2
1  2  3  5 52 43 61  6  b
5  1  5  6 55 48 60  6  c
3  1  5  6 55 48 60  6  f
4  2  4  4 65 64 58  2  b
2  6  4  3 72 NA 59  1  a
23
dudusan

Soit df le bloc de données avec 2 champs A et B

Cas 1: si vos champs A et B sont numériques

df[order(df[,1],df[,2]),] - sorts fields A and B in ascending order
df[order(df[,1],-df[,2]),] - sorts fields A in ascending and B in descending order
la priorité est donnée à A.

Cas 2: si le champ A ou B est un facteur ou un caractère non numérique

Dans notre cas, si B est un caractère et que nous voulons trier dans l'ordre inverse
df[order(df[,1],-as.numeric(as.factor(df[,2]))),] -> this sorts field A(numerical) in ascending and field B(character) in descending.
la priorité est donnée à A.

The idea is that you can apply -sign in order function ony on numericals. So for sorting character strings in descending order you have to coerce them to numericals.

4
ayush1723

Le tri par défaut est stable, nous trions donc deux fois: d'abord par la clé mineure, puis par la clé majeure

rum1 <- rum[order(rum$I2, decreasing = FALSE),]
rum2 <- rum1[order(rum1$I1, decreasing = TRUE),]
3
Rick

Simple sans rang:

rum[order(rum$I1, -rum$I2, decreasing = TRUE), ]
2
Somnath Kadam
    library(dplyr)
    library(tidyr)
    #supposing you want to arrange column 'c' in descending order and 'd' in ascending order. name of data frame is df
    ## first doing descending
    df<-arrange(df,desc(c))
    ## then the ascending order of col 'd;
    df <-arrange(df,d)
2
Pranay Aryal
rum[order(rum$T1, -rum$T2 ), ]
1
Dmitri B

Dans l'exemple de @ dudusan, vous pouvez également inverser l'ordre de I1, puis trier par ordre croissant:

> rum <- read.table(textConnection("P1  P2  P3  T1  T2  T3  I1  I2
+   2   3   5   52  43  61  6   b
+   6   4   3   72  NA  59  1   a
+   1   5   6   55  48  60  6   f
+   2   4   4   65  64  58  2   b
+   1   5   6   55  48  60  6   c"), header = TRUE)
> f=factor(rum$I1)   
> levels(f) <- sort(levels(f), decreasing = TRUE)
> rum[order(as.character(f), rum$I2), ]
  P1 P2 P3 T1 T2 T3 I1 I2
1  2  3  5 52 43 61  6  b
5  1  5  6 55 48 60  6  c
3  1  5  6 55 48 60  6  f
4  2  4  4 65 64 58  2  b
2  6  4  3 72 NA 59  1  a
> 

Cela semble un peu plus court, vous n'inversez pas l'ordre de I2 deux fois.

0
Dries Knottnerus

La manière correcte est:

rum[order(rum$T1, rum$T2, decreasing=c(T,F)), ]
0
dinh