从sfa_out列表的随机前沿模型提取效率值至数据框报错求助
批量提取随机前沿模型效率值的问题与解决
需求描述
有一个存储了8个随机前沿模型的列表sfa_out,需要用efficiencies()函数提取每个模型的效率估计值,并将所有模型的效率值合并到同一个数据框中。单独处理每个模型正常,但批量处理的for循环报错。
原代码与错误信息
原循环代码
# define an empty data frame eff_out <- data.frame() # write a for loop for each i model in the list "sfa_out" for(i in 1:length(sfa_out$models)) { eff_out$i = as.data.frame(efficiencies(sfa_out$models[[i]])) %>% # the code below pivots the data frame so that three columns are "col", "year" and "efficiency" mutate(col = row.names(efficiencies(sfa_out$models[[i]]))) %>% pivot_longer(cols = 1:23, names_to = "year", values_to = "efficiency") %>% drop_na() }
错误信息
Error in `$<-.data.frame`(`*tmp*`, "i", value = list(col = c("GB0000365774", : replacement has 139 rows, data has 0
问题分析
- 初始
eff_out是0行空数据框,直接赋值新列时,新列的行数(139行)与原数据框行数(0行)不匹配,触发报错。 eff_out$i会创建固定名为i的列,而非动态对应每个模型的标识,且每次循环会覆盖该列,无法保留所有模型的数据。- 重复调用
efficiencies(sfa_out$models[[i]])两次,冗余且降低效率。
解决方案
方法1:修正for循环
先初始化空数据框,每次处理单个模型时添加模型ID,再合并到总数据框:
library(dplyr) library(tidyr) # 初始化空数据框 eff_out <- data.frame() # 循环处理每个模型 for(i in 1:length(sfa_out$models)) { # 先提取效率值,避免重复调用 eff_df <- as.data.frame(efficiencies(sfa_out$models[[i]])) # 处理当前模型的数据,添加模型ID current_eff <- eff_df %>% mutate(col = rownames(eff_df), model_id = i) %>% # 添加模型标识,区分不同模型 pivot_longer(cols = 1:23, names_to = "year", values_to = "efficiency") %>% drop_na() # 合并到总数据框 eff_out <- bind_rows(eff_out, current_eff) }
方法2:用purrr批量处理(更简洁)
使用purrr::map_dfr可以避免手动循环,自动合并数据框:
library(dplyr) library(tidyr) library(purrr) eff_out <- map_dfr(seq_along(sfa_out$models), function(i) { eff_df <- as.data.frame(efficiencies(sfa_out$models[[i]])) eff_df %>% mutate(col = rownames(eff_df), model_id = i) %>% pivot_longer(cols = 1:23, names_to = "year", values_to = "efficiency") %>% drop_na() })
补充说明
- 添加
model_id列可以区分不同模型的效率值,方便后续分析。 - 如果效率值列数不是固定23,可以用
cols = -col代替cols = 1:23,避免硬编码列数,提升代码通用性。
内容的提问来源于stack exchange,提问作者fsure
相关产品推荐
相关产品推荐

