用“For循环”填充矩阵耗时太长

Posted

技术标签:

【中文标题】用“For循环”填充矩阵耗时太长【英文标题】:Filling a Matrix with "For Loop" Taking Too Long 【发布时间】:2014-02-09 02:11:08 【问题描述】:

我正在尝试使用 for 循环创建一个大约 1,000,000 x 5 的数据框,但已经 5 个多小时了,我认为它不会很快完成。我正在使用 rjson 库从大型 json 文件中读取数据。有人可以帮助我以更快的方式填充此数据框吗?

library(rjson)

# read in data from json file
file <- "/filename"
c <- file(file, "r")
l <- readLines(c, -1L)
data <- lapply(X=l, fromJSON)

# specify variables that i want from this data set
myvars <- c("url", "time", "userid", "hostid", "title")
newdata <- matrix(data[[1]][myvars], 1, 5, byrow=TRUE)

# here's where it goes wrong
for (i in 2:length(l)) 
newdata <- rbind(newdata, data[[i]][myvars])


newestdata <- data.frame(newdata)

【问题讨论】:

你在R Inferno的第二个圈子里。 查看 R inferno。随着每次循环迭代和消耗资源,您正在增长newdata。最好为你的 1000000 x 5 矩阵预先分配内存,然后填写信息。 ...但惯用的方式类似于do.call(rbind,data)。请参阅 data.table 包中的 rbindlist 以获得更快的速度。 R 是更改时复制,因此您将成倍增加每个循环所需的时间。在lapply 或类似的东西上使用rbindlist(来自data.table)。 data &lt;- sapply(X=l, fromJSON) 应该这样做,但您可能需要转置结果。 【参考方案1】:

这需要很长时间,因为循环的每次迭代都在创建一个新的、更大的对象。试试这个:

slice <- function(field, data) unlist(lapply(data, `[[`, field))
data.frame(Map(slice, myvars, list(data)))

这将创建一个 data.frame 并保留您的原始数据类型:字符、数字等,如果重要的话。将所有内容强制转换为矩阵会强制将所有内容转换为字符类。

【讨论】:

这适用于我较小的测试数据集,但不适用于我实际的大型数据集。这里有什么问题?这是我得到的错误。 "data.frame 中的错误(buzz = c("azcentral.com/community/phoenix/articles/…", : 参数暗示不同的行数:1349674、1339352" 你能更准确地说“不起作用”吗?如果您收到错误消息,您可以分享吗?您的文件中是否存在不包含所有五个条目的记录? 上面贴出了错误信息。运行以下行时出现此错误:“newdata 长度(数据)为 1349674 所以,是的,您有缺少条目的记录。尝试用这个替换上面的sliceslice &lt;- function(field, data) unlist(lapply(lapply(data, "[[", field), function(x) if (is.null(x)) NA else x)) 【参考方案2】:

如果没有数据,很难确定,但您正在做的一些事情相对较慢。这应该更快,但同样,没有数据,我无法测试:

newdata <- vapply(data, `[`, character(5L), myvars)

我还假设您的datacharacter,我认为它必须基于title

另外,正如其他人所指出的,你的速度慢的原因是你正在增长一个对象,这需要 R 不断重新分配内存。 vapply 会提前分配内存,因为它知道每次迭代结果的大小,以及有多少项。

【讨论】:

以上是关于用“For循环”填充矩阵耗时太长的主要内容,如果未能解决你的问题,请参考以下文章

matlab中矩阵怎么在for循环中用

MATLAB中如何用for 循环将结果代入矩阵中?

matlab 如何将for每循环一次产生的矩阵合并成一个大矩阵

c-用for循环填充一维数组

两通道 cv::Mat 对象填充了没有 for 循环的行列索引

怎样在for循环变量中,将循环变量赋值给一个变量 批处理 bat