这两天在尝试开发一个htmlwidgets包 https://github.com/Liripo/aggrid,封装aggrid, 遇到个编程小问题想请教下。

举个简单例子:

sortmodel <- data.frame(
  sort = c("asc","desc"),
  colid = c("Sepal.Length","Species")
)

我想根据上面的对象,对iris数据集进行排序,编程方式怎么写呢?

ps: 之所以搞这个包是很喜欢这个表格包的筛选样式,现在简单的支持了它的server模式,百万行也还行。

乱试出来一个能行的写法

sortmodel <- data.frame(
  desc = c(F, T),
  col = c('Sepal.Length', 'Species')
)

order_index <- do.call(
  function(...) {order(..., decreasing = sortmodel$desc)},
  lapply(sortmodel$col, function(col) {iris[[col]]})
)

iris[order_index, ]

核心思路就是想办法把sortmodel$colsortmodel$desc用参数的形式塞进下面这个式子里面

order_index <- order(iris[['Sepal.Length']], iris[['Species']], decreasing = c(F, T))

    meeeeeeeeo

    我尝试了下

    sortmodel <- data.frame(
      sort = c("asc","desc"),
      colid = c("Sepal.Length","Species")
    )
    true_index <- order(c(iris[['Sepal.Length']],iris[['Species']]),decreasing = sortmodel$sort == "desc")
    
    
    # 第一种
    order_index1 <- do.call(
      function(...) {order(..., decreasing = sortmodel$sort == "desc")},
      lapply(sortmodel$colid, function(col) {iris[[col]]})
    )
    
    cat("正确?",all(true_index == order_index1))
    # 第二种
    ord_expr <- rlang::call2("order",
                             rlang::parse_expr(sprintf("c(%s)",paste0("iris[['",sortmodel$colid,"']]",collapse = ","))),
      decreasing = sortmodel$sort == "desc")
    
    order_index2 <- eval(ord_expr)
    
    cat("正确?",all(true_index == order_index2))

    第一种似乎不对,但是我也没看出哪里有问题,第二种自己写的,又感觉很凌乱。
    输出如下:

    正确? FALSE
    正确? TRUE

      Liripo

      搞错了,第一种是对的,正确索引的代码写错,不好意思。

        Liripo

        chatgpt4的解答也挺好,记录下:

        library(dplyr)
        
        sort_iris <- function(data, sortmodel) {
          sort_expr <- lapply(1:nrow(sortmodel), function(i) {
            sort_col <- sortmodel$colid[i]
            sort_order <- sortmodel$sort[i]
            if (sort_order == "asc") {
              expr(!!sym(sort_col))
            } else {
              expr(desc(!!sym(sort_col)))
            }
          })
          
        sorted_data <- data %>% arrange(!!!sort_expr)
        return(sorted_data) } # 创建排序模型 sortmodel <- data.frame( sort = c("asc", "desc", "asc"), colid = c("Sepal.Length", "Species", "Petal.Width") ) # 加载iris数据集 data(iris) # 对iris数据集进行排序 sorted_iris <- sort_iris(iris, sortmodel) # 打印排序后的数据集 print(sorted_iris) ```