来自JSON页面的rbind:重复rowname错误

时间:2018-02-15 19:18:55

标签: json r duplicates rbind rowname

我试图从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*tmp*,值=值)出错:   重复&#39; row.names&#39;不允许 另外:警告信息: 设置&#39; row.names&#39;:'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来访问这些数据并且运行良好,但是我想知道如何在这里解决重复行名称问题,以便我可以处理类似的情况,其中没有替代软件包是可用。

1 个答案:

答案 0 :(得分: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.