【问题标题】:Pass logical expression to function for data.table in R将逻辑表达式传递给 R 中 data.table 的函数
【发布时间】:2020-09-07 01:24:23
【问题描述】:

我想将一个数值传递给一个函数,在该函数中我将使用它来选择数据表中的行。这是一个简单的例子,其中的数字量是一个日期:

#' Example
library(data.table)
library(ggplot2)

test <- function(date = NULL){
  DT <- as.data.table(economics)
  if (!is.null(date)){
    date <- as.Date(date)
# See https://stackoverflow.com/questions/21658893/subsetting-data-table-using-variables-with-same-name-as-column
    DT <- DT[eval(DT[,date %in% ..date])] # Pick one date
  }
  DT
}

请注意,它使用推荐的第二种方法here 为函数参数使用与 data.table 列相同的名称。

这适用于以下调用:

junk <- test(date = "1970-01-01")

还要注意,在现实生活中,我不会使用示例中使用的数据集。相反,我将从here 下载联合国人口数据。这是相关的,因为此数据集仅按年份对数值进行日期编码,因此无需像示例中那样使用 as.Date() 进行转换。

所以调用看起来更像:

   junk <- test(date = 1970)

这就是问题所在。除了将单个值作为日期传递之外,我还想传递逻辑表达式。但是最好的方法是什么?

为方便起见,让我们将“..date”作为对日期参数的引用与“date”作为对日期列名称的引用进行区分。

在示例函数中,对DT的第二个修改当前使用:

   DT <- DT[date %in% ..date],

其中 ..date 已从字符转换为日期。因为我正在使用将日期编码为数值的数据集,所以这种转换是不必要的。 (但调用代码有时可能需要将数值转换为日期。)

现在我想要类似的东西

   DT <- DT [date ..date],

其中 ..date 可以是逻辑表达式的后端,例如“

因此,就数据表子集的简单选择而言,有时可以评估为:

   DT <- [date == 1970],

其他时间为:

   DT <- [date <= 1970]

实现这一点的最佳方法是什么?

【问题讨论】:

    标签: r function date data.table arguments


    【解决方案1】:

    试试这个:

    test <- function(..., .data = data.table::as.data.table(economics)) {
      ind <- Reduce(`&`, eval(substitute(list(...)), envir = .data))
      .data[ind,]
    }
    

    它支持:

    • 单个参数,任意长度/复杂度,将在.data 的上下文中解析:

      test(date > as.Date("1969-01-01") & date < as.Date("1970-01-01"))
      #           date   pce    pop psavert uempmed unemploy
      #  1: 1969-02-01 588.7 201881     9.7     4.9     2692
      #  2: 1969-03-01 588.9 202023    10.2     4.0     2712
      #  3: 1969-04-01 593.9 202161     9.7     4.0     2758
      #  4: 1969-05-01 600.3 202331    10.1     4.2     2713
      #  5: 1969-06-01 600.9 202507    11.1     4.4     2816
      #  6: 1969-07-01 602.7 202677    11.8     4.4     2868
      #  7: 1969-08-01 609.9 202877    11.5     4.4     2856
      #  8: 1969-09-01 613.2 203090    11.6     4.7     3040
      #  9: 1969-10-01 618.5 203302    11.4     4.5     3049
      # 10: 1969-11-01 620.5 203500    11.6     4.8     2856
      # 11: 1969-12-01 622.8 203675    11.8     4.6     2884
      
    • 任意数量的参数,结合逻辑矢量化&amp;

      test(date > as.Date("1969-01-01"), date < as.Date("1970-01-01"))
      
    • 设置成员资格(标准 R)

      test(date %in% as.Date(c("1969-04-01", "1969-07-01")))
      #          date   pce    pop psavert uempmed unemploy
      # 1: 1969-04-01 593.9 202161     9.7     4.0     2758
      # 2: 1969-07-01 602.7 202677    11.8     4.4     2868
      

    它没有特定的date 参数,但如果您正在寻找集合成员资格、平等或不平等的各种组合,我认为最好“让”您使用date == 1970 而不是@987654329 @(这将是一个命名参数)。

    添加一个命名参数date= 可能是可行的,如果!missing(date) 将用于集合成员资格。

    test2 <- function(..., date, .data = data.table::as.data.table(economics)) {
      ind <- Reduce(`&`, eval(substitute(list(...)), envir = .data))
      if (!missing(date)) {
        stopifnot("date" %in% colnames(.data))
        ind <- ind & .data[["date"]] %in% date
      }
      .data[ind,]
    }
    
    test2(date > as.Date("1969-01-01"), date < as.Date("1970-01-01"), 
          date = as.Date("1969-07-01")) # this 'date=' is different than 'date' in line above
    #          date   pce    pop psavert uempmed unemploy
    # 1: 1969-07-01 602.7 202677    11.8     4.4     2868
    

    但我不清楚这如何增加任何功能。 (我想这取决于您的具体用途。)

    【讨论】:

      猜你喜欢
      • 2012-05-27
      • 2011-06-09
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      相关资源
      最近更新 更多