r-如果列存在循环dplyr,则突变列



我想做一个简单的任务:如果一列存在,则更改该列的值。我想对循环中的多个列和数据帧执行此操作。

我做了一个可重复的例子。在该示例中,我们有两个数据帧BelgFran

Fran具有两列t1t2,而Belg具有三列t1t2t3。我想根据下面代码中描述的一个简单操作来替换这两三列中的值。棘手的部分是,由于两个数据帧的列数不相同,下面的代码会生成第三列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_tBelg_t放在列表中。请注意,这不会更改底层帧Fran_tBelg_t,但您的原始循环也没有这样做;而是创建了称为CCD_ 16和CCD_。发生这种情况是因为您的assign(c,a)呼叫。如果您想实际更改Fran_tBelg_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_tBelg_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")))
)
}