【问题标题】:How does data.table get the column name from j?data.table 如何从 j 中获取列名?
【发布时间】:2013-12-30 23:32:15
【问题描述】:

例如:

dt <- data.table()
x=1:5
> dt[,list(2,3,x)]
   V1 V2 x
1:  2  3 1
2:  2  3 2
3:  2  3 3
4:  2  3 4
5:  2  3 5

生成的 data.table 有列 x

出于某种原因,我想创建一个函数来简化 data.table 的构造。

tt <- function(a, b, ...){
    list(a=sum(a), b=sum(b), ...)
}

> dt[,tt(1:2,1:3,x)]
   a b V3
1: 3 6  1
2: 3 6  2
3: 3 6  3
4: 3 6  4
5: 3 6  5

所以每当我调用list 时,我都会改用tt,所以它会自动为我插入预定义的列。 但是,现在它无法识别x 的快捷方式命名。

如果不太难,如何将tt 改进为data.table 中list 等自动命名列?

瞄准

dt[,tt(1:2,1:3,x)]

返回

   a b  x
1: 3 6  1
2: 3 6  2
3: 3 6  3
4: 3 6  4
5: 3 6  5

解决方案

tt <- function(a, b, ...){
    dots <- list(...)
    inferred <- sapply(substitute(list(...)), function(x) deparse(x)[1])[-1]
    if(is.null(names(inferred))){
        names(dots) <- inferred
    } else {
        names(dots)[names(inferred) == ""] <- inferred[names(inferred) == ""]
    }
    c(a=sum(a), b=sum(b), dots)
}

dt <- data.table(c=1:5)
x=1:5

> dt[,tt(1:2,1:3,x,c+1)]
   a b x c + 1
1: 3 6 1     2
2: 3 6 2     3
3: 3 6 3     4
4: 3 6 4     5
5: 3 6 5     6
> dt[,tt(1:2,1:3,x, z=c+1)]
   a b x z
1: 3 6 1 2
2: 3 6 2 3
3: 3 6 3 4
4: 3 6 4 5
5: 3 6 5 6

更新

最近我发现 Venables & Ripley 的 S Programming 第 46 页存在一些错误。我做了一些修改并把它放在这里。希望它对某些人有用。

# Get the best names vector for arguments like what data.frame does.
# Modified from page 46 of S Programming from Venables & Ripley.
# http://stackoverflow.com/questions/20545476/how-does-data-table-get-the-column-name-from-j
name.args <- function(...){
    # Get a list of arguments.
    dots <- as.list(substitute(list(...)))[-1]
    # Get names of the members if they have, otherwise "".
    # If a list have no named members, it returns NULL.
    nm <- names(dots)
    # If all arguments are named, return the names directly.
    # Otherwise it would cause a problem when do nm[logic(0)] <- list().
    if (!is.null(nm) && all(nm != ""))
        return(nm)
    # Handle empty argument list case.
    if (length(dots) == 0)
        return(character(0))
    # Get positions of arguments without names.
    fixup <- 
        if (is.null(nm))
            seq(along=dots)
        else
            nm == ""
    dep <- sapply(dots[fixup], function(x) deparse(x)[1])
    if (is.null(nm))
        dep
    else {
        nm[fixup] <- dep
        nm
    }
}

# Example
# x <- 1:2
# name.args(x, y=3, 5:6)
# name.args(x=x, y=3)
# name.args()

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    一个简单的解决方案是将附加参数作为 named 而不是 unnamed 参数传递:

    dt[,tt(1:2,1:3,x=x)]   ## Note that this uses `x=x` rather than just `x`
    #    a b x
    # 1: 3 6 1
    # 2: 3 6 2
    # 3: 3 6 3
    # 4: 3 6 4
    # 5: 3 6 5
    

    或者对于真正懒惰的人来说,像这样;)

    tt <- function(a, b, ...){
        dots <- list(...)
        names(dots) <- as.character(substitute(list(...))[-1])
        c(a=sum(a), b=sum(b), dots)
    }
    dt[,tt(1:2,1:3,x)]
    #    a b x
    # 1: 3 6 1
    # 2: 3 6 2
    # 3: 3 6 3
    # 4: 3 6 4
    # 5: 3 6 5
    

    【讨论】:

    • 当然我知道我总是可以明确表达...我正在寻找一个懒惰的解决方案。
    • 好的 - 从您的预编辑问题中并不清楚。添加了适用于未命名参数的解决方案。 (如果你想使用命名和未命名的附加参数的组合,你可能需要做一些额外的处理来合并提供的和隐含的名称。)
    • 我更喜欢as.character(substitute(list(...))[-1])(请注意,“列表”部分无关紧要,只要它看起来像一个函数就可以在那里做任何事情)而不是sapply(match.call(...,因为我有一些后者的问题
    • @eddi -- 我在他们的 MASS 书的第 46 页上看到了这一点(他们在其中展示了上述内容的增强版本,用于处理命名和未命名的参数)Venables 和 Ripley 使用 sapply(dots, function(x) deparse(x)[1])。我敢打赌[1] 会避免使用sapply() 可能出现的问题...
    • 无权访问该书,并且 Google 图书预览无法用于第 46 页...(第 45,48 页均可用)。但是,我设法找到了这个:codecollector.net/view/…
    【解决方案2】:

    更简单的解决方案依赖于tibble::lst

    library(data.table)
    
    tt <- function(a, b, ...){
      tibble::lst(a=sum(a), b=sum(b), ...)
    }
    
    dt <- data.table(c=1:5)
    x=1:5
    
    dt[, tt(1:2, 1:3, x, c+1)]
    #>    a b x c + 1
    #> 1: 3 6 1     2
    #> 2: 3 6 2     3
    #> 3: 3 6 3     4
    #> 4: 3 6 4     5
    #> 5: 3 6 5     6
    dt[, tt(1:2, 1:3, x, z=c+1)]
    #>    a b x z
    #> 1: 3 6 1 2
    #> 2: 3 6 2 3
    #> 3: 3 6 3 4
    #> 4: 3 6 4 5
    #> 5: 3 6 5 6
    

    【讨论】:

      猜你喜欢
      • 2018-10-29
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      • 2021-06-14
      • 2013-12-24
      • 2017-02-04
      • 1970-01-01
      相关资源
      最近更新 更多