首页 > 解决方案 > 创建函数/循环

问题描述

我从 API 中提取数据,但出于此目的,我将使用虚拟数据:

test <- structure(list(Id = 201:203, firstname = c("Jackie", "Liz", "Jack"), 
                       lastname = c("Jormpjomp", "Lemon", "Donaghy"), 
                       address = c("4 Main St.", "5 Main St.", "6 Main St."), 
                       zip = c(89044L, 60301L, 85281L), 
                       dob = c(NA, "7/1/88", "2/13/90"), 
                       phone = c("333-333-3333","4444", "555-555-5555"), 
                       statecode = c("NV", "WI", "AZ")), 
                  class = "data.frame", 
                  row.names = c(1, 2, 3))
                                                                

首先,我将所有需要的变量隔离为它们自己的值:

Ids <- test$Id
firstnames <- test$firstname
lastnames <- test$lastname
addresses <- test$address
zips <- test$zip
dobs <- test$dob
phones <- test$phone

然后我创建一个字符向量以添加到最终的 API 调用中:

data_upsert = paste0(
    '{ "Id": ', Ids, ',
  "firstName": "', firstnames, '",
  "lastname": "', lastnames, '",
  "dateOfBirth": "', dobs, '",
  "phones": [ 
               { "phoneNumber": "', phones, '" } ], 
               "addresses": [ 
               { "addressLine1": "', addresses, '", 
               "zipOrPostalCode": "', zips, '",
               } ] } 
  ')

然后我为我的标题创建一个变量 - 这将始终保持不变

headers_upsert = c(
  `Accept` = 'application/json',
  `Authorization` = 'Basic JFOJDIFvdhSOFOHAD83820348voqpTOESV==',
  `Content-Type` = 'application/json'
)

最后,我完成了 API 调用,如下所示:

upsert <- httr::POST(url = 'https://api.secure.com/v1/people/Create', httr::add_headers(.headers=headers_upsert), body = data_upsert)

运行它会创建一个如下所示的响应:

Response [https://api.secure.com/v1/people/Create]
  Date: 2021-08-31 20:28
  Status: 201
  Content-Type: application/json; charset=utf-8
  Size: 58 B
{
  "Id": 222323178,
  "status": "UnmatchedStored"

然后我想以表格形式存储这个响应:

resContent <- content(res, as="text")

resJSON <- jsonlite::fromJSON(resContent)

resTable <- as.data.frame(resJSON)

如果您运行上面的所有内容,它显然只适用于 中的第一行test,但我正在寻找一种时尚的方式来编写一个函数和循环:

A) 为所有三行运行 API 调用

B) 创建一个包含所有三个响应的表

编辑:根据 Bing 的回复:

运行 Bing 的响应后,它完成了第一部分,但问题在于最后制作表格。

结果response如下所示:

[[1]]
Response [https://api.secure.com/v1/people/111322450]
  Date: 2021-09-01 15:02
  Status: 200
  Content-Type: application/json; charset=utf-8
  Size: 1.56 kB
{
  "Id": 111322450,
  "firstName": "Jackie",
  "lastName": "Jormpjomp",
  "middleName": null,
  "suffix": null,
  "title": "Mr.",
  "contactMode": "Person",
  "organizationContactCommonName": null,
  "organizationContactOfficialName": null,
...

[[2]]
Response [https://api.secure.com/v1/people/findOrCreate/]
  Date: 2021-09-01 15:02
  Status: 201
  Content-Type: application/json; charset=utf-8
  Size: 58 B
{
  "Id": 111323215,
  "status": "UnmatchedStored"

[[3]]
Response [https://api.secure.com/v1/people/findOrCreate/]
  Date: 2021-09-01 15:02
  Status: 201
  Content-Type: application/json; charset=utf-8
  Size: 58 B
{
  "Id": 111323216,
  "status": "UnmatchedStored"

当我运行时:

resContent=map(response , httr::content, as="text")

resJSON <- map(resContent, jsonlite::fromJSON)

resTable <- map(resJSON, as.data.frame)

resTable仍然存储为一个看起来像这样的列表编辑

$data
$data[[1]]
Response [https://api.secure.com/v1/people/111322450]
  Date: 2021-09-01 18:24
  Status: 200
  Content-Type: application/json; charset=utf-8
  Size: 1.58 kB
{
  "Id": 111322450,
  "firstName": "Jackie",
  "lastName": "Jormpjomp",
  "middleName": null,
  "suffix": null,
  "title": null,
  "contactMode": "Person",
  "organizationContactCommonName": null,
  "organizationContactOfficialName": null,
...

$data[[2]]
Response [https://api.secure.com/v1/people/findOrCreate/]
  Date: 2021-09-01 18:24
  Status: 201
  Content-Type: application/json; charset=utf-8
  Size: 58 B
{
  "Id": 111323215,
  "status": "UnmatchedStored"

$data[[3]]
Response [https://api.secure.com/v1/people/findOrCreate/]
  Date: 2021-09-01 18:24
  Status: 201
  Content-Type: application/json; charset=utf-8
  Size: 58 B
{
  "Id": 111323216,
  "status": "UnmatchedStored"


$args
$args[[1]]
[1] "map(jsonlite::fromJSON)"
attr(,"type")
[1] "map"

$args[[2]]
[1] "map(as.data.frame)"
attr(,"type")
[1] "map"


attr(,"class")
[1] "jqr"

我需要从每个响应中获取的唯一数据是Id

编辑#2

运行以下:

resContent=map(response , httr::content)   
    
resTable <- map(resContent, ~.x$Id) %>% as.data.frame()

返回以下错误:

Error in as.data.frame.default(.) : 
  cannot coerce class ‘&quot;jqr"’ to a data.frame

标签: rfunctionpurrrhttr

解决方案


httr::POST 未矢量化。您将需要遍历每一个。您可以使用lapply或整洁的版本,例如:

library(purrr)
response = map(data_upsert,
  ~httr::POST(url = 'https://www.google.com/', 
           httr::add_headers(.headers=headers_upsert), 
           body = .x))

看看这些是否有效。编辑

resContent=map(response , httr::content)   
    
resTable <- map(resContent, ~.x$Id) #%>% as.data.frame()

推荐阅读