R语言循环下载数据框URL对应JPEG存入数组时的覆盖问题
问题:批量下载URL图片存入R数组时出现变量覆盖、维度丢失问题
问题现象
我需要将data frame中存储的URL对应的多张JPEG格式图片下载后存入array,初始编写的实现代码如下:
# 遍历训练集URL下载图片 for (i in 1:274) { theurl <- paste(train[i,c("Icon.URL")], sep = "") z <- tempfile() download.file(theurl,z,mode = "wb") train_image <- readJPEG(z) writeJPEG(train_image, paste("imageTrain", i, ".jpg", sep = "")) file.remove(z) }
运行上述代码后,train_image仅为包含786432个元素的数组,恰好对应单张尺寸为512×512×3的JPEG图片的元素总量,每次for循环运行时该变量都会被覆盖,最终仅存储了最后一张图片的数据。
补充信息
train为存储图片URL的data frame对象- 初始代码参考自RStudio社区公开技术帖
已尝试的无效方案
曾尝试使用append()函数修改代码,修改后的代码如下:
for (i in 1:10) { theurl <- paste(train[i,c("Icon.URL")], sep = "") z <- tempfile() download.file(theurl,z,mode = "wb") train_img <- readJPEG(z) train_image <- append(train_image, train_img) writeJPEG(train_img, paste("imageTrain", i, ".jpg", sep = "")) file.remove(z) }
该写法虽然可以将图片数据追加到train_image中,但最终得到的是长数值型向量,而非预期的多维array结构。
错误原因
- 初始代码的覆盖问题:循环内直接对
train_image执行全量赋值,没有预留存储所有图片的结构,每次读取新图片时都会直接替换掉变量中存储的上一张图片内容,循环结束后自然只剩最后一张图的数据。 append()方案的维度丢失问题:R中append()函数仅支持一维向量拼接,传入高维数组时会自动将数组展平为一维向量再执行拼接,最终只能得到拉长的数值向量,无法保留图片的高、宽、通道维度信息。
正确实现方案
推荐使用「列表暂存+最终合并」的写法,容错性更高,不会因为个别图片尺寸异常直接中断循环:
library(jpeg) # 初始化空列表暂存所有图片矩阵 train_image_list <- list() for (i in 1:274) { theurl <- train[i, "Icon.URL"] z <- tempfile() download.file(theurl, z, mode = "wb", quiet = TRUE) # 读取单张图片,得到512*512*3的三维数组 train_img <- readJPEG(z) # 按索引存入列表 train_image_list[[i]] <- train_img # 本地保存单张图片 writeJPEG(train_img, paste0("imageTrain", i, ".jpg")) file.remove(z) } # 合并为4维数组:默认维度顺序为 [高度, 宽度, 通道数, 图片序号] train_image <- simplify2array(train_image_list) # 如果需要调整维度顺序为[图片序号, 高度, 宽度, 通道数],可以用aperm转置 # train_image <- aperm(simplify2array(train_image_list), c(4,1,2,3))
如果能确保所有图片尺寸完全一致,也可以预先初始化固定维度的数组,循环内按索引赋值,运行效率更高:
library(jpeg) # 预分配274张512*512*3的数组空间 train_image <- array(NA, dim = c(274, 512, 512, 3)) for (i in 1:274) { theurl <- train[i, "Icon.URL"] z <- tempfile() download.file(theurl, z, mode = "wb", quiet = TRUE) train_img <- readJPEG(z) # 存入对应位置 train_image[i,,,] <- train_img writeJPEG(train_img, paste0("imageTrain", i, ".jpg")) file.remove(z) }
内容的提问来源于stack exchange,提问作者RtotheB314
相关产品推荐
相关产品推荐

