我经常希望在特定索引处添加新列; mutate()没有这个的简单实现,而add_column()通过.before和.after参数执行。我希望这两个函数在简单设置中表现相同,但它们不会。下面是MWE转换行索引到新变量。 R文档没有说清楚:为什么这两个函数的基本语法不同?
dat <- as.tibble(matrix(rnorm(1e4), nrow=100))
dat1 <- dat %>% mutate(id=row_number()) # works as expected
dat2 <- dat %>% add_column(id=row_number()) # throws error
dat3 <- dat %>% add_column(id=1:nrow(dat), .before=1) # works, but harder to read
答案 0 :(得分:3)
如果你检查这两个函数的代码,你会得到一些线索。
function (.data, ...)
{
UseMethod("mutate")
}
<environment: namespace:dplyr>
function (.data, ..., .before = NULL, .after = NULL)
{
df <- tibble(...)
if (ncol(df) == 0L) {
return(.data)
}
if (nrow(df) != nrow(.data)) {
if (nrow(df) == 1) {
df <- df[rep(1L, nrow(.data)), ]
}
else {
stopc("`.data` must have ", nrow(.data), pluralise_n(" row(s)",
nrow(.data)), ", not ", nrow(df))
}
}
extra_vars <- intersect(names(df), names(.data))
if (length(extra_vars) > 0) {
stopc(pluralise_msg("Column(s) ", extra_vars), pluralise(" already exist[s]",
extra_vars))
}
pos <- pos_from_before_after_names(.before, .after, colnames(.data))
end_pos <- ncol(.data) + seq_len(ncol(df))
indexes_before <- rlang::seq2(1L, pos)
indexes_after <- rlang::seq2(pos + 1L, ncol(.data))
indexes <- c(indexes_before, end_pos, indexes_after)
.data[end_pos] <- df
.data[indexes]
}
<environment: namespace:tibble>
首先,您会注意到它们来自两个不同的包,尽管它们都是tidyverse的一部分。
其次,您会看到mutate
使用指定的方法,而add_column
更多是使用r基础rlang编写的便捷函数。
我不确定这两个软件包的路线图,但是,如果没有已经提出或者分叉项目并提供拉取请求,我确定你可以提出增强功能。这将是一个有用的补充。
这已经在tidyverse/dplyr中提出,似乎已经在开发流程中,但尚未安排。