#r #for-loop
#r #для цикла
Вопрос:
У меня следующая настройка
df_names <- c("df1", "df2", "df3")
df1 <- tibble("1" = "hallo")
df2 <- tibble("1" = "hallo")
df3 <- tibble("1" = "hallo")
missing_columns <- c("2", "3")
Моя цель — добавить к каждому фрейму данных столбцы, которые видны в missing_columns .
Я пытался
for(i in df_names){
for(j in missing_columns){
get(i)[, j] <- ""
}
}
Error in get(i) <- `*vtmp*` : could not find function "get<-"
и
for(i in df_names){
for(j in missing_columns){
assign(get(i)[, j], "")
}
}
Error: Can't subset columns that don't exist.
x Column `2` doesn't exist.
Конечно, столбец 2 не существует, поэтому я хочу его добавить.
Комментарии:
1. Просто сделайте
df1[["2"]] <- "foo"
2. Это не сработало бы для меня, поскольку я пишу о чем-то, где столбцы, которые нужно добавить, и количество фреймов данных различаются. Вот почему у меня есть вектор имен фреймов данных и вектор отсутствующих столбцов. И именно поэтому я подумал, что использование for-цикла может быть правильным выбором.
Ответ №1:
Вам необходимо назначить объект глобальной среде, чтобы иметь к ним доступ после выполнения кода:
library(tidyverse)
df_names <- c("df1", "df2", "df3")
df1 <- tibble("1" = "hallo")
df2 <- tibble("1" = "hallo")
df3 <- tibble("1" = "hallo")
missing_columns <- c("2", "3")
df1
#> # A tibble: 1 x 1
#> `1`
#> <chr>
#> 1 hallo
df2
#> # A tibble: 1 x 1
#> `1`
#> <chr>
#> 1 hallo
expand_grid(
col = missing_columns,
df = df_names
) %>%
mutate(
new_df = map2(col, df, ~ {
res <- get(.y)
res[[.x]] <- "foo"
assign(.y, res, envir = globalenv())
})
)
#> # A tibble: 6 x 3
#> col df new_df
#> <chr> <chr> <list>
#> 1 2 df1 <tibble [1 × 2]>
#> 2 2 df2 <tibble [1 × 2]>
#> 3 2 df3 <tibble [1 × 2]>
#> 4 3 df1 <tibble [1 × 3]>
#> 5 3 df2 <tibble [1 × 3]>
#> 6 3 df3 <tibble [1 × 3]>
df1
#> # A tibble: 1 x 3
#> `1` `2` `3`
#> <chr> <chr> <chr>
#> 1 hallo foo foo
df2
#> # A tibble: 1 x 3
#> `1` `2` `3`
#> <chr> <chr> <chr>
#> 1 hallo foo foo
Создано 2021-12-09 пакетом reprex (v2.0.1)
Ответ №2:
Также зависит от вашей конечной цели, возможно, этот подход может быть полезен для вас.
df_names <- c("df1", "df2", "df3")
# note the small change in sample data
df1 <- tibble("1" = "hallo")
df2 <- tibble("2" = "hallo")
df3 <- tibble("3" = "hallo")
# I suggest to work with required columns, what is not there becomes missing
required <- c("1", "2", "3")
dfs <- lapply(df_names, function(df) {
t <- get(df)
t[setdiff(required, names(t))] <- NA
t
})
dfs
[[1]]
# A tibble: 1 x 3
`1` `2` `3`
<chr> <lgl> <lgl>
1 hallo NA NA
[[2]]
# A tibble: 1 x 3
`2` `1` `3`
<chr> <lgl> <lgl>
1 hallo NA NA
[[3]]
# A tibble: 1 x 3
`3` `1` `2`
<chr> <lgl> <lgl>
1 hallo NA NA
# if you want to combine the data anyhow
do.call("rbind", dfs)
# A tibble: 3 x 3
`1` `2` `3`
<chr> <chr> <chr>
1 hallo NA NA
2 NA hallo NA
3 NA NA hallo