如何按一列降序和一升序对数据框进行排序?

发布于 2024-12-10 00:48:18 字数 440 浏览 1 评论 0原文

我有一个数据框,看起来像这样:

    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"

我想按 I1 降序对其进行排序,并按 I2 按升序对 I1 中具有相同值的行进行排序,以 1 3 4 2< 的顺序获取行/代码>。但 order 函数似乎只采用一个 decreasing 参数,对于所有排序向量,该参数为 TRUEFALSE立刻。如何正确排序?

I have a data frame, which looks like that:

    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"

I want to sort it by I1 in descending order, and rows with the same value in I1 by I2 in ascending order, getting the rows in the order 1 3 4 2. But the order function seems to only take one decreasing argument, which is then TRUE or FALSE for all ordering vectors at once. How do I get my sort correct?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

〃安静 2024-12-17 00:48:18

我使用这段代码来产生您想要的输出。这就是你所追求的吗?

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

I used this code to produce your desired output. Is this what you were after?

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
固执像三岁 2024-12-17 00:48:18

我使用排名

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

I use 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
〗斷ホ乔殘χμё〖 2024-12-17 00:48:18

恐怕 Roman Luštrik 的答案是错误的。它偶然作用于这个输入。
例如,考虑其在非常相似的输入上的输出(具有与原始第 3 行类似的附加行,其中 I2 列中带有“c”):

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

这不是所需的结果:I2 的前三个值是 fb c 而不是 bc f,这是预期的,因为辅助排序是按升序排列的 I2。

要获得 I2 的相反顺序,您希望较大的值较小,反之亦然。对于数值乘以 -1 就可以了,但对于字符则有点棘手。字符/字符串的一般解决方案是遍历因子,反转级别(使大值变小,使小值变大)并将因子更改回字符:

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

I'm afraid Roman Luštrik's answer is wrong. It works on this input by chance.
Consider for example its output on a very similar input (with an additional line similar to the original line 3 with "c" in the I2 column):

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

This is not the desired result: the first three values of I2 are f b c instead of b c f, which would be expected since the secondary sort is I2 in ascending order.

To get the reverse order of I2, you want the large values to be small and vice versa. For numeric values multiplying by -1 will do it, but for characters its a bit more tricky. A general solution for characters/strings would be to go through factors, reverse the levels (to make large values small and small values large) and change the factor back to characters:

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
美胚控场 2024-12-17 00:48:18

设 df 为具有 2 个字段 A 和 B 的数据框

情况 1:如果您的字段 A 和 B 是数字

df[order(df[,1],df[,2]),] - 按升序对字段 A 和 B 进行排序
df[order(df[,1],-df[,2]),] - 按升序对字段 A 进行排序,按降序对字段 B 进行排序
优先权给A。

情况 2:如果字段 A 或 B 为非数字,则为因子或字符

在我们的例子中,如果 B 是字符并且我们想按相反顺序排序
df[order(df[,1],-as.numeric(as.factor(df[,2]))),] ->这会将字段 A(数字)按升序排序,将字段 B(字符)按降序排序。
优先级给予 A。

其想法是,您可以仅在数字上应用 -sign 顺序函数。因此,要按降序对字符串进行排序,您必须将它们强制转换为数字。

Let df be the data frame with 2 fields A and B

Case 1: if your field A and B are numeric

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
priority is given to A.

Case 2: if field A or B is non numeric say factor or character

In our case if B is character and we want to sort in reverse order
df[order(df[,1],-as.numeric(as.factor(df[,2]))),] -> this sorts field A(numerical) in ascending and field B(character) in descending.
priority is given to 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.

橘亓 2024-12-17 00:48:18
    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)
    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)
风月客 2024-12-17 00:48:18

简单的没有等级的:

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

Simple one without rank :

rum[order(rum$I1, -rum$I2, decreasing = TRUE), ]
遗心遗梦遗幸福 2024-12-17 00:48:18

默认排序是稳定的,因此我们排序两次:首先按次键,然后按主键

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

The default sort is stable, so we sort twice: First by the minor key, then by the major key

rum1 <- rum[order(rum$I2, decreasing = FALSE),]
rum2 <- rum1[order(rum1$I1, decreasing = TRUE),]
玉环 2024-12-17 00:48:18
rum[order(rum$T1, -rum$T2 ), ]
rum[order(rum$T1, -rum$T2 ), ]
稍尽春風 2024-12-17 00:48:18

正确的做法是:

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

The correct way is:

rum[order(rum$T1, rum$T2, decreasing=c(T,F)), ]
此刻的回忆 2024-12-17 00:48:18

在@dudusan的示例中,您还可以反转 I1 的顺序,然后升序排序:

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

这似乎有点短,您不会反转 I2 的顺序两次。

In @dudusan's example, you could also reverse the order of I1, and then sort ascending:

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

This seems a bit shorter, you don't reverse the order of I2 twice.

深空失忆 2024-12-17 00:48:18

你可以使用令人惊奇的包 dplyr
有一个函数叫排列。
您只需考虑您选择的层次结构来设置数据框和要排序的列。默认为升序。但如果您想按降序排列,请使用命令 desc。

朗姆酒 <- read.table(textConnection("P1 P2 P3 T1 T2 T3 I1 I2
2 3 5 52 43 61 6 b
6 4 3 72 不适用 59 1 个
1 5 6 55 48 60 6 f
2 4 4 65 64 58 2 b"), header = TRUE)

库(dplyr)
安排(朗姆酒,desc(I1),I2)

you can use the amazing package dplyr
there is a function called arrange.
you just set the data-frame and the columns you want to order considering the hierarchy you choose. the defualt is ascending order. but if you want in descreasing order you use the command desc.

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)

library(dplyr)
arrange(rum,desc(I1),I2)

薄荷港 2024-12-17 00:48:18

一般来说,xtfrm() 是获取数值向量的通用函数
排序类似于给定的输入向量。然后可以通过减少排序来完成
使用 xtfrm() 的负值进行排序。 (这正是例如
dplyr 的 desc() 已实现。)

例如,对于有问题的数据:

df <- read.table(text = "
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)

df[order(-xtfrm(df$I1), df$I2), ]
#>   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

这种方法可以推广到基本 R 函数中进行排序
按给定列的数据帧,也接受向量值递减
争论。从我的回答
最近的问题

sortdf <- function(x, by = colnames(x), decreasing = FALSE) {
  x[do.call(order, Map(sortproxy, x[by], decreasing)), , drop = FALSE]
}

sortproxy <- function(x, decreasing = FALSE) {
  as.integer((-1)^as.logical(decreasing)) * xtfrm(x)
}

通过当前的示例数据,我们(当然)得到:

sortdf(df, by = c("I1", "I2"), decreasing = c(TRUE, FALSE))
#>   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

In general, xtfrm() is the generic function to get a numeric vector that
sorts like the given input vector. Decreasing sorting can then be done by
sorting with the negated value of xtfrm(). (This is exactly how e.g.
dplyr’s desc() is implemented.)

For example, with the data in question:

df <- read.table(text = "
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)

df[order(-xtfrm(df$I1), df$I2), ]
#>   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

This approach can be generalized into a base R function to sort
data frames by given columns, that also accepts a vector-valued decreasing
argument. From my answer to
this recent question:

sortdf <- function(x, by = colnames(x), decreasing = FALSE) {
  x[do.call(order, Map(sortproxy, x[by], decreasing)), , drop = FALSE]
}

sortproxy <- function(x, decreasing = FALSE) {
  as.integer((-1)^as.logical(decreasing)) * xtfrm(x)
}

And with the current example data, we (of course) get:

sortdf(df, by = c("I1", "I2"), decreasing = c(TRUE, FALSE))
#>   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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文