【问题标题】:Memory and otimization problems in JSTOR's XML big loopJSTOR 的 XML 大循环中的内存和优化问题
【发布时间】:2019-11-02 11:20:38
【问题描述】:

在将 JSTOR 数据的 200,000 多个文档用于研究时,我遇到了内存和优化问题。文档为 xml 格式。更多信息可以在这里找到:https://www.jstor.org/dfr/

在代码的第一步中,我通过以下方式将一个 xml 文件转换为一个整洁的数据框:


    Transform <- function (x)
    {
        a <- xmlParse (x)
        aTop <- xmlRoot (a)

        Journal <- xmlValue(aTop[["front"]][["journal-meta"]][["journal-title group"]][["journal-title"]])
        Publisher <- xmlValue (aTop[["front"]][["journal-meta"]][["publisher"]][["publisher-name"]])
        Title <- xmlValue (aTop[["front"]][["article-meta"]][["title-group"]][["article-title"]])
        Year <- as.integer(xmlValue(aTop[["front"]][["article-meta"]][["pub-date"]][["year"]]))
        Abstract <- xmlValue(aTop[["front"]][["article-meta"]][["abstract"]])
        Language <- xmlValue(aTop[["front"]][["article-meta"]][["custom-meta-group"]][["custom-meta"]][["meta-value"]])

        df <- data.frame (Journal, Publisher, Title, Year, Abstract, Language, stringsAsFactors = FALSE)

    df
    }

在序列中,我使用第一个函数将一系列 xml 文件转换为单个数据帧:


    TransformFiles <- function (pathFiles)
    {

        files <- list.files(pathFiles, "*.xml")
        i = 2
        df2 <- Transform (paste(pathFiles, files[i], sep="/", collapse=""))
        while (i<=length(files)) 
        { 
            df <- Transform (paste(pathFiles, files[i], sep="/", collapse=""))
            df2[i,] <- df

            i <- i + 1
        }

    data.frame(df2)
    }

当我有超过 100000 个文件时,运行需要几个小时。如果有 200000,它最终会随着时间的推移而中断或变慢。即使在小集合中,也可以注意到它随着时间的推移运行得更慢。有什么我在做错事吗?我可以做些什么来优化代码吗?我已经尝试过 rbind 和 bind-rows 而不是直接使用 df2[i,] 分配值

【问题讨论】:

  • 内存不足了吗?您是否尝试过profiling 您的代码,以便查看实际占用时间的内容?你能把问题分成更小的任务,然后最后合并吗?一般来说,一次增长一个数据帧是非常低效的。
  • 通常问题出在时间上,但我已经用完一两次 RAM。我没有尝试过分析。我去做。至于较小的任务,不知道该怎么做。
  • 看看能不能分块运行。 1000-2000 将是一个不错的数字。最终会有两个绑定行。一个用于块,稍后用于块。
  • 您也可以使用包jstor:ropensci.github.io/jstor 该包经过优化,使导入尽可能顺畅和快速。免责声明:我是包的作者。
  • 什么是Transformar?你只显示Transform。另外,请显示我已经尝试过 rbind 和 bind-rows。目前尚不清楚df2[i,] &lt;- df 是如何不发出警告的,因为两者的长度可能不同。

标签: r xml performance loops jstor


【解决方案1】:

通过分配 df2[i,] &lt;- df 避免对象在循环中增长(顺便说一下,只有 df 是单行时才有效)并避免使用迭代器的 while 所需的簿记, i

相反,请考虑使用lapply 构建一个数据框列表,然后您可以在循环外的一次调用中将rbind 一起使用。

TransformFiles <- function (pathFiles)
    {
        files <- list.files(pathFiles, "*.xml", full.names = TRUE)
        df_list <- lapply(files, Transform)

        final_df <- do.call(rbind, unname(df_list))

        # ALTERNATIVES FOR POSSIBLE PERFORMANCE:

        # final_df <- data.table::rbindlist(df_list)
        # final_df <- dplyr::bind_rows(df_list)
        # final_df <- plyr::rbind.fill(df_list)
    }

【讨论】:

  • 谢谢。我通常选择循环而不是应用。我认为我应该反其道而行之。
  • 有没有办法用 lapply 跟踪代码?比如打印转换文件的百分比......
  • 您可以在lapply 中使用匿名或定义函数扩展函数:lapply(files, function(f) { df &lt;- Transform(f) ...other lines... return(df) })。顺便问一下,解决方案有帮助吗?
猜你喜欢
  • 2018-10-29
  • 2022-12-04
  • 1970-01-01
  • 2022-01-26
  • 2017-02-06
  • 1970-01-01
  • 2019-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多