0

我试图 rbind 从 api 抓取的一些 json 数据

library(jsonlite)

pop_dat <- data.frame()

for (i in 1:3) {

# Generate url for each page
url <- paste0('http://api.worldbank.org/v2/countries/all/indicators/SP.POP.TOTL?format=json&page=',i)

# Get json data from each page and transform it into dataframe
dat <- as.data.frame(fromJSON(url)[2],flatten = TRUE, row.names = NULL)
pop_dat <- rbind(pop_dat, dat)
               }

但是,它返回以下错误:

row.names<-.data.frame( , value = value)中的错误*tmp*:不允许重复的“row.names”另外:警告消息:设置“row.names”时的非唯一值:“1”、“10”、“11”、“12” ','13','14','15','16','17','18','19','2','20','21','22','23', '24'、'25'、'26'、'27'、'28'、'29'、'3'、'30'、'31'、'32'、'33'、'34'、'35' ','36','37','38','39','4','40','41','42','43','44','45','46', '47'、'48'、'49'、'5'、'50'、'6'、'7'、'8'、'9'

将 row.names 更改为 null 不起作用。我从某人那里听说这是因为有些数据在这里存储为列表,我不太明白。

我知道有一个替代包 WDI 可以访问此数据并且它运​​行良好,但我想知道如何解决这里的重复行名称问题,以便我可以处理没有替代包可用的类似情况。

4

1 回答 1

1

我从某人那里听说这是因为某些数据存储为列表...

这是对的。解决方案相当简单,但我发现很容易被它绊倒。现在你正在使用:

dat <- as.data.frame(fromJSON(url)[2],flatten = TRUE, row.names = NULL)

问题来自fromJSON(url)[2]. 这应该是fromJSON(url)[[2]]相反的。[根据文档,和之间的主要区别[[是单个括号可以选择多个元素,而[[只能选择一个。

你可以看到它是如何处理一些假数据的。

 foo <- list(
  a = rnorm(100),
  b = rnorm(100),
  c = rnorm(100)
)

使用[,您可以在此列表中选择多个值。

 foo[c("a", "b")]
 length(foo["a"]) # Result is 1 not 100 like you might expect.

[[结果不同。

foo[[c("a", "b")]] # Raises a subscript error.
foo[["a"]] #This works.
length(foo[["a"]]) # Result is 100.

因此,您的答案将取决于您使用的子集运算符。对于您的问题,您需要使用[[在列表中选择单个 data.frame。然后,您应该能够正确使用 rbind。

final <- data.frame()
for (i in 1:10) {
  url <- paste0(
    'http://api.worldbank.org/v2/countries/all/indicators/SP.POP.TOTL?format=json&page=',
    i
  )

  res <- jsonlite::fromJSON(url, flatten = TRUE)[[2]]
  final <- rbind(final, res)
}

lapply 的替代解决方案:

urls <- sprintf(
  'http://api.worldbank.org/v2/countries/all/indicators/SP.POP.TOTL?format=json&page=%s',
  1:10
)

resl <- lapply(urls, jsonlite::fromJSON, flatten = TRUE)
resl <- lapply(resl, "[[", 2) # Use lapply to select the 2 element from each list element.
resl <- do.call(rbind, resl) # This takes all the elements of the list and uses those elements as the arguments for rbind.
于 2018-02-15T21:27:53.957 回答