1

我有一个包含多个 JSON 对象的文件。我需要通读这些文件并从 JSON 对象中提取某些字段。更复杂的是,一些对象不包含所有字段。我正在处理一个包含超过 200,000 个 JSON 对象的大文件。我想将工作拆分到多个核心。我曾尝试使用 doSNOW、foreach 和 parallel 进行试验,但我真的不明白如何做到这一点。以下是我希望提高效率的代码。

foreach (i in 2:length(linn)) %dopar% {
  json_data <- fromJSON(linn[i])


  if(names(json_data)[1]=="info")
    next

  mLocation <- ifelse('location' %!in% names(json_data$actor),'NULL',json_data$actor$location$displayName)
  mRetweetCount <- ifelse('retweetCount' %!in% names(json_data),0,json_data$retweetCount)
  mGeo <- ifelse('geo' %!in% names(json_data),c(-0,-0),json_data$geo$coordinates)

  tweet <- rbind(tweet, 
               data.frame(
                 record.no        =     i,
                 id               =     json_data$id,
                 objecttype       =     json_data$actor$objectType,
                 postedtime       =     json_data$actor$postedTime,
                 location         =     mLocation,
                 displayname      =     json_data$generator$displayName,
                 link             =     json_data$generator$link,
                 body             =     json_data$body,
                 retweetcount     =     mRetweetCount,
                 geo              =     mGeo)
               )

}
4

1 回答 1

2

与其尝试并行化迭代,我认为您最好尝试矢量化(嗯,实际上下面的大部分内容仍在迭代......)。例如在这里我们得到了所有的记录(还没有速度提升,虽然见下文......)

json_data <- lapply(linn, fromJSON)

因为location我们预先分配了一个 NA 向量来表示没有位置的记录,然后找到确实有位置的记录(也许有更好的方法......)并更新它们

mLocation <- rep(NA, length(json_data))
idx <- sapply(json_data, function(x) "location" %in% names(x$actor))
mLocation[idx] <- sapply(json_data[idx], function(x) x$location$displayName)

最后,在一次调用中创建一个 200,000 行数据框(而不是您的“复制和附加”模式,它先复制第一行,然后是第一行和第二行,然后是第一行、第二行、第三行,然后是 . .. 所以 N 平方行,除了重新创建因子和其他 data.frame 特定费用;这可能是您花费大部分时间的地方)

data.frame(i=seq_along(json_data), location=mLocation)

这个想法是累积所有列,然后只调用一次data.frame(). 我认为您可以通过将所有内容粘贴到代表 JSON 数组的单个字符串中并在一次调用中解析来一次解析一行

json_data <- fromJSON(sprintf("[%s]", paste(linn, collapse=",")))
于 2013-10-10T02:22:24.467 回答