在R中合并数据并为缺失缩写补零的实现方案
解决森林数据集的缩写替换与字段补全问题
这是个挺典型的结构化数据清洗+扩展需求,我帮你拆解成两个核心步骤来实现,代码都给你写好啦,咱们一步步来:
准备工作:整理统一的缩写字典
首先得把你提供的几个字典统一成方便使用的键值对,原始的tree_dict和td1结构有点混乱,我们转成命名向量更便于后续替换操作:
library(stringr) library(dplyr) library(tidyr) # 合并所有缩写字典为统一的命名向量(可根据实际需求补充对应关系) tree_dict <- c( "AS" = "Aspen", # 按合理逻辑修正原字典的对应关系 "WB" = "Warty Birch", "Д" = "(请补充Д对应的真实树种名称)", "ЛИП" = "Linden", # 假设ЛИП是椴树的缩写,可按需调整 "oak" = "Oak", "H" = "Hornbeam", # 对应td1里的О=H -> Oak=Hornbeam "M" = "Maple" # 对应td1里的О=M -> Oak=Maple )
步骤1:替换所有字段中的缩写
我们需要遍历所有字符型和因子型字段,把里面的缩写替换成真实树种名称(比如把"7AS 3WB"变成"7Aspen 3Warty Birch")。这里用正则表达式确保只匹配独立的缩写,避免误替换其他字符串:
# 替换所有字段中的缩写 forest_clean <- forest %>% mutate(across(where(is.character) | where(is.factor), ~ { # 先转成字符型统一处理 str_val <- as.character(.x) # 遍历字典替换每个缩写,正则匹配数字/空格后的缩写,以及空格/结尾前的缩写 for(abbr in names(tree_dict)) { pattern <- str_glue("(?<=\\d|\\s){abbr}(?=\\s|$)") str_val <- str_replace_all(str_val, pattern, tree_dict[abbr]) } # 还原原字段类型(因子/字符) if(is.factor(.x)) factor(str_val) else str_val }))
步骤2:补全缺失树种的编号字段
接下来要为字典里存在但数据集中没有的树种,新增对应的KOFPORx、PORx等字段,按现有编号延续,数值补0:
# 1. 提取现有PORx字段的编号和对应的树种 por_cols <- grep("^POR\\d+\\.C\\.254", names(forest_clean), value = TRUE) existing_trees <- forest_clean %>% select(all_of(por_cols)) %>% pivot_longer(everything(), values_to = "tree") %>% pull(tree) %>% unique() %>% na.omit() # 2. 找出字典中未在数据集中出现的树种 missing_trees <- setdiff(unname(tree_dict), existing_trees) # 3. 获取现有最大编号,确定新增字段的起始编号 max_num <- max(as.integer(str_extract(por_cols, "\\d+")), na.rm = TRUE) current_num <- max_num + 1 # 4. 循环新增每个缺失树种的字段组 for(tree in missing_trees) { # 构建所有需要新增的字段名 field_names <- list( nomyar = str_glue("NOMYAR{current_num}.N.16.6"), kofpor = str_glue("KOFPOR{current_num}.N.16.6"), por = str_glue("POR{current_num}.C.254"), vozpor = str_glue("VOZPOR{current_num}.N.16.6"), vyspor = str_glue("VYSPOR{current_num}.N.16.6"), dempor = str_glue("DEMPOR{current_num}.N.16.6"), polnot = str_glue("POLNOT{current_num}.N.16.6"), zapzah = str_glue("ZAPZAH{current_num}.N.16.6") ) # 新增字段,参考现有数据规律赋值 forest_clean <- forest_clean %>% mutate( !!field_names$nomyar := 1, # 现有NOMYARx都是1,保持一致 !!field_names$kofpor := 0, !!field_names$por := tree, !!field_names$vozpor := 0, !!field_names$vyspor := 0, !!field_names$dempor := 0, !!field_names$polnot := 0, !!field_names$zapzah := 0 ) current_num <- current_num + 1 }
注意事项
- 如果你的原始
PORx字段存的是缩写(比如AS)而不是替换后的名称,那步骤2里需要用原始缩写来对比:把existing_trees换成提取原始缩写,missing_trees换成tree_dict[setdiff(names(tree_dict), existing_abbrs)]即可。 - 字典里的对应关系可以根据实际需求随时调整,新增缩写直接加到
tree_dict里就行。 - 如果某些字段的默认值不是0(比如
NOMYARx),可以根据现有数据的规律修改赋值逻辑。
内容的提问来源于stack exchange,提问作者psysky
相关产品推荐
相关产品推荐

