【问题标题】:sapply with multiple set of arguments to an user defined functionsapply 为用户定义的函数提供多组参数
【发布时间】:2020-09-08 14:23:52
【问题描述】:

我有一个数据框df 并想使用函数range_frac 来执行操作。

set.seed(137)
df <- data.frame(col1 = sample(LETTERS, 100, TRUE), 
                 col2 = sample(-75:75, 100, TRUE), 
                 col3 = sample(-75:75, 100, TRUE))

df$col2[c(23, 48, 78)] <- NA
df$col3[c(37, 68, 81)] <- NA


range_frac <- function(n, my_df, my_var) {

  len = sum(my_df[my_var] < n, na.rm = TRUE)
  len
}

我想分别知道col2col3 中满足上述条件的行数。由于我没有成功传递列名,所以我传递了列索引(23)。但是,当我尝试为my_var 传递一个向量时,它会汇总各个值的输出。这是怎么发生的?

sapply(1:3, range_frac, my_df = df, my_var = 2) 
[1] 57 57 57

sapply(1:3, range_frac, my_df = df, my_var = 3) 
[1] 51 51 52

sapply(1:3, range_frac, my_df = df, my_var = 2:3) 
[1] 108 108 109

有人可以解释第三次操作(即 57+51、57+51、57+52)的结果吗?

(基本上,我正在尝试以dyplr-summarise 的方式实现以下输出,但停留在这一点上并认为我会清除对这个概念的理解)。

n col2 col3
1 57 51
2 57 51
3 57 52

更新:我问了一个不清楚的问题,所以用更多信息更新它。解决方法如下:

对于每个n,解决方案可以理解为表达式的求值 sum(df[,2:3] &lt; n, na.rm = TRUE) 而不是单独用于列 2&3

【问题讨论】:

    标签: r dplyr sapply


    【解决方案1】:

    如果你输入2:3my_varrange_frac()实际执行

    sum(df[2:3] < n, na.rm = TRUE)
    

    对于每个n。当然,第二列和第三列中的元素数量少于n。一种解决方案是将参数 my_var 矢量化,即

    sapply(1:3, Vectorize(range_frac, "my_var"), my_df = df, my_var = 2:3)
    
    #      [,1] [,2] [,3]
    # [1,]   48   48   48
    # [2,]   49   51   51
    

    【讨论】:

    • 感谢您的回答。如果我在检查时更加谨慎,我本可以避免这个问题!我正在询问我现在发现的输出背后的解释,因为它是以sum(df[,2:3] &lt; 1, na.rm = TRUE) 的形式评估的。很抱歉浪费了您的时间。
    • @Prradep 我在回答的开头已经解释过了,和你找到的一样。
    • 谢谢,我接受了解决方案。您能否还评论一下如何传递列名而不是索引。这不是一个新问题,我在原始问题中也提到过(由于我没有成功传递列名,所以我传递了列索引(23))。
    • @Prradep 我认为用my_var = c("col2", "col3") 替换my_var = 2:3 是可以的!
    【解决方案2】:

    我们以下面的代码为例

    sapply(1:3, range_frac, my_df = df, my_var = 2:3) 
    

    这里,1:3 作为第一个参数传递给range_frac,相当于迭代,例如,

    for (i in 1:3) {
         range_frac(...)
    }
    

    sapplymy_df = dfmy_var = 2:3 内作为第二个和第三个参数传递给range_frac。因此,整个sapply 行可以解释为

    res <- c()
    for (i in 1:3) {
         res[i] <- range_frac(i, df, 2:3)
    }
    

    一些解决方法

    sapply(1:3,Vectorize(range_frac,"my_var"),my_df = df, my_var = 2:3)
    
    sapply(1:3,function(k) sapply(2:3,function(v) range_frac(k,df,v)))
    

    【讨论】:

    • 您能否还包括my_var = 2:3 在输出中的作用。我猜是sum(df[,2:3] &lt; 1, na.rm = TRUE)。我本来可以正确检查的,抱歉。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 2019-03-27
    • 2018-06-07
    • 2013-01-07
    • 2023-01-29
    相关资源
    最近更新 更多