You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

for循环中sapply+as.numeric转换失效,出现行数不匹配错误

问题:循环读取Excel工作表时第二次迭代赋值报错

使用for循环读取Excel文件的所有工作表,处理后存入列表。第一次迭代正常执行,但进入第二次迭代(i=2)时出现如下错误:

Error:
! Assigned data `sapply(EstContratos[cols.name], as.numeric)` must be compatible with existing data.
✖ Existing data has 1 row.
✖ Assigned data has 3 rows.
ℹ Row updates require a list value. Do you need `list()` or `as.list()`?

用户表示第二次迭代中的EstContratos只有1行,疑惑为何报错提示赋值数据有3行,怀疑是否沿用了第一次迭代的3行数据。

原代码:

mysheetlist <- excel_sheets(path="whatever/EstadoContrato.xlsx")

datalist<-list()

i=1

for (i in 1:length(mysheetlist)){
  EstContratos <- read_excel(path="whatever/EstadoContrato.xlsx", sheet = mysheetlist[i])


EstContratos<-EstContratos %>%
  filter (!row_number() %in% c (1:15))

EstContratos<-Filter(function(x)!all(is.na(x)), EstContratos)

colnames(EstContratos)<-c("Cap","UM","CantContr","VrUni","VrUniTot","VrTotalContr",
                          "CantEjec","VrTotalEjec","CantXEjec","VrXEjec")

EstContratos<-EstContratos%>%
  select(Cap,VrTotalContr,VrTotalEjec,VrXEjec)

EstContratos$VrTotalContr<- gsub(",", "",EstContratos$VrTotalContr)
EstContratos$VrTotalEjec<- gsub(",", "",EstContratos$VrTotalEjec)
EstContratos$VrXEjec<-gsub(",", "",EstContratos$VrXEjec)

EstContratos<-EstContratos %>% drop_na(Cap)

cols.name <- c("VrTotalContr","VrTotalEjec","VrXEjec")
EstContratos[cols.name] <- sapply(EstContratos[cols.name],as.numeric)

EstContratos[c('CapCod', 'Capítulo')] <- str_split_fixed(EstContratos$Cap, ' ', 2)

EstContratos<-EstContratos%>%
  select(CapCod,VrTotalContr,VrTotalEjec)

ResumenContratos<-aggregate(EstContratos[,2:3], by = list(EstContratos$CapCod), sum)

datalist[[i]] <- ResumenContratos

}

ConsolidadoContratos = do.call(rbind, datalist)

问题原因与解决办法

核心原因

报错出现在EstContratos[cols.name] <- sapply(EstContratos[cols.name],as.numeric)这一行:
当EstContratos只有1行时,sapply处理后返回的是长度为3的向量,而非匹配数据框列结构的列表/数据框。R在执行列赋值时,会将这个向量当作行数据来解析,导致“现有1行,赋值3行”的不匹配错误。

解决办法

将sapply替换为lapply(返回列表,与数据框列结构完全匹配):

cols.name <- c("VrTotalContr","VrTotalEjec","VrXEjec")
EstContratos[cols.name] <- lapply(EstContratos[cols.name], as.numeric)

或者使用dplyr的mutate_at写法更简洁,避免这类类型匹配问题:

EstContratos <- EstContratos %>%
  mutate_at(vars(VrTotalContr, VrTotalEjec, VrXEjec), as.numeric)

额外验证(可选)

如果仍不确定第二次迭代的EstContratos行数,可以在报错代码前添加打印语句确认:

print(paste("当前工作表行数:", nrow(EstContratos)))

内容的提问来源于stack exchange,提问作者vivs

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:10:33