【问题标题】:Order based on multiple columns passed in as an input基于作为输入传入的多列的顺序
【发布时间】:2018-03-08 00:55:32
【问题描述】:

我想编写一个函数,按任意数量的列对给定的 data.frame(我将其称为 dataSet)进行排序,其名称也传递给函数(在我将引用的向量中)为 orderList)。我知道要通过单个传入的字符串进行排序,您可以使用

sortDataset <- function(dataSet, sortCol) {
return(dataSet[order(dataSet[[sortCol]]),])
}

并且您可以使用多个传入的字符串进行排序

sortDataset <- function(dataSet, sortCol1, sortCol2) {
return(dataSet[order(dataSet[[sortCol1]], dataSet[[sortCol2]]),])
}

无论我想要多少 sortCol# 输入。但是,我希望能够传入任意数量的字符串列表。我尝试了以下方法:

dataSet[order(dataSet[[orderList]]),]
dataSet[order(dataSet$orderList),]
dataSet[order(dataSet[,orderList])]

并遇到了前 2 个问题,因为它们不是获取多列的有效方法(不过我仍然尝试过):)并且在第三个中,订单似乎不接受返回的矩阵以dataSet[,orderList]为参数。

我想要一个函数如下:

sortDataset <- function(dataSet, sortCols)

其中 sortCols 的第一个元素是优先级最高的列,然后第二列是第一个 tiebreaker,第三列是第二个 tiebreaker,以此类推,函数返回适当排序的 dataSet。如果我可以在可选输入中指定是否每个都应该升序,那也很好,所以第一列可以升序排序,第二列降序排序,等等。

到目前为止,我真正能想到的唯一方法是假设每个列表仅包含数值,然后将各个排序列乘以 10^n,以便所有列可以合并到一个列中维护优先级,然后按该列排序。不过,我觉得应该有更好的方法来做到这一点,因为这似乎是一个非常基本的功能。

【问题讨论】:

  • 听起来像 data.table::setorderv 函数

标签: r sorting dataframe


【解决方案1】:

使用do.call:

data[do.call("order", data[sortCols]), ]

其中data 是一个数据框,sortCols 是一个列名的字符向量。

还可以查看 doBy 包中的 orderBy

【讨论】:

    【解决方案2】:

    我们可以通过tidyverse 做到这一点

    library(dplyr)
    data %>%
         arrange_at(vars(sortCols))
    

    可以使用quos/1!!将其制成一个函数

    sortDataset <- function(dataSet, ...) {
       stopifnot(rlang::is_quosures(...))
       a1 <- c(...)
    
      dataSet %>%
          arrange(!!!  a1)
     }
    sortDataset(mtcars, quos(mpg, cyl))
    

    如果我们将变量作为字符串传递,则使用arrange_at

    sortDataset <- function(dataSet, ...) {
    
     a1 <- c(...)
    dataSet %>%
        arrange_at(vars(a1))
    }
    
    sortDataset(mtcars, "mpg", "cyl")
    

    正如@Nettle 在 cmets 中提到的,将arrange_atgroup_by 一起使用可能会导致一些错误(基于here

    【讨论】:

    猜你喜欢
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 2020-12-01
    相关资源
    最近更新 更多