首页 > 解决方案 > 无法将数据帧绑定到空数据帧

问题描述

我正在学习 R Studio,这是针对我正在从事的项目的。我正在使用 Marvel API 来获取宇宙中所有角色的列表,方法是使用 for 循环多次调用 API。他们的 API 将您限制为 100 个结果/调用,因此我正在迭代并设置每个循环的偏移量。

我的代码在过去几天工作,但是当我今天加载并尝试获取数据时,我收到错误:“rbind 错误(deparse.level,...):无效列表参数:所有变量都应该有相同的长度”

这是我正在运行的代码:

MarvelUniverse = data.frame()
y = 1
offset = c(0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400)
for(x in offset){
  partialUrl = "https://gateway.marvel.com:443/v1/public/characters?ts=1&apikey={apiKey}&hash={hash}&limit=100&offset="  
  url = paste(partialUrl, offset, sep="")
  call = httr::GET(url[y])
  query = httr::content(call, as="raw")
  name = jsonlite::fromJSON(rawToChar(query))
  df = flatten(as.data.frame(name))
  MarvelUniverse = rbind(df, MarvelUniverse)
  y = y + 1
}

由于我之前绑定到一个空数据框,我不明白为什么我之前能够使用此功能,但现在它失败了?我确实注意到它df现在持有 1618 个元素,而在休息前它持有 ~1498 个元素。该name列表仍然包含一个包含 7 个元素的大型列表,因此看起来是一样的。

编辑 我发现如果我从中删除 flatten df = flatten(as.data.frame(name)),调用将在循环的第一次迭代中执行,但现在我遇到了重复 row.names 的问题。试图将它们设置为 NULL,但不幸的是到目前为止还没有运气。

标签: rrbind

解决方案


几点建议:

  • 不要rbind()在循环中一次一个数据帧 - 这是一个经典的反模式。它被称为“培养对象”,是R Inferno 中的第二个地狱圈。这是非常低效的。相反,您应该将所有数据框放在一个列表中,并rbind在最后一次将它们全部放在一起。

  • 您在同一个循环中使用了两个循环变量:xy. x是 中指定的for()y您正在手动跟踪。这很容易出现错误 - 只需使用一个循环变量(几乎总是最好让循环变量超过 1、2、3、...、n)

解决这些问题,我会尝试以下代码:

MarvelUniverseList = list()
offset = c(0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400)
for(i in seq_along(offset)){
  partialUrl = "https://gateway.marvel.com:443/v1/public/characters?ts=1&apikey={apiKey}&hash={hash}&limit=100&offset="  
  url = paste(partialUrl, offset[i], sep="")
  call = httr::GET(url[i])
  query = httr::content(call, as="raw")
  name = jsonlite::fromJSON(rawToChar(query))
  MarvelUniverseList[[i]] = flatten(as.data.frame(name))
}

## combine at end
MarvelUniverse = do.call(rbind, MarvelUniverseList)

## more efficient and flexible version from dplyr
MarvelUniverse = dplyr::bind_rows(MarvelUniverseList)

当然,如果没有 API 密钥,我无法对此进行测试或查看您的问题所在。dplyr::bind_rows比 灵活一点rbind,所以它可以解决你的问题。但是这种方法也有一个优点,如果组合数据帧时出现问题,您可以将各个数据帧存储在列表中,您可以检查/调试/修复它们,以便将它们组合起来。


推荐阅读