【问题标题】:A basic R function一个基本的 R 函数
【发布时间】:2012-07-29 03:38:14
【问题描述】:

在为程序员阅读 R 时,我看到了这个函数

oddcount <- function(x) {
  k <- 0
  for (n in x) {
    if (n %% 2 == 1) k <- k+1
  }
  return(k)
}

我更喜欢用更简单的风格(即 lisp)来编写它

(defn odd-count [xs]
  (count (filter odd? xs)))

我看到函数长度等于count,我可以写奇数吗?那么有内置的 map/filter/remove 类型的函数吗?

【问题讨论】:

    标签: r


    【解决方案1】:

    在 R 中,当您使用向量时,人们通常更喜欢一次处理整个向量,而不是循环遍历它(例如,参见 this 讨论)。

    从某种意义上说,R 确实具有“内置”过滤器和归约函数:您可以选择向量子集的方式。它们在 R 中非常方便,并且有几种方法可以解决 - 我将向您展示几个,但是如果您阅读 R 并在这样的网站上查看其他人的代码,您会学到更多。我还会考虑查看?which?'[',这比我这里有更多的例子。

    第一种方法是简单地选择您想要的元素。如果您知道所需元素的索引,则可以使用它:

    x <- letters[1:10]
    > x
     [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
    

    如果我们只想要前五个字母,我们可以这样写:

    x[1:5]
    x[c(1,2,3,4,5)] # a more explicit version of the above
    

    您还可以通过使用减号来选择不需要的元素,例如:

     x[-(6:10)]
    

    另一种选择元素的方法是使用布尔向量:

    x <- 1:5
    selection <- c(FALSE, TRUE, FALSE, TRUE, FALSE)
    x[selection]   # only the second and fourth elements will remain
    

    这很重要,因为我们可以通过将向量放入比较函数中来创建这样的向量:

    selection <- (x > 3)
    > selection
     [1] FALSE FALSE FALSE  TRUE  TRUE
    
    x[selection]   # select all elements of x greater than 3
    x[x > 3]       # a shorthand version of the above
    

    再一次,我们可以选择与我们使用的比较相反的值(注意,因为它是布尔值,所以我们使用! 而不是-):

    x[!(x > 3)]    # select all elements less than or equal to 3
    

    如果你想做向量比较,你应该考虑%in% 函数。例如:

    x <- letters[1:10]
    > x %in% c("d", "p", "e", "f", "y")
     [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE
    
    # Select all elements of x that are also "d", "p", "e", "f", or "y"
    x[x %in% c("d", "p", "e", "f", "y")]  
    # And to select everything not in that vector:
    x[!(x %in% c("d", "p", "e", "f", "y"))]  
    

    以上只是几个例子;我肯定会推荐文档。我知道在您已经接受答案之后这是一篇很长的帖子,但是这种事情非常重要,如果您是 R 新手,理解它将为您节省很多时间和将来的痛苦,所以我想我将与您分享几种方法。

    【讨论】:

    • 谢谢,这绝对有帮助。
    【解决方案2】:

    执行此操作的更 R 方法是避免 for 循环,并使用矢量化:

    oddcount <- function(x) {
      sum(x %% 2)
    }
    

    x 和 2 之间的比较输出一个向量,因为x 本身就是一个向量。 Sum than 计算向量的和,其中TRUE 等于 1,FALSE 等于零。通过这种方式函数计算向量中奇数的个数。

    这已经导致更简单的语法,尽管对于非向量化的人来说,for 循环往往更容易阅读。我非常喜欢矢量化语法,因为它要短得多。不过,我更愿意为 x 使用更具描述性的名称,例如number_vector.

    【讨论】:

    • 在这种情况下,它可能会更短,你不需要==1,因为%% 只会返回 0 和 1。使用sum(x %% 2)。这也可能会快一点,因为您没有生成逻辑并将它们转换回数字。有些人可能会发现较长的版本更具可读性(如果您要将其扩展为查找不是 2 的倍数或不是倍数的数字,那么您将需要较长的版本。
    【解决方案3】:

    你应该看看funprog库,其中包括mapfilterreduce等。

    【讨论】:

    • 谢谢,length(Filter(odd_p, xs)) 似乎可以完成这项工作,但是根据最后一个答案,我似乎问错了问题:)
    • 使用funprog没有什么问题,但是使用标准的R你可以在代码中得到同样的简洁。
    • 这很好,@Paul。试图将一种使用一种范式(矢量化)的语言强制转换为另一种范式(函数式)通常会导致不必要的冗长代码。
    猜你喜欢
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2021-10-08
    • 2020-09-16
    相关资源
    最近更新 更多