我想做一个简单的任务:如果一列存在,则更改该列的值。我想对循环中的多个列和数据帧执行此操作。
我做了一个可重复的例子。在该示例中,我们有两个数据帧Belg
和Fran
。
Fran
具有两列t1
和t2
,而Belg
具有三列t1
、t2
和t3
。我想根据下面代码中描述的一个简单操作来替换这两三列中的值。棘手的部分是,由于两个数据帧的列数不相同,下面的代码会生成第三列t3
到dfFran
——这不是我想要的。
df <- data.frame (v1 = c("Fran", "Fran", "Fran", "Belg", "Belg", "Belg"),
v2 = c(1201, 1201, 1202, 1203, 1204, 1205),
v3 = c(1, 2, 1, 1, 3, 1)
)
Fran_t <- data.frame(v1 = c("Fran", "Fran"),
t1 = c(NA, NA),
t2 = c(NA, NA)
)
Belg_t <- data.frame(v1 = c("Belg", "Belg", "Belg"),
t1 = c(NA, NA, NA),
t2 = c(NA, NA, NA),
t3 = c(NA, NA, NA)
)
cty <- c("Fran", "Belg")
for (c in cty) {
a <- df
d <- paste0(c,"_t")
a <- a %>%
filter(v1==paste(c)) %>%
left_join(., get(d), by="v1") %>%
group_by(v2) %>%
mutate("t1" = case_when(any(v3==1) ~ "NAv", TRUE ~ "NAp")) %>%
mutate("t2" = case_when(any(v3==2) ~ "NAv", TRUE ~ "NAp")) %>%
mutate("t3" = case_when(any(v3==3) ~ "NAv", TRUE ~ "NAp"))
assign(c, a)
}
我试过这样的东西:
mutate({if("t1" %in% names(.)) "t1" = case_when(any(v3==1) ~ "NAv") else "NULL"})
or even
{if("t1" %in% names(.)) mutate("t1" = case_when(any(v3==1) ~ "NAv", TRUE ~ "NAp")) else NULL}
``
您可以将Fran_t
和Belg_t
放在列表中。请注意,这不会更改底层帧Fran_t
和Belg_t
,但您的原始循环也没有这样做;而是创建了称为CCD_ 16和CCD_。发生这种情况是因为您的assign(c,a)
呼叫。如果您想实际更改Fran_t
和Belg_t
,请参阅底部的选项:
cty <- list(Fran_t, Belg_t)
lapply(cty, function(c) {
df%>%
inner_join(c, by="v1") %>%
group_by(v2) %>%
mutate(across(starts_with("t"), ~if_else(any(v3==1),"NAv", "NAp")))
})
输出:
[[1]]
# A tibble: 6 x 5
# Groups: v2 [2]
v1 v2 v3 t1 t2
<chr> <dbl> <dbl> <chr> <chr>
1 Fran 1201 1 NAv NAv
2 Fran 1201 1 NAv NAv
3 Fran 1201 2 NAv NAv
4 Fran 1201 2 NAv NAv
5 Fran 1202 1 NAv NAv
6 Fran 1202 1 NAv NAv
[[2]]
# A tibble: 9 x 6
# Groups: v2 [3]
v1 v2 v3 t1 t2 t3
<chr> <dbl> <dbl> <chr> <chr> <chr>
1 Belg 1203 1 NAv NAv NAv
2 Belg 1203 1 NAv NAv NAv
3 Belg 1203 1 NAv NAv NAv
4 Belg 1204 3 NAp NAp NAp
5 Belg 1204 3 NAp NAp NAp
6 Belg 1204 3 NAp NAp NAp
7 Belg 1205 1 NAv NAv NAv
8 Belg 1205 1 NAv NAv NAv
9 Belg 1205 1 NAv NAv NAv
更改Fran_t
和Belg_t
的选项:
cty <- c("Fran_t", "Belg_t")
for(c in cty) {
assign(c, df%>%
inner_join(get(c), by="v1") %>%
group_by(v2) %>%
mutate(across(starts_with("t"), ~if_else(any(v3==1),"NAv", "NAp")))
)
}