USArrests 是 R 附带的一个数据集, 现在我们需要创建一个 factor 向量 urbancat, 如果 UrbanPop 列的某个值在中位数之上, 就把 urbancat 对应位置的值设为 1, 否则设为 0.
这种数据处理任务实在太简单了, 一个 for 循环就能搞定. 首先, 我们计算一下 UrbanPop 的中位数:
urbanPop.median <- median(USArrests$UrbanPop)
然后, 用 rep 函数初始化一个等长的 urbancat 向量:
urbancat <- rep(x = 0, times = length(USArrests$UrbanPop))
接着, 用 for 循环为 urbancat 设置对应位置的值:
- for (i in 1:length(urbancat)) {
- if (USArrests$UrbanPop[i]> urbanPop.median) {
- urbancat[i] <- 1
- }
- }
以上代码对于拥有命令式编程背景的同学来说是非常亲切自然的. 值的提醒的是, 如果 urbancat 的长度有可能为 0, 那么使用 1:length(urbancat)可能会有非预期结果 (你可以试一下), 这个时候我们建议把 1:length(urbancat) 换成 seq_along(urbancat).
对于拥有函数式编程背景的同学, 可以使用 purrr 的 map 函数:
- library(purrr)
- urbancat <- map_dbl(USArrests$UrbanPop, function(x) if (x> urbanPop.median) 1 else 0)
map_dbl 会在应用你传入的匿名函数之后以 double 向量的方式返回结果. 如果你喜欢用 formula, 也可以把匿名函数换成 formula:
urbancat <- map_dbl(USArrests$UrbanPop, ~ if (.x> urbanPop.median) 1 else 0)
这里的. x 表示 map_dbl 传给你的 UrbanPop 列的某个值.
在接触 R 之前, 我基本上都会选择 FP 的做法, 但在接触 R 之后, 我被它的向量化运算以及通过逻辑值取子集 (logical subsetting) 的做法深深吸引:
urbancat[USArrests$UrbanPop> urbanPop.median] <- 1
USArrests$UrbanPop 是一个向量, 而 urbanPop.median 是一个值, 因为 R 默认支持向量化运算, 所以拿 USArrests$UrbanPop 和 urbanPop.median 比较会自动转化成拿 USArrests$UrbanPop 里的每个值和 urbanPop.median, 得到一个和 USArrests$UrbanPop 等长的由逻辑值 (T 和 F) 组成的向量(F F T F T ......). 当我们用这个逻辑值向量去索引 urbancat 时, 就会取出逻辑值为 T 的对应元素, 这个时候, 结合赋值运算就可以把这些元素都设为 1 了.
最后, 要把 urbancat 变成 factor 向量, 你可以修改 for 循环或者 map 函数, 但在 R 里, 你只需把 urbancat 传给 factor 函数就行了:
urbancat <- factor(urbancat)
Ruby 之父松本行弘在他的松本行弘的程序世界里说过,"在语言学领域里, 有一个 Sapir-Whirf 假说, 认为语言可以影响说话者的思想. 也就是说, 语言的不同, 造成了思想的不同. 程序员由于使用的编程语言不同, 他的思考方法和编写出来的代码都会受到编程语言的很大影响." 而这番话可以很好地概括我此时的感受.
来源: https://www.cnblogs.com/allenlooplee/p/9222173.html