如何在R中基于两列匹配将循环获取的数据追加至同一列?
解决按站点迭代追加数据到同一列的问题
问题场景
初始数据结构:
dat <- data.frame( Site = rep(c('a', 'b', 'c', 'd', 'e'), each = 5), Date = rep(c(1,2,3,4,5),5) )
通过循环按站点下载流量数据(示例数据如下),使用left_join追加时,每次迭代会生成新的dailyQ.x、dailyQ.y列,需求是将所有迭代的流量数据合并到同一dailyQ列中。
示例迭代流量数据:
# 站点a的流量数据 q1 <- data.frame( Site = rep('a',5), Date = c(1,2,3,4,5), dailyQ = c(NA, 70, 65, NA, 41) ) # 站点b的流量数据 q2 <- data.frame( Site = rep('b',5), Date = c(1,2,3,4,5), dailyQ = c(43, 55, NA, NA, 72) )
优雅解决方案
方法1:用rows_patch精准更新(推荐)
dplyr的rows_patch函数专门用于用新数据的非NA值更新原数据框的对应行,完全匹配需求,不会生成冗余列:
library(dplyr) # 先初始化dailyQ列为NA dat$dailyQ <- NA # 第一次迭代更新 dat <- rows_patch(dat, q1, by = c("Site", "Date")) # 第二次迭代更新 dat <- rows_patch(dat, q2, by = c("Site", "Date"))
每次迭代调用rows_patch,新数据中的非NA值会自动填充到dat的dailyQ列对应位置,原有的NA或已填充值不会被覆盖。
方法2:批量合并所有流量数据
如果可以在循环中先将所有站点的流量数据存入列表,最后一次性合并,效率更高:
# 循环过程中把每个站点的流量数据存入列表 q_list <- list(q1, q2) # 合并所有流量数据到一个数据框 all_q <- bind_rows(q_list) # 一次性左连接到初始数据框 dat <- left_join(dat, all_q, by = c("Site", "Date"))
方法3:动态合并迭代生成的列
如果必须逐次迭代合并,可通过coalesce自动合并多列到同一列,再清理冗余列:
# 封装成可复用函数 add_dailyQ <- function(dat, new_q) { # 左连接新增数据 dat <- left_join(dat, new_q, by = c("Site", "Date")) # 提取所有dailyQ相关列 q_cols <- grep("^dailyQ", names(dat), value = TRUE) # 合并列并清理冗余 dat <- dat %>% mutate(dailyQ = coalesce(!!!syms(q_cols))) %>% select(-all_of(q_cols[-length(q_cols)])) return(dat) } # 循环中调用函数 dat <- add_dailyQ(dat, q1) dat <- add_dailyQ(dat, q2)
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

