R 里面有个 which()
函数,我感觉很多人一旦学了就忘不了,总是想用。它可以把逻辑向量转化为整数向量,这些整数表示哪些位置上的值是 TRUE
,如 which(c(F, T, F))
就会返回 2。我见过好些人在用下标索引的时候硬生生把逻辑向量用 which()
转一下,比如 x[which(y)]
(y
是逻辑向量),这个 which()
的调用完全没必要,因为 R 有三种索引方式:整数值、逻辑值、字符(名字)。可能一般人还是习惯整数索引吧。
作为强迫症患者,我尽量不做无谓的强迫,尽管这个有点难。比如要不要提出来 which()
是不必要的,其实不能完全根据自己的喜好来判断,而是要客观测量它究竟有多糟糕。糟不糟糕,主要准则应该是速度,比如用了 which()
会导致代码显著变慢吗?理论上多调用一个函数肯定会更慢,但我用三秒钟的时间想了一下,万一 which()
慢,但整数索引比逻辑索引更快,那时间有没有可能追回来?
空谈误国,放码过来。前方测速区:
n = 100000
x = runif(n)
i = logical(n)
i[sample(n, n/4)] = TRUE
microbenchmark::microbenchmark(x[i], x[which(i)], times = 1000)
跑了一下,貌似没那么糟糕。
Unit: microseconds
expr min lq mean median uq max neval
x[i] 362.4 488.6 719.6 577.2 669.7 6723 1000
x[which(i)] 438.4 581.3 900.7 670.2 795.8 82968 1000
我还有个类似的洁癖,就是不愿意看到 if (x == TRUE)
这种写法,if (x)
就足够。去年在芝加哥参加 JSM 的时候我已经吐槽过一次。不过呢,把 TRUE
写出来倒也不是完全没有好处:它的潜在好处是快速扫描代码的时候很容易知道这里有个逻辑值,因为这四个大写字母比较耀眼。