【问题标题】:How do I add an attribute to an R data.frame while I'm making it with a function?如何在使用函数制作时向 R data.frame 添加属性?
【发布时间】:2017-07-02 05:54:47
【问题描述】:

假设我有一个 R data.frame:

> x <- data.frame()

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

> (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 dataframe attributes attr


    【解决方案1】:

    请注意,R 中的数据库函数通常会返回一个数据框,因此您不必填充现有的空数据框。下面我们使用 sqldf 包来保持示例的独立性和可重复性,但您可以替换您正在使用的任何类型的数据库访问。 (通常您需要创建一个数据库连接并将其传递给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 的引用类,我们可以定义一个类,其中包含数据和查询字段以及存储查询并运行它的方法,以便每个使用 .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"
    

    【讨论】:

    • 这太好了,谢谢。但是您的回答是否暗示在这样的构造函数对象中没有self.thing 样式的赋值?
    • 如果您正在寻找一种 OO 风格,那么有许多对象系统(S3、S4、参考类)以及几个定义额外 OO 系统(proto、oo.R、R6)的包。我们在答案末尾添加的关于参考类的部分中说明了参考类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-01
    • 2017-08-26
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 2018-07-06
    相关资源
    最近更新 更多