57 votes

Comment ordonner un cadre de données par une colonne descendante et une colonne ascendante ?

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

    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 veux le trier par I1 dans l'ordre décroissant, et les lignes ayant la même valeur dans I1 par I2 dans l'ordre croissant, en obtenant les lignes dans l'ordre suivant 1 3 4 2 . Mais le order semble ne prendre qu'un seul decreasing qui est ensuite TRUE ou FALSE pour tous les vecteurs d'ordre à la fois. Comment faire pour que mon tri soit correct ?

55voto

Roman Luštrik Points 19295

J'ai utilisé ce code pour produire le résultat souhaité. Est-ce que c'est ce que vous recherchez ?

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

34voto

Michele Points 3199

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

26voto

dudusan Points 76

J'ai bien peur que la réponse de Roman Luštrik soit fausse. Il fonctionne sur cette entrée par hasard. Considérez par exemple sa sortie sur une entrée très similaire (avec une ligne supplémentaire similaire à la ligne 3 originale 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 qui est normal puisque le tri secondaire est I2 dans l'ordre croissant.

Pour obtenir l'ordre inverse de I2, vous voulez que les grandes valeurs soient petites et vice versa. Pour les valeurs numériques, il suffit de multiplier par -1, mais pour les caractères, c'est un peu plus délicat. Une solution générale pour les caractères/chaînes serait de passer par les facteurs, d'inverser les niveaux (pour que les grandes valeurs soient petites et les petites valeurs grandes) et de changer le facteur en 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

7voto

ayush1723 Points 26

Soit df le cadre 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 non numérique, dites facteur ou caractère.

Dans notre cas, si B est un caractère et que nous voulons le 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.

4voto

Somnath Kadam Points 487

Un simple sans grade :

rum[order(rum$I1, -rum$I2, decreasing = TRUE), ]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X