【问题标题】:Concatenate expressions to subset a dataframe连接表达式以子集数据帧
【发布时间】:2011-07-28 17:22:02
【问题描述】:

我正在尝试创建一个函数来计算子集数据框中列的平均值。这里的诀窍是我总是希望有几个子集条件,然后可以选择将更多条件传递给函数以进一步子集数据帧。

假设我的数据如下所示:

dat <- data.frame(var1 = rep(letters, 26), var2 = rep(letters, each = 26), var3 = runif(26^2))

head(dat)
  var1 var2      var3
1    a    a 0.7506109
2    b    a 0.7763748
3    c    a 0.6014976
4    d    a 0.6229010
5    e    a 0.5648263
6    f    a 0.5184999

我希望能够完成下面显示的子集,在所有函数调用中使用第一个条件,第二个条件可以随着每个函数调用而改变。此外,第二个子集条件可以在其他变量上(我使用单个变量 var2 表示简约,但条件可能涉及多个变量)。

subset(dat, var1 %in% c('a', 'b', 'c') & var2 %in% c('a', 'b'))
   var1 var2      var3
1     a    a 0.7506109
2     b    a 0.7763748
3     c    a 0.6014976
27    a    b 0.7322357
28    b    b 0.4593551
29    c    b 0.2951004

我的示例函数和函数调用如下所示:

getMean <- function(expr) {  
  return(with(subset(dat, var1 %in% c('a', 'b', 'c') eval(expr)), mean(var3)))  
}
getMean(expression(& var2 %in% c('a', 'b')))

另一种调用可能如下所示:

getMean(expression(& var4 < 6 & var5 > 10))

非常感谢任何帮助。


编辑:在 Wojciech Sobala 的帮助下,我想出了以下函数,它让我可以选择传入 0 个或多个条件。

getMean <- function(expr = NULL) {
  sub <- if(is.null(expr)) { expression(var1 %in% c('a', 'b', 'c'))
  } else expression(var1 %in% c('a', 'b', 'c') & eval(expr))
  return(with(subset(dat, eval(sub)), mean(var3)))
}
getMean()
getMean(expression(var2 %in% c('a', 'b')))

【问题讨论】:

  • 你应该在子集函数subset(dat, var1 %in% c('a', 'b', 'c') & eval(expr) 中做一些小的改变(添加&)而不是调用getMean(表达式(var2 %in% c('a', 'b'))).
  • 太好了,这行得通。你想让你的回复成为答案,以便我接受吗?
  • 如果您要使用表达式,我认为您最好在自己的函数中复制子集的逻辑 - 您当前的尝试将创建很难修复的错误。
  • 谢谢,哈德利。我不清楚为什么会这样。你能指出一些可以解释为什么或如何去做的事情吗?

标签: r subset


【解决方案1】:

可以使用默认 expr=TRUE 来简化。

getMean <- function(expr = TRUE) {
  return(with(subset(dat, var1 %in% c('a', 'b', 'c') & eval(expr)), mean(var3)))
}

【讨论】:

    【解决方案2】:

    这就是我的处理方式。函数 getMean 使用了 R 方便的默认参数设置:

    getMean <- function(x, subset_var1, subset_var2=unique(x$var2)){
        xs <- subset(x, x$var1 %in% subset_var1 & x$var2 %in% subset_var2)
    
        mean(xs$var3)
    }
    
    getMean(dat, c('a', 'b', 'c'))
    [1] 0.4762141
    
    getMean(dat, c('a', 'b', 'c'), c('a', 'b'))
    [1] 0.3814149
    

    【讨论】:

    • 感谢您的回答。我在最初的帖子中不够清楚,因此我对其进行了编辑,以包括可以以各种方式对多个变量进行子集化。我不确定我需要如何对数据进行子集化,因此该函数需要足够灵活以处理%in%之外的其他方式。
    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    • 2021-02-16
    相关资源
    最近更新 更多