output[i] <- mean(df[[i]]) } output }
但接着你想到,如果还能计算中位数和标准差会更有帮助,于是你复制并粘贴了 col_mean() 函数,把 mean() 替换为 median() 和 sd():
col_median <- function(df) { output <- vector("double", length(df)) for (i in seq_along(df)) { output[i] <- median(df[[i]]) } output } col_sd <- function(df) { output <- vector("double", length(df)) for (i in seq_along(df)) { output[i] <- sd(df[[i]]) } output }
糟糕!你已经把这段代码复制粘贴了两次,是时候考虑如何将它泛化了。注意,这段代码的大部分都是 for 循环的样板代码,很难看出函数之间唯一不同的地方(mean()、median()、sd())。
如果你看到一组这样的函数,你会怎么做?
f1 <- function(x) abs(x - mean(x)) ^ 1 f2 <- function(x) abs(x - mean(x)) ^ 2 f3 <- function(x) abs(x - mean(x)) ^ 3
希望你能注意到其中存在大量重复,并将其提取为一个额外的参数:
f <- function(x, i) abs(x - mean(x)) ^ i
这样你减少了出 bug 的可能性(因为代码量减少了 1/3),并且更容易推广到新的情形。
我们可以对 col_mean()、col_median() 和 col_sd() 做完全一样的事情:添加一个参数,用于提供要应用到每一列的函数:
col_summary <- function(df, fun) { out <- vector("double", length(df)) for (i in seq_along(df)) {