R语言迭代作物相关列组构建rbind拼接tidy规整数据集方法问询
最优实现思路:使用tidyr::pivot_longer一步完成宽转长
完全不需要循环写文件、读文件拼接,利用列名的命名规律直接提取分组信息,代码量极少且运行效率远高于循环方案:
library(tidyverse) # 示例数据 data <- tribble( ~grower, ~YEAR, ~c.0., ~a.0., ~s.0., ~f.0., ~o.0., ~r.0., ~c.10., ~a.10, ~s.10., ~f.10., ~o.10., ~r.10., "Bob", 2014, "Kale, Baby", 7.0, 87.0, 126.0, "C", "", "Carrot", 16.0, 47.8, 137.0, "O", "", "Janet", 2015, "Broccoli", 18.0, 68.2,162.0, "O", "", "Garlic", 25.0, 9.1, 152.3, "C", "", "Chris", 2014, "Cabbage", 34.2, 8.6, 200.7, "C", "", "Cauliflower", 105.2, 113.0, 199.4, "O", "", "Ted", 2016, "Kale", 12.2, 11.9, 120.2, "C", "", "Lettuce, Head", 55.2, 113.0, 166.5, "C", "NY" ) tidy_data <- data %>% # 排除固定列grower、YEAR,对剩余作物列做长转换 pivot_longer( cols = -c(grower, YEAR), # 正则匹配列名:第一组是变量前缀(c/a/s/f/o/r),第二组是作物组号,兼容前后有无小数点的情况 names_pattern = "^([cafsor])\\.?([0-9]+)\\.?$", # .value表示把第一组匹配的前缀作为新列名,第二组匹配的组号存为crop_group列 names_to = c(".value", "crop_group") ) %>% # 按要求统一重命名列 rename( CROP = c, CROP_ACREAGE = a, SOIL_N = s, APP_N = f, TYPE = o, NOTES = r )
运行后直接得到规整的tidy格式数据,每一行对应一个种植户某一年的单种作物数据,不需要任何中间文件存储,不管是2组还是50组作物都无需修改代码适配。
按组遍历的替代实现(特殊场景可选)
如果出于特定需求必须逐组处理,也可以自动匹配列位置,不需要手动指定:
# 提取所有作物组号 crop_groups <- str_extract(colnames(data)[-(1:2)], "[0-9]+") %>% unique() # 预存结果的列表 res_list <- list() for (i in seq_along(crop_groups)) { group_id <- crop_groups[i] # 自动匹配当前组的6个列 group_cols <- str_detect(colnames(data), paste0("\\.?", group_id, "\\.?$")) # 提取数据+重命名 res_list[[i]] <- data %>% select(grower, YEAR, which(group_cols)) %>% set_names(c("grower", "YEAR", "CROP", "CROP_ACREAGE", "SOIL_N", "APP_N", "TYPE", "NOTES")) } # 直接拼接所有结果,不需要读写中间文件 tidy_data <- bind_rows(res_list)
内容的提问来源于stack exchange,提问作者blschum
相关产品推荐
相关产品推荐

