Jak zamówić ramkę danych o jednej kolumnie malejącej i rosnącej?

Mam ramkę danych, która wygląda tak:

    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"

Chcę sortować go według I1 w porządku malejącym, a wiersze o tej samej wartości w I1 przez I2 w porządku rosnącym, otrzymując wiersze w porządku 1 3 4 2. Jednak funkcja order zdaje się przyjmować tylko jeden argument decreasing, który jest wtedy TRUE lub FALSE dla wszystkich porządkujących wektorów jednocześnie. Jak mogę poprawić mój sortowanie?

 43
Author: Jaap, 2011-10-17

10 answers

Użyłem tego kodu, aby wyprodukować pożądany wynik. O to ci chodziło?

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
 37
Author: Roman Luštrik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-17 12:10:48

Używam 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
 26
Author: Michele,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-22 11:16:36

Obawiam się, że odpowiedź Romana Luštrika jest błędna. Działa na tym wejściu przez przypadek. Rozważmy na przykład jego wyjście na bardzo podobnym wejściu (z dodatkową linią podobną do oryginalnej linii 3 z "c"w kolumnie 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

Nie jest to pożądany wynik: pierwsze trzy wartości I2 to f b c zamiast b c f, Czego można się spodziewać, ponieważ sortowaniem wtórnym jest I2 w porządku rosnącym.

Aby uzyskać odwrotną kolejność I2, chcesz, aby duże wartości były małe i odwrotnie versa. Dla wartości liczbowych mnożenie przez -1 zrobi to, ale dla znaków jest trochę bardziej skomplikowane. Ogólnym rozwiązaniem dla znaków / łańcuchów byłoby przejście przez czynniki, odwrócenie poziomów (aby duże wartości były małe i małe wartości duże) i zmiana czynnika z powrotem na znaki:

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
Author: dudusan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-12 04:13:28

Niech df będzie ramką danych z 2 polami A i B

Przypadek 1: Jeśli Twoje pola A i B są liczbowe

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
pierwszeństwo otrzymuje A.

Przypadek 2: jeśli pole a lub B nie jest numeryczne, powiedz czynnik lub znak

W naszym przypadku Jeśli B jest znakiem i chcemy sortować w odwrotnej kolejności
df[order(df[,1],-as.numeric(as.factor(df[,2]))),] -> this sorts field A(numerical) in ascending and field B(character) in descending.
pierwszeństwo ma 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
Author: ayush1723,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-27 13:18:11

Sortowanie domyślne jest stabilne, więc sortujemy dwa razy: najpierw według klucza podrzędnego, a następnie według klucza głównego

rum1 <- rum[order(rum$I2, decreasing = FALSE),]
rum2 <- rum1[order(rum1$I1, decreasing = TRUE),]
 3
Author: Rick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-08 23:49:36

Prawidłowy sposób to:

rum[order(rum$T1, rum$T2, decreasing=c(T,F)), ]
 2
Author: dinh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-22 01:58:22
    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
Author: Pranay Aryal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-15 19:53:11
rum[order(rum$T1, -rum$T2 ), ]
 1
Author: Dmitri B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-29 11:15:54

Prosty bez Rangi:

rum[order(rum$I1, -rum$I2, decreasing = TRUE), ]
 1
Author: Somnath Kadam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 11:37:03

W przykładzie @ dudusan możesz również odwrócić kolejność I1, a następnie sortować rosnąco:

> 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
> 

To wydaje się trochę krótsze, nie odwracasz kolejności I2 dwa razy.

 0
Author: Dries Knottnerus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-23 06:27:05