【问题标题】:R Sort one column ascending, all others descending (based on column order)R对一列升序排序,所有其他降序(基于列顺序)
【发布时间】:2023-10-30 23:07:01
【问题描述】:

我有一个有序表,类似如下:

df <- read.table(text = 
"A   B   C   Size
1   0   0   1
0   1   1   2
0   0   1   1
1   1   0   2
0   1   0   1",
header = TRUE)

实际上会有更多的列,但这对于解决方案来说很好。

我希望首先按 SIZE(升序)对该表进行排序,然后按优先级顺序(降序)按 其他列 - 即首先按 A 列,然后 B 列,然后 C 列,等等。

问题是我不会提前知道列名,所以无法命名它们,但实际上需要“除 SIZE 之外的所有列”。

最终结果应该是:

A B C Size
1 0 0 1
0 1 0 1
0 0 1 1
1 1 0 2
0 1 1 2

我见过按两列排序的示例,但我只是找不到正确的语法来按“所有其他列顺序”排序。

非常感谢

【问题讨论】:

  • 所有这些列都是数字还是整数?

标签: r sorting multiple-columns


【解决方案1】:

像这样使用order 的名称。没有使用任何包。

o <- with(df, order(Size, -A, -B, -C))
df[o, ]

这给出了:

  A B C Size
1 1 0 0    1
5 0 1 0    1
3 0 0 1    1
4 1 1 0    2
2 0 1 1    2

或者不使用名称只使用列号:

o <- order(df[[4]], -df[[1]], -df[[2]], -df[[3]])

k <- 4
o <- do.call("order", data.frame(df[[k]], -df[-k]))

如果Size 始终是最后一列,请改用k &lt;- ncol(df),或者如果它不一定是最后一列但始终称为Size,则改用k &lt;- match("Size", names(df))

注意:虽然在问题中显示的示例中不需要,但如果列不是数字,则无法否定它们,因此更通用的解决方案是将上面的第一行替换为以下内容其中xtfrm 是一个 R 函数,它将对象转换为数字,以便结果按预期顺序排序。

o <- with(df, order(Size, -xtfrm(A), -xtfrm(B), -xtfrm(C)))

【讨论】:

  • 列是数字,但我不想明确命名它们,因为它们在每次执行中可能不同。
  • 见注释前最后的补充。
【解决方案2】:

我们可以从dplyr使用arrange

library(dplyr)
arrange(df, Size, desc(A), desc(B), desc(C))

更多列数,可以使用arrange_

cols <-  paste0("desc(", names(df)[1:3], ")")
arrange_(df, .dots = c("Size", cols))

【讨论】: