为sort.data.frame创建通用/方法一致性的最佳方法?

Ari*_*man 8 generics methods r class

我终于决定将在互联网上浮动的sort.data.frame方法放入R包中.它只是被要求太多而无法留给临时分发方法.

但是,它使用参数编写,使其与泛型排序函数不兼容:

sort(x,decreasing,...)
sort.data.frame(form,dat)
Run Code Online (Sandbox Code Playgroud)

如果我sort.data.frame改为将减少作为参数sort.data.frame(form,decreasing,dat)并且丢弃减少,那么它就会失去它的简单性,因为你总是必须指定dat=并且不能真正使用位置参数.如果我将其添加到最后sort.data.frame(form,dat,decreasing),则顺序与泛型函数不匹配.如果我希望减少被赶上点`sort.data.frame(form,dat,...),那么当使用基于位置的匹配时,我相信泛型函数会将第二个位置分配给减少,它会得到丢弃.协调这两个功能的最佳方法是什么?

完整的功能是:

# Sort a data frame
sort.data.frame <- function(form,dat){
# Author: Kevin Wright
# http://tolstoy.newcastle.edu.au/R/help/04/09/4300.html
# Some ideas from Andy Liaw
# http://tolstoy.newcastle.edu.au/R/help/04/07/1076.html
# Use + for ascending, - for decending.
# Sorting is left to right in the formula
# Useage is either of the following:
# sort.data.frame(~Block-Variety,Oats)
# sort.data.frame(Oats,~-Variety+Block)

# If dat is the formula, then switch form and dat
  if(inherits(dat,"formula")){
    f=dat
    dat=form
    form=f
  }
  if(form[[1]] != "~") {
    stop("Formula must be one-sided.")
  }
# Make the formula into character and remove spaces
  formc <- as.character(form[2])
  formc <- gsub(" ","",formc)
# If the first character is not + or -, add +
  if(!is.element(substring(formc,1,1),c("+","-"))) {
    formc <- paste("+",formc,sep="")
  }
# Extract the variables from the formula
  vars <- unlist(strsplit(formc, "[\\+\\-]"))
  vars <- vars[vars!=""] # Remove spurious "" terms
# Build a list of arguments to pass to "order" function
  calllist <- list()
  pos=1 # Position of + or -
  for(i in 1:length(vars)){
    varsign <- substring(formc,pos,pos)
    pos <- pos+1+nchar(vars[i])
    if(is.factor(dat[,vars[i]])){
      if(varsign=="-")
        calllist[[i]] <- -rank(dat[,vars[i]])
      else
        calllist[[i]] <- rank(dat[,vars[i]])
    }
    else {
      if(varsign=="-")
        calllist[[i]] <- -dat[,vars[i]]
      else
        calllist[[i]] <- dat[,vars[i]]
    }
  }
  dat[do.call("order",calllist),]
} 
Run Code Online (Sandbox Code Playgroud)

例:

library(datasets)
sort.data.frame(~len+dose,ToothGrowth)
Run Code Online (Sandbox Code Playgroud)

had*_*ley 6

使用该arrange功能plyr.它允许您单独选择哪些变量应按升序和降序排列:

arrange(ToothGrowth, len, dose)
arrange(ToothGrowth, desc(len), dose)
arrange(ToothGrowth, len, desc(dose))
arrange(ToothGrowth, desc(len), desc(dose))
Run Code Online (Sandbox Code Playgroud)

它还有一个优雅的实现:

arrange <- function (df, ...) {
  ord <- eval(substitute(order(...)), df, parent.frame())
  unrowname(df[ord, ])
}
Run Code Online (Sandbox Code Playgroud)

而且desc只是一个普通的功能:

desc <- function (x) -xtfrm(x)
Run Code Online (Sandbox Code Playgroud)

xtfrm如果您正在编写此类函数,强烈建议您阅读帮助.

  • 谢谢.这似乎有望成为我的替代品.但我仍然很好奇如何制作一个通用的和它的方法一致,因为它经常出现在我身上.另外,从语法上讲,sort()方法似乎可以使事物与其他数据类型保持一致.但这是一些漂亮的代码:-) (2认同)

Rei*_*son 5

那里有一些问题。sort.data.frame需要具有与泛型相同的参数,所以至少它需要是

sort.data.frame(x, decreasing = FALSE, ...) {
....
}
Run Code Online (Sandbox Code Playgroud)

要进行调度工作,第一个参数需要是被调度的对象。所以我会开始:

sort.data.frame(x, decreasing = FALSE, formula = ~ ., ...) {
....
}
Run Code Online (Sandbox Code Playgroud)

哪里x是你的datformula是你的form,我们为公式提供了一个默认值来包含所有内容。(我还没有详细研究你的代码以确切了解form代表什么。)

当然,你不需要decreasing在调用中指定,所以:

sort(ToothGrowth, formula = ~ len + dose)
Run Code Online (Sandbox Code Playgroud)

将是如何使用上述规范调用函数。

否则,如果您不想sort.data.frame成为 S3 泛型,则将其称为其他名称,然后您就可以随意使用任何您想要的参数。