在为程序员阅读 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)))
我看到函数长度等于计数,我可以写奇数吗?那么有内置的地图/过滤器/删除类型功能吗?
在为程序员阅读 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)))
我看到函数长度等于计数,我可以写奇数吗?那么有内置的地图/过滤器/删除类型功能吗?
在 R 中,当您使用向量时,人们通常更喜欢一次处理整个向量,而不是循环遍历它(例如,参见这个讨论)。
从某种意义上说,R 确实具有“内置”过滤器和归约函数:您可以选择向量子集的方式。它们在 R 中非常方便,并且有几种方法可以解决 - 我将向您展示几个,但是如果您阅读 R 并在这样的网站上查看其他人的代码,您会学到更多。我还会考虑查看?which
and ?'['
,其中的示例比我在这里做的要多。
第一种方法是简单地选择您想要的元素。如果您知道所需元素的索引,则可以使用它:
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 新手,理解它将为您节省很多时间和将来的痛苦,所以我想我将与您分享几种方法。
一种更 R 的方法是避免for
循环,并使用矢量化:
oddcount <- function(x) {
sum(x %% 2)
}
和 2之间的比较x
输出一个向量,因为x
它本身就是一个向量。Sum than 计算向量的和,其中TRUE
等于 1 且FALSE
等于 0。通过这种方式,函数计算向量中奇数的个数。
这已经导致更简单的语法,尽管对于非向量化的人来说,for
循环往往更容易阅读。我非常喜欢矢量化语法,因为它要短得多。不过,我更愿意使用更具描述性的名称x
,例如number_vector
.
您应该查看funprog库,其中包括map
、filter
等reduce
。