如何避免R语言for循环中出现'replacement has length zero'错误
问题与解决方案
问题背景
有如下记录不同公司各年份数据的数据框:
# company year value1 value2 # 1 1 2019 1 10 # 2 1 2020 11 110 # 3 1 2021 111 1110 # 4 2 2019 2 20 # 5 2 2021 222 2220 # 6 3 2019 3 30 # 7 3 2020 33 330 # 8 3 2021 333 3330
其中公司2的2020年数据缺失。尝试通过for循环计算各公司2020年value1与value2之和时,因缺失数据触发报错:
Error in x[[jj]][iseq] <- replacement has length zero
原循环代码:
df_sum <- data.frame() for (i in 1:3) { df_sum[i, 1] <- i df_sum[i, 2] <- df[df$company == i & df$year == 2020, "value1"] + df[df$company == i & df$year == 2020, "value2"] }
需求是让缺失数据对应结果为NA,且循环不终止,最终得到如下结果:
company | sum of values ------------------------- 1| 1 | 121 2| 2 | NA 3| 3 | 363
数据构造代码:
df <- structure(list(company = c(1, 1, 1, 2, 2, 3, 3, 3), year = c(2019, 2020, 2021, 2019, 2021, 2019, 2020, 2021), value1 = c(1, 11, 111, 2, 222, 3, 33, 333), value2 = c(10, 110, 1110, 20, 2220, 30, 330, 3330)), class = "data.frame", row.names = c(NA, -8L))
解决方案
方案1:修改原for循环
报错原因是无匹配数据时,提取的向量长度为0,无法赋值给数据框。可以先初始化数据框,再通过判断行数处理缺失情况:
# 初始化包含所有公司编号的结果框,sum_values列默认NA df_sum <- data.frame(company = 1:3, sum_values = NA_real_) for (i in 1:3) { # 筛选对应公司和年份的行 target_row <- df[df$company == i & df$year == 2020, ] # 若存在数据则计算和,否则保留NA if (nrow(target_row) > 0) { df_sum$sum_values[i] <- target_row$value1 + target_row$value2 } }
方案2:向量化操作(推荐)
在R中优先用向量化/分组操作替代循环,更高效简洁。这里用dplyr包实现:
library(dplyr) df_sum <- df %>% filter(year == 2020) %>% # 筛选2020年数据 mutate(sum_values = value1 + value2) %>% # 计算两列和 right_join(data.frame(company = 1:3), by = "company") %>% # 保留所有公司,缺失数据补NA select(company, sum_values) # 保留需要的列
运行后直接得到目标结果:
company sum_values 1 1 121 2 2 NA 3 3 363
如果用base R实现,可通过aggregate+merge组合:
# 计算有数据的公司的和 sum_result <- aggregate(cbind(sum_values = value1 + value2) ~ company, data = df[df$year == 2020, ], FUN = identity) # 合并所有公司编号,缺失数据补NA df_sum <- merge(data.frame(company = 1:3), sum_result, by = "company", all.x = TRUE)
内容的提问来源于stack exchange,提问作者kynadid4
相关产品推荐
相关产品推荐

