在使用函数创建属性时,如何向 R data.frame 添加属性?

How do I add an attribute to an R data.frame while I'm making it with a function?

假设我有一个 R data.frame:

> x <- data.frame()

我还有一个 SQL 正在使用 sprintf() 构建的查询:

> (query <- sprintf("select %s from %s %s", "names", "name_table", "where age > 20"))
[1] "select names from name_table where age > 20"

我打算将其包含在一个函数中,以便用 query 的结果填充 data.frame x,并且只是为了在顶部洒上几滴我想告诉未来的自己 query 是用来生成 data.frame x 的。我想像这样调用 attr() 来做到这一点:

> attr(x, "query") <- query
> str(x)
'data.frame':   0 obs. of  0 variables
 - attr(*, "query")= chr "select names from name_table where age > 20"

因为函数看起来像

answer_maker <- function(col_names, table_name, condtions) {

                   query <- sprintf("select %s from %s %s", col_names, table_name, conditions)

                   data.frame(sql(query))

    ############## WHAT DO I DO HERE? 
    ############## I want to type something py-like ...self.attr()?
                   attr(self, "query") <- query
               }

稍后我将能够执行以下操作

> my_first_answer <- answer_maker("names", "name_table", "where age > 20")
> attr(my_first_answer, "query")
[1] "select names from name_table where age > 20"

请注意,R 中的数据库函数通常 return 一个数据框,因此您不必填充一个空的现有数据框。下面我们使用 sqldf 包来保持示例 self-contained 和可重现性,但您可以替换您正在使用的任何类型的数据库访问。 (通常您需要创建数据库连接并将其传递给 answer_maker,但在本例中,因为我们使用的是 sqldf,所以不需要。)

library(sqldf)   
name_table <- data.frame(names = letters, age = 1:26) # test data

answer_maker <- function(col_names, table_name, conditions) {
      query <- sprintf("select %s from %s %s", col_names, table_name, conditions)
      ans <- sqldf(query)
      attr(ans, "query") <- query
      ans
}

ans <- answer_maker("names", "name_table", "where age > 20")

给予:

> ans
  names
1     u
2     v
3     w
4     x
5     y
6     z

> attr(ans, "query")
[1] "select names from name_table where age > 20"

引用类使用R的引用classes我们可以定义一个class包含数据和查询字段以及存储查询的方法和 运行 这样每个输出对象都使用 .self :

Query <- setRefClass("Query", fields = c("data", "query"),
   methods = list(
      setQuery = function(col_names, table_name, conditions) {
          query <<- sprintf("select %s from %s %s", col_names, table_name, conditions)
          .self
      },
      runQuery = function() {
          data <<- sqldf(query)
          .self
      }))

qq <- Query$
        new()$
        setQuery("names", "name_table", "where age > 20")$
        runQuery()

给予:

> qq$data
  names
1     u
2     v
3     w
4     x
5     y
6     z
> qq$query
[1] "select names from name_table where age > 20"