【问题标题】:Writing a vectorised function in R [duplicate]在R中编写向量化函数[重复]
【发布时间】:2022-01-06 21:31:44
【问题描述】:

我写了以下函数:

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)
}

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

我想做的例子:

vector_pvals = c(0.1, 0.05, 0.001, 0.0001)
asteriks(vector_pvals)

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

[1] "NS" "*" "***" "****"

当然,我可以通过在for-loop 中使用该函数来实现这一点,但我实际上想在dplyr 管道中使用它,所以能够只提供一个完整的向量就好了.答案是在函数中使用for-loop 来一次处理每个元素,还是有更简单的方法?

【问题讨论】:

    标签: r function vectorization


    【解决方案1】:

    在这里您不需要编写自己的函数。 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'))
    

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

    【讨论】:

      【解决方案2】:

      使用ifelse 代替if。它被设计为矢量化。你的函数可以写成

      asteriks = function(pvalue){
        ifelse(pvalue > 0.05, "NS",
        ifelse(pvalue > 0.01, "*",
        ifelse(pvalue > 0.001, "**",
        ifelse(pvalue >0.0001, "***", "****"))))
      }
      

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

      asteriksV <- Vectorize(asteriks)
      

      现在asteriksV 甚至可以使用您对asteriks 的原始定义。

      【讨论】:

      • 谢谢,这两种解决方案都运行良好,vectorize() 选项也非常适合作为通用解决方案。我猜如果有更多嵌套的ifelse 语句系列可能会让人感到困惑,在这种情况下,使用上面建议的cut 的解决方案可能会更容易。
      【解决方案3】:

      在 10 次方处休息 strrep:

      asteriks <- function(pvalue) {
        ifelse(pvalue > 0.05, "NS", strrep("*", pmin(-log10(pvalue), 4)))
      }
      
      asteriks(c(0.1, 0.05, 0.001, 0.0001))
      #> [1] "NS"   "*"    "***"  "****"
      

      【讨论】:

        【解决方案4】:

        只是为了总结不同方法的练习。

        asteriks <- function(p) {
          v <- c("*" = 0.05, "**" = 0.01, "***" = 0.001, "****" = 0.0001)
          ifelse(p > max(v), "NS", names(v[v <= p][1]))
        }
        
        vector_pvals = c(0.1, 0.05, 0.001, 0.0001)
        
        unlist(lapply(vector_pvals, asteriks))
        
        [1] "NS"   "*"    "***"  "****"
        

        【讨论】:

          猜你喜欢
          • 2011-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多