在 R 中编写向量化函数

Ann*_*ick 5 r function vectorization

我写了以下函数:

asteriks = function(pvalue){
  if(pvalue > 0.05){
    output = "NS"
  }else if (pvalue <=0.05 & pvalue >0.01){
    output = "*"
  }else if (pvalue <=0.01 & pvalue >0.001){
    output = "**"
  }else if (pvalue <=0.001 & pvalue >0.0001){
    output = "***"
  }else if (pvalue <=0.0001){
    output = "****"
  }
  return(output)
}
Run Code Online (Sandbox Code Playgroud)

当我提供长度为 1 的参数时它工作正常,但我希望该函数将长度 >1 的向量作为输入并返回相同长度的向量。

我想做的例子:

vector_pvals = c(0.1, 0.05, 0.001, 0.0001)
asteriks(vector_pvals)
Run Code Online (Sandbox Code Playgroud)

输出应该是这样的字符向量:

[1] "NS" "*" "***" "****"
Run Code Online (Sandbox Code Playgroud)

当然,我可以通过在for循环中使用该函数来实现这一点,但我实际上想在dplyr管道中使用它,因此能够为其提供整个向量会很好。答案是for在函数中使用循环来一次处理每个元素,还是有更简单的方法?

Oli*_*ver 7

这里你不需要编写自己的函数。cut正是您正在寻找的(这是迄今为止最简单的方法)

pvalues <- seq(0, 0.1, by = 0.0001)
cut(pvalues,
    breaks = c(-Inf, 0.0001, 0.001, 0.01, 0.05, Inf), 
    include.lowest = TRUE, 
    right = FALSE, 
    labels = c('****', '***', '**', '*', 'NS'))
Run Code Online (Sandbox Code Playgroud)

如果您想使其成为“向量化”的练习,您可以通过多种方式转换您的函数,两种方式都使用ifelse另一个答案的建议,创建匹配每个组的索引或使用多个索引。ifelse是最简单的方法。


use*_*330 3

使用ifelse而不是if. 它被设计为矢量化。你的函数可以写成

asteriks = function(pvalue){
  ifelse(pvalue > 0.05, "NS",
  ifelse(pvalue > 0.01, "*",
  ifelse(pvalue > 0.001, "**",
  ifelse(pvalue >0.0001, "***", "****"))))
}
Run Code Online (Sandbox Code Playgroud)

对于其他无法进行更复杂计算的函数,您可以使用该Vectorize()函数将函数转换为向量化形式(通过在内部运行循环)。例如,

asteriksV <- Vectorize(asteriks)
Run Code Online (Sandbox Code Playgroud)

现在asteriksV即使使用您最初的定义也可以工作asteriks