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
相关产品推荐
相关产品推荐

