英文:
Creating multiple NEW columns using across() in R
问题
我理解你的问题是,你想使用mutate
创建不依赖于现有列的新列。
你可以使用以下方法创建新列,而不引用现有列:
tibble(
a = 1:5,
b = LETTERS[1:5]
) %>%
mutate(new_column = NA)
这将创建一个名为new_column
的新列,并将其填充为NA
。
希望这可以帮助到你!如果你有任何其他问题,请随时问。
英文:
The difference between my question and existing questions is that I want to create new columns with mutate
that do not depend on existing columns.
Some dummy data:
library(dplyr)
dat <- tibble(
a = 1:5,
b = LETTERS[1:5]
)
I know I can create new columns one-by-one like so
dat <- dat %>%
mutate(foo = NA, bar = NA, bar2 = NA)
And I can modify columns more conveniently using across
, e.g. :
new_vars <- c("foo", "bar", "bar2")
dat <- dat %>%
mutate(across(all_of(new_vars), ~ replace(., is.na(.), 0)))
But how do I create new columns without referencing existing columns in a similar manner? E.g. adding new columns filled with NA
:
tibble(
a = 1:5,
b = LETTERS[1:5]
) %>%
# mutate(across(all_of(new_vars), ~ function(.x) NA)) # Error
mutate(across(all_of(new_vars), NA)) # Error
Open to any tidyverse
alternatives.
答案1
得分: 4
类似于这个答案中提到的方法,你可以使用以下代码:
new_vars <- c("foo", "bar", "bar2")
tibble(
a = 1:5,
b = LETTERS[1:5]
) %>%
mutate(!!!setNames(rep(NA, length(new_vars)), new_vars))
# 或者(感谢 @joran)
# tibble::add_column(!!!setNames(rep(NA, length(new_vars)), new_vars))
输出结果为:
a b foo bar bar2
<int> <chr> <lgl> <lgl> <lgl>
1 1 A NA NA NA
2 2 B NA NA NA
3 3 C NA NA NA
4 4 D NA NA NA
5 5 E NA NA NA
请注意,这是一段R代码,用于在数据框中添加指定名称的空列。
英文:
Similar to this answer buried in the popular question here, you can use:
new_vars <- c("foo", "bar", "bar2")
tibble(
a = 1:5,
b = LETTERS[1:5]
) %>%
mutate(!!!setNames(rep(NA, length(new_vars)), new_vars))
# or (thanks @joran)
# tibble::add_column(!!!setNames(rep(NA, length(new_vars)), new_vars))
output
a b foo bar bar2
<int> <chr> <lgl> <lgl> <lgl>
1 1 A NA NA NA
2 2 B NA NA NA
3 3 C NA NA NA
4 4 D NA NA NA
5 5 E NA NA NA
答案2
得分: 4
我尽量避免使用过多的tidyverse工具,但是为了避免简单的方法,我们正在做一些有点荒谬的事情,我个人认为。
这里是一个友好的管道示例:
library(dplyr)
dat <- tibble(
a = 1:5,
b = LETTERS[1:5]
)
new_vars <- c("foo", "bar", "bar2")
# ?
# dat[new_vars] <- NA
add_vars <- function(df, vars, val) {
df[vars] <- val
df
}
dat %>%
add_vars(df = ., vars = new_vars, val = NA)
你甚至可以使用匿名函数(但只能与magrittr管道一起使用):
dat %>%
(\(x) {x[new_vars] <- NA; x})
这也适用于function(x)
语法(与magrittr管道一起使用)。
英文:
I use tidyverse stuff as much as the next fellow, but the lengths we're going to to avoid doing things the simple way is getting a little silly, imho.
Here. Pipe friendly.
library(dplyr)
dat <- tibble(
a = 1:5,
b = LETTERS[1:5]
)
new_vars <- c("foo", "bar", "bar2")
# ?
# dat[new_vars] <- NA
add_vars <- function(df,vars,val){
df[vars] <- val
df
}
dat |>
add_vars(df = _,vars = new_vars,val = NA)
You could even use an anonymous function (but only with the magrittr pipe):
dat %>%
(\(x) {x[new_vars] <- NA; x})
This also works (with the magrittr pipe) with the function(x)
syntax.
答案3
得分: 3
使用dplyr::bind_cols()
和管道:
library(dplyr)
tibble(a = 1:5,
b = LETTERS[1:5]) %>%
bind_cols(., setNames(lapply(new_vars, function(x) x = NA), new_vars))
结果:
# A tibble: 5 × 5
a b foo bar bar2
<int> <chr> <lgl> <lgl> <lgl>
1 1 A NA NA NA
2 2 B NA NA NA
3 3 C NA NA NA
4 4 D NA NA NA
5 5 E NA NA NA
虽然我认为这个问题的第二个答案也很好。
如果你真的想要使用mutate
,Ritchie在评论中的答案也可以。
英文:
Using dplyr::bind_cols()
and pipes:
library(dplyr)
tibble(a = 1:5,
b = LETTERS[1:5]) %>%
bind_cols(., setNames(lapply(new_vars, function(x) x = NA), new_vars))
Result:
# A tibble: 5 × 5
a b foo bar bar2
<int> <chr> <lgl> <lgl> <lgl>
1 1 A NA NA NA
2 2 B NA NA NA
3 3 C NA NA NA
4 4 D NA NA NA
5 5 E NA NA NA
Although I think the second answer to this question, on which this is based, is just as good.
If you really want mutate
, Ritchie's answer in the comments works.
答案4
得分: 1
也许这是你正在寻找的样式:
library(dplyr)
dat <- tibble(
a = 1:5,
b = LETTERS[1:5]
)
new_vars <- c("foo", "bar", "bar2")
dat %>%
purrr::reduce(new_vars, ~mutate(.x, {{.y}} := 0), .init = .)
我们使用purrr::reduce()
而不是使用across()
,它将循环遍历new_vars
。我们将mutate
函数应用于上一次迭代的输出。我们想要以.init = dat
开始,但我们将其作为管道输入。
如果你想为每个new_vars
设置不同的值,甚至可以使用reduce2
。
英文:
Maybe this is the style you're looking for:
library(dplyr)
dat <- tibble(
a = 1:5,
b = LETTERS[1:5]
)
new_vars <- c("foo", "bar", "bar2")
dat %>%
purrr::reduce(new_vars, ~mutate(.x, {{.y}} := 0), .init = .)
Instead of using across()
we use purrr::reduce()
which will loop over the new_vars
. We apply the mutate
function to the output of the previous iteration. We want to start with .init = dat
, but we pipe it in.
You could even use reduce2
if you wanted to have different values for each of the new_vars
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论