【问题标题】:efficient rbind alternative with applied function具有应用功能的高效 rbind 替代方案
【发布时间】:2018-08-23 17:30:58
【问题描述】:

退一步说,我的最终目标是将大约 130,000 张图像读入 R 中,像素大小为 HxW,然后制作一个数据帧/数据表,其中包含新行上每个图像的每个像素的 rgb。所以输出会是这样的:

    > head(train_data, 10)
         image_no          r         g         b pixel_no
 1: 00003e153.jpg 0.11764706 0.1921569 0.3098039        1
 2: 00003e153.jpg 0.11372549 0.1882353 0.3058824        2
 3: 00003e153.jpg 0.10980392 0.1843137 0.3019608        3
 4: 00003e153.jpg 0.11764706 0.1921569 0.3098039        4
 5: 00003e153.jpg 0.12941176 0.2039216 0.3215686        5
 6: 00003e153.jpg 0.13333333 0.2078431 0.3254902        6
 7: 00003e153.jpg 0.12549020 0.2000000 0.3176471        7
 8: 00003e153.jpg 0.11764706 0.1921569 0.3098039        8
 9: 00003e153.jpg 0.09803922 0.1725490 0.2901961        9
10: 00003e153.jpg 0.11372549 0.1882353 0.3058824       10

我目前有一段代码来执行此操作,其中我应用了一个函数来获取指定图像的每个像素的 rgb,并在数据帧中返回结果:

#function to get rgb from image file paths
get_rgb_table <- function(link){

  img <- readJPEG(toString(link))

  # Creating the data frame
  rgb_image <- data.frame(r = as.vector(img[1:H, 1:W, 1]),
                          g = as.vector(img[1:H, 1:W, 2]),
                          b = as.vector(img[1:H, 1:W, 3]))
  #add pixel id
  rgb_image$pixel_no <- row.names(rgb_image)

  #add image id
  train_rgb <- cbind(sub('.*/', '',link),rgb_image)
  colnames(train_rgb)[1] <- "image_no"
  return(train_rgb)
}

我在另一个包含所有图像链接的数据帧上调用此函数:

train_files <- list.files(path="~/images/", pattern=".jpg",all.files=T, full.names=T, no.. = T)
train <- data.frame(matrix(unlist(train_files), nrow=length(train_files), byrow=T))

火车数据框如下所示:

> head(train, 10)
                               link
1  C:/Documents/image/00003e153.jpg
2  C:/Documents/image/000155de5.jpg
3  C:/Documents/image/00021ddc3.jpg
4  C:/Documents/image/0002756f7.jpg
5  C:/Documents/image/0002d0f32.jpg
6  C:/Documents/image/000303d4d.jpg
7  C:/Documents/image/00031f145.jpg
8  C:/Documents/image/00053c6ba.jpg
9  C:/Documents/image/00057a50d.jpg
10 C:/Documents/image/0005d01c8.jpg

我终于通过以下循环得到了我想要的结果:

for(i in 1:length(train[,1])){
  train_data <- rbind(train_data,get_rgb_table(train[i,1]))
}

但是,最后一段代码效率很低。优化如何应用函数和/或 rbind 会有所帮助。我认为函数get_rgb_table() 本身很快,但问题在于循环和rbind。我曾尝试使用apply(),但无法在每一行上执行此操作并将结果放入一个数据帧中而不会耗尽内存。对此的任何帮助都会很棒。谢谢!

【问题讨论】:

  • 你没有说你的函数做了什么,也没有说你的输入和输出数据是什么样的。人们很难提供帮助。您是要仅优化 rbind 部分还是“将函数应用于数据帧的每一行”部分?
  • data.table::rbindlist() 应该快得多,但这似乎是一个有问题的过程,循环遍历 data.frame,可能有更好的方法。
  • 我认为@avid_user 建议解释函数的作用,因为通常有比将函数应用于每一行更有效的解决方案。
  • 在 R 中增长东西通常很糟糕,尤其是对于数据帧,因为它非常慢且内存效率低下。如果您事先知道结果应该有多少行,您可以启动一个具有该大小的数据框并用循环生成的结果填充它。
  • 感谢摩西的建议,我也试试看!

标签: r image-processing


【解决方案1】:

鉴于问题含糊不清,这很难回答,但我会为您提出的问题认为提供一个可重复的示例,并给出解决方案。

假设我有一个返回数据框的函数:

MyFun <- function(x)randu[1:x,]

我有一个数据框df,它将作为函数的输入。

#     a  b
# 1   1 21
# 2   2 22
# 3   3 23
# 4   4 24
# 5   5 25
# 6   6 26
# 7   7 27
# 8   8 28
# 9   9 29
# 10 10 30

从您的问题来看,似乎只有一列将用作输入。因此,我使用 lapply 将函数应用于此数据帧的每一行,然后使用 do.callrbind 将结果绑定在一起,如下所示:

do.call(rbind, lapply(df$a, MyFun))

【讨论】:

  • 如果您能澄清反对意见,我们将不胜感激。
猜你喜欢
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
相关资源
最近更新 更多