如何用新数据框df1更新旧数据框df2并维护record_id
用R实现旧数据框的更新与新增行
针对你需要用df1更新df2的需求(同步status、新增行、延续record_id),可以用dplyr包的一系列操作来实现,具体步骤如下:
首先确认输入的数据结构:
df1<-structure(list(protocol_no = c("study1", "study2", "study3", "study4", "study5", "study6", "study7"), status = c("New", "Open", "Closed", "New", "PI signoff", "Closed", "Open")), row.names = c(NA, -7L), class = c("tbl_df", "tbl", "data.frame")) df2<-structure(list(record_id = c(11, 12, 13, 14, 15, 16), protocol_no = c("study1", "study2", "study3", "study4", "study5", "study6"), status = c("New", "Closed", "Closed", "New", "PI signoff", "Closed"), form_1_complete = c(0, 0, 0, 0, 0, 0)), row.names = c(NA, 6L), class = "data.frame")
完整解决方案代码
library(dplyr) # 1. 更新已有研究的status:移除旧status,关联df1的最新值 updated_existing <- df2 %>% select(-status) %>% left_join(df1, by = "protocol_no") %>% filter(!is.na(status)) # 2. 处理新增研究:生成连续record_id,补充其他列默认值 new_rows <- df1 %>% anti_join(df2, by = "protocol_no") %>% mutate( record_id = max(df2$record_id) + row_number(), form_1_complete = 0 # 可根据实际需求调整默认值 ) %>% select(record_id, protocol_no, status, form_1_complete) # 3. 合并数据并排序 final_df <- bind_rows(updated_existing, new_rows) %>% arrange(record_id) # 查看结果 print(final_df)
关键步骤解释
- 更新已有行:通过
select(-status)丢弃df2中的旧status,再用left_join关联df1获取最新的status值,确保已有研究的状态同步。 - 新增行处理:
anti_join筛选出df1中未在df2出现的研究,用max(df2$record_id) + row_number()生成连续的record_id,同时补充form_1_complete的默认值(这里和旧数据保持一致为0,可按需修改)。 - 合并结果:用
bind_rows合并两部分数据,再按record_id排序,得到符合要求的最终数据框。
输出结果
# A tibble: 7 × 4 record_id protocol_no status form_1_complete <dbl> <chr> <chr> <dbl> 1 11 study1 New 0 2 12 study2 Open 0 3 13 study3 Closed 0 4 14 study4 New 0 5 15 study5 PI signoff 0 6 16 study6 Closed 0 7 17 study7 Open 0
可以看到:
- study2的status已从"Closed"更新为df1中的"Open"
- 新增的study7分配了延续的record_id 17
- 所有protocol_no唯一,包含全部4列
内容的提问来源于stack exchange,提问作者Joe Crozier
相关产品推荐
相关产品推荐

