在R数据框中重复国家名称至Total行的高效实现方法
高效填充R数据框中国家名称的方法
针对你拥有的这种分组结构(每个国家开头一行是国名,后续行NA,最后一行是Total),而且有252个国家的情况,推荐以下几种高效的实现方法,避免逐行循环浪费时间:
首先,还原你的数据框(方便测试)
先把你提供的文本数据转换成可操作的R数据框:
df <- data.frame( Country = c("Andorra", NA, NA, "Total", "Antigua", NA, NA, NA, "Total"), Information = c("Small", "Medium", "Large", NA, "Small", "Medium", "Large", "X-Large", NA), Export = c(10, 50, 40, 100, 60, 20, 5, 15, 100), Import = c(20, 30, 50, 100, 70, 10, 10, 10, 100), stringsAsFactors = FALSE )
方法1:用dplyr + tidyr(语法直观,适合熟悉tidyverse的用户)
这个方法通过分组填充实现,全程向量操作,效率很高:
library(dplyr) library(tidyr) df_filled <- df %>% # 生成组ID:每遇到一个新国家就开启一个新组 mutate(group_id = cumsum(!is.na(Country) & Country != "Total")) %>% # 按组向下填充Country列的NA值 group_by(group_id) %>% fill(Country, .direction = "down") %>% # 把Total行的Country恢复为"Total"(因为fill会把Total行的Country也填充成国名) mutate(Country = ifelse(is.na(Information), "Total", Country)) %>% ungroup() %>% select(-group_id) # 移除临时组ID列 # 查看结果 print(df_filled)
方法2:用data.table(速度最快,适合大数据量)
如果你的数据行数很多,data.table的底层C实现会比tidyverse更快,非常适合252个国家的规模:
library(data.table) setDT(df) # 生成组ID df[, group_id := cumsum(!is.na(Country) & Country != "Total")] # 按组向下填充NA,用nafill比fill更快 df[, Country := nafill(Country, type = "locf"), by = group_id] # 恢复Total行的Country值 df[is.na(Information), Country := "Total"] # 删除临时组ID列 df[, group_id := NULL] # 查看结果 print(df)
方法3:基础R实现(无需额外包)
如果你不想加载任何第三方包,这个方法也能高效完成,因为它是按组循环而不是按行循环,252次循环完全不会有性能问题:
# 找到所有国家名所在的行位置 country_starts <- which(!is.na(df$Country) & df$Country != "Total") # 找到所有Total行的位置 total_rows <- which(df$Country == "Total") # 循环每个国家组,填充国名 for (i in seq_along(country_starts)) { # 当前组的起始行到Total行的前一行 fill_range <- country_starts[i]:(total_rows[i] - 1) df$Country[fill_range] <- df$Country[country_starts[i]] } # 查看结果 print(df)
这三种方法都能完美实现你的需求:每个国家的名称会填充到其对应行组的Total行之前的所有行,Total行保持不变。其中data.table方法在处理大规模数据时优势最明显,推荐优先使用。
内容的提问来源于stack exchange,提问作者Data Science
相关产品推荐
相关产品推荐

