【问题标题】:Loop Stops when API returns NULL in R当 API 在 R 中返回 NULL 时循环停止
【发布时间】:2020-07-22 06:40:47
【问题描述】:

我正在循环通过一个 API 来匹配字符串并根据我自己的参考数据集标准化数据。在大多数情况下,API 会给出响应,并将结果填充到输出文件中。但是,当 API 返回 NULL 时,循环停止,我需要删除特定的字符串以使其再次运行。这是一个严重的迭代过程。有什么办法

  1. 查找 API 将返回 NULL 的字符串?这样的字符串可以在我们的数据中修复
  2. 在输出文件中为返回 NULL 的字符串填充 NULL 或 NA

我无法共享 API,因为它是在组织内部开发的,但会共享代码。

DESTINATIONS<- subset(DESTINATIONS, DESTINATIONS!="ABCDEF")


df <- data.frame()

for(i in 1:nrow(DESTINATIONS))
{
  
  location_url <- paste0(base_url, "destinations?name=", DESTINATIONS(DESTINATIONS))[i],specs)
  
  
  
destination_res <- GET(location_url)
   
destination_text <- content(destination_res, "text", encoding = "UTF-8")
  
location_df1 <- fromJSON(destination_text, flatten = TRUE)
  
location_df1 <- do.call(c, unlist(location_df1, recursive=FALSE))
  
location_df1 <- as.data.frame(t(location_df1))

coordinates_a <- select(location_df1, contains("items.country.name"))
  
coordinates_a <- coordinates_a %>% distinct() %>% t()
  
coordinates_a <- as.data.frame(coordinates_a)
  
coordinates_b <- select(location_df1, contains("items.id"))
  
coordinates_b <- coordinates_b %>% distinct() %>% t()
  
coordinates_b <- as.data.frame(coordinates_b)

coordinates <-  cbind.data.frame(coordinates_a, coordinates_b)

df <- rbind.data.frame(df, coordinates)}

简而言之,如果 DESTINATIONS 数据帧中的字符串没有来自 API 的响应,则循环中断

感谢您提前提供的所有帮助。

【问题讨论】:

  • 当你说“breaks”时,你的意思是“throws an error”吗?如果是这样,tryCatch() 可能是您的解决方案。
  • “中断”是指它处理该字符串之前的所有字符串并将它们存储在输出文件中。然后我删除这个字符串,然后开始处理字符串。
  • 这不是我问的。你怎么知道代码“坏了”?您是否收到错误或警告消息?您不检查对GET 的回复状态。如果您的 API 表现良好,那应该会对您有所帮助。等等。如果您希望我们帮助您,您需要提供完整且准确的信息。我们现在所拥有的都不是。
  • Error in `$&lt;-.data.frame`(`*tmp*`, "DEST", value = "ABCDEF") : replacement has 1 row, data has 0 这是我遇到的错误
  • 所以现在您有了一种可能的解决方案。找到引发错误的行(如果必须,请使用多个 print 语句,并测试零行的数据框。此外,您真的应该在执行任何其他操作之前测试响应的状态代码。如果您有这样做,而且你的 API 写得很好,那几乎肯定会在一开始就避免这个问题。

标签: r api httr jsonlite rjsonio


【解决方案1】:

假设GET 请求将返回NULL,您可以检查它是否为length

尝试使用这样的东西:

data_list <- vector('list', nrow(DESTINATIONS))

for(i in 1:nrow(DESTINATIONS)) {
   location_url <- paste0(base_url, "destinations?name=", 
                          DESTINATIONS(DESTINATIONS))[i],specs)
   destination_res <- GET(location_url)
   if(length(destination_res) > 0) {
      destination_text <- content(destination_res, "text", encoding = "UTF-8")
      location_df1 <- fromJSON(destination_text, flatten = TRUE)
      location_df1 <- do.call(c, unlist(location_df1, recursive=FALSE))
      location_df1 <- as.data.frame(t(location_df1))
      coordinates_a <- select(location_df1, contains("items.country.name"))
      coordinates_a <- coordinates_a %>% distinct() %>% t()
      coordinates_a <- as.data.frame(coordinates_a)
      coordinates_b <- select(location_df1, contains("items.id"))
      coordinates_b <- coordinates_b %>% distinct() %>% t()
      coordinates_b <- as.data.frame(coordinates_b)
      coordinates <-  cbind.data.frame(coordinates_a, coordinates_b)
     }
   else coordinates <- NA
   data_lst[[i]] <- coordinates
}

现在,可以通过以下方式找到失败的请求:

which(is.na(data_lst))

要将数据绑定在一起,您可以删除那些 NA 值。

complete_data <- do.call(rbind, Filter(is.data.frame, data_lst))

【讨论】:

  • 循环运行良好。但是当我尝试使用原始字符串添加一列时,我得到了同样的错误。我正在添加coordinates$DEST &lt;- DESTINATIONS$DESTINATIONS[i]。我尝试了 100 个字符串,得到了 90 个的结果,这似乎是正确的。另外,which(is.na(data_list)) 给了我integer(0)
  • 嗯....抱歉,我不明白您为什么/如何会收到此错误。如果没有可重现的例子,这就是我能想到的。
  • 为了不停止循环,我通过检查模式添加了一个特定于我的 API 输出的 IF 语句。由于这不是一个通用的答案,我不知道我是否应该发布它。
  • 如果它解决了你的问题,你一定要发布它。
猜你喜欢
  • 2020-06-04
  • 1970-01-01
  • 2021-01-06
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
  • 2021-08-06
  • 1970-01-01
  • 2022-01-02
相关资源
最近更新 更多