在 R 中构建动态点列表以一次一行读取数据帧?

问题描述 投票:0回答:1

我正在尝试从数据帧中一次一行构建 GET 请求,其中可能的参数是一个多种多样的大型列表,并且我传递给函数的数据帧可能没有正确命名的列标题。

起始数据示例

library(tidyverse)
library(httr2)

dfInput <- structure(list(orig_zip = c("17502", "66616", "M1P2T7"),
                     orig_ctry = c("USA", "MEX", "CAN")),
                row.names = c(NA, 3L), class = "data.frame")
> dfInput
  orig_zip orig_ctry
1    17502       USA
2    66616       MEX
3   M1P2T7       CAN

演示功能1

第一个函数显示了从数据帧的每一行获取的所需输出,但在这里我对其进行了硬编码,而不是实际使用我想要的

...
。在编写时选择什么参数没有灵活性,但是
postalcode = df$orig_zip[i], country = df$orig_ctry[i]
是我需要的代码类型
req_url_query()
:

f1 <- function(df, ...){

  req <- httr2::request("http://some/base/url")

  for (i in 1:nrow(df)){
    req %>%
      req_url_query(postalcode = df$orig_zip[i], country = df$orig_ctry[i]) %>%
      req_dry_run()
  }
}

> f1(dfInput, postalcode = orig_zip, country = orig_ctry)

GET /base/url?postalcode=17502&country=USA HTTP/1.1
***OUTPUT TRUNCATED***
GET /base/url?postalcode=66616&country=MEX HTTP/1.1
***OUTPUT TRUNCATED***
GET /base/url?postalcode=M1P2T7&country=CAN HTTP/1.1
***OUTPUT TRUNCATED***

演示功能2

此函数使用

...
,但我在函数调用中传递实际值,显然这不会通过数据帧进行。

f2 <- function(df, ...){
  
  req <- httr2::request("http://some/base/url")
  
  for (i in 1:nrow(df)){
    req %>%
      req_url_query(...) %>%
      req_dry_run()
  }
}

> f2(dfInput, postalcode = "17502", country = "USA")

GET /base/url?postalcode=17502&country=USA HTTP/1.1
***OUTPUT TRUNCATED***
GET /base/url?postalcode=17502&country=USA HTTP/1.1
***OUTPUT TRUNCATED***
GET /base/url?postalcode=17502&country=USA HTTP/1.1
***OUTPUT TRUNCATED***

其他努力

我做了一些努力(未全部显示)来尝试各种

rlang
引用功能,直到达到您在下面看到的内容,但我觉得这可能与一些更简单的过程相距太远。

f3 <- function(df, ...){
  
  args <- list2(enexprs(...))
  print(args)
  a1 <- lapply(args, \(x) paste0(".data$", x, "[i]"))
  print(a1)
  # req <- httr2::request("http://some/base/url")
  
  # for (i in 1:nrow(df)){
  #   req %>%
  #     req_url_query(...) %>%
  #     req_dry_run()
  # }
}

> f3(dfInput, postalcode = orig_zip, country = orig_ctry)
[[1]]
[[1]]$postalcode
orig_zip

[[1]]$country
orig_ctry


[[1]]
[1] ".data$orig_zip[i]"  ".data$orig_ctry[i]"

我仍在努力解决这个问题,但在燃烧了几个小时后,我没有得到它,需要一些帮助。我很感激你能提供的任何东西。谢谢你。

编辑已于美国东部时间 2023 年 8 月 18 日上午 12:17 添加

目标(按优先顺序):

  1. 编写一个包质量函数,该函数将接受数据帧和未指定数量的参数,这些参数可以一次生成一行 GET 请求。我相信
    ...
    是必要的,但我是一名 padawanR,而不是 JediR,所以我在这一点上持开放态度。
  2. 更广泛地说,我试图理解 rlang、tidyeval、data-masking、quosures、quasiquotation、NSE 等。我觉得其中一些与这里相关,但再次...... padawanR(在之后获得 883 的声誉) 9 年;-) )
  3. 更具体地说,正如我在上面的演示函数中所阐述的,我有一个奇怪的情况,感觉这应该是一个有点常见的问题:我需要从具有列名的数据框中一次获取
    list(postalcode = "17502", country = "USA")
    一行
     orig_zip
    orig_ctry
    但是下次我使用该函数时,我可能需要从包含列
    list(address = "1 Infinite Loop", city = "Redmond", state = "TN")
    orig_addr
    orig_city
    的数据框中传递
    orig_state
    。因此,我有灵活的函数参数(
    postalcode
    ),它必须指向数据框的列名称(
    orig_zip
    ),它必须一次指向该列中的一个值(“17502”)。你是怎么做到的?
r rlang tidyeval httr2
1个回答
0
投票

技巧是使用点来构建一个中间数据框,其中

transmute()
仅包含感兴趣的列。

然后使用

!!!
注入行,但由于您是在数据屏蔽上下文之外执行此操作,因此我们需要使用
inject()
显式启用注入。

f <- function(df, ...) {
  req <- httr2::request("http://some/base/url")

  # Transform to tibble to make sure `[` behaves predictably.
  # Also prevents grouped df to disturb behaviour.
  # Use `transmute()` to reduce the data frame to passed inputs.
  df <- df |> as_tibble() |> transmute(df, ...)

  for (i in seq_len(nrow(df))) {
    # Inject rows into the query with `!!!`
    rlang::inject(
      req %>%
        req_url_query(!!!df[i, ]) %>%
        req_dry_run()
    )
  }
}

f(dfInput, postalcode = orig_zip, country = orig_ctry)
#> GET /base/url?orig_zip=17502&orig_ctry=USA&postalcode=17502&country=USA HTTP/1.1
#> Host: some
#> User-Agent: httr2/0.2.3 r-curl/5.0.1 libcurl/7.85.0
#> Accept: */*
#> Accept-Encoding: deflate, gzip
#>
#> GET /base/url?orig_zip=66616&orig_ctry=MEX&postalcode=66616&country=MEX HTTP/1.1
#> Host: some
#> User-Agent: httr2/0.2.3 r-curl/5.0.1 libcurl/7.85.0
#> Accept: */*
#> Accept-Encoding: deflate, gzip
#>
#> GET /base/url?orig_zip=M1P2T7&orig_ctry=CAN&postalcode=M1P2T7&country=CAN HTTP/1.1
#> Host: some
#> User-Agent: httr2/0.2.3 r-curl/5.0.1 libcurl/7.85.0
#> Accept: */*
#> Accept-Encoding: deflate, gzip
© www.soinside.com 2019 - 2024. All rights reserved.