R-带有data.frame的意外行为(tag = value,..)



根据data.frame(...)的文档,...参数具有:

... these arguments are of either the form value or tag = value. 
    Component names are created based on the tag (if present) or 
    the deparsed argument itself.

考虑一个带有三列的数据框:A,B,C

DF <- data.frame(a=1:10, b=letters[1:10], c=rnorm(10))

现在考虑创建新数据框架的这三种可能性

newDF <- data.frame(x=DF$a)
colnames(newDF)        # as expected...
# [1] "x"
newDF <- data.frame(x=DF["a"])
colnames(newDF)        # Huh??
# [1] "a"
newDF <- data.frame(x=DF[["a"]])
colnames(newDF)        # Why is this necessary??
# [1] "x"

查看每个RHS的类:

class(DF$a)
# [1] "integer"
class(DF["a"])
# [1] "data.frame"
class(DF[["a"]])
# [1] "integer"

看来,如果RHS是一个data.frame,则tagvalue的DIMNAME覆盖。

另外,考虑到这个问题的提示,请考虑以下问题:

library(xts)
data(sample_matrix)
xtsObject=as.xts(sample_matrix)
head(xtsObject,1)
#                Open     High      Low    Close
# 2007-01-02 50.03978 50.11778 49.95041 50.11778
newDF <- data.frame(x=xtsObject$Open)    # would have expected this to work
colnames(newDF)                          # alas, no...
# [1] "Open"
class(xtsObject$Open)
# [1] "xts" "zoo"

所以我的问题是:使用data.frame(tag=value,...)时的规则是什么?也就是说,我什么时候可以期望结果有一个名为"tag"的列?

tl; dr :如果未命名提供给data.frame的对象,则结果将具有标签的名称。

让我们将可选参数称为data.frame数据。data.frame首先创建提供给它的数据的列表。然后该功能循环遍历列表的每个元素。如果列表的元素具有名称,则data.frame保留该名称。从技术上讲,它检查了提供给该功能的数据列表的每个元素i是否 length(names(data[[i]])) > 0。只有该元素没有名称,data.frame才会使用tag作为名称。

回到您的示例,请考虑提供给data.frameDF的参数名称:

names(DF$a)
# NULL
names(DF['a'])
# [1] "a"
names(DF[['a']])
# NULL

请注意,在第一种和第三种情况下,names(...)NULL。这就是为什么data.frame(x = DF$a)data.frame(x = DF[['a']])具有预期名称:x的原因。

对于更复杂的 xts对象,请注意,带有$的子集操作的结果对象具有一个名称:

names(xtsObject$Open)
#"Open"
names(xtsObject[, 'Open'])
#"Open"

因此,无论哪种情况,使用data.frame(x=xtsObject[, 'Open'])data.frame(x=xtsObject$Open)创建的数据框都将具有Open的名称。

这是在data.frame中设置名称的相关代码。请注意,xlist(...),其中...是数据。

for (i in seq_len(n)) {
  xi <- if (is.character(x[[i]]) || is.list(x[[i]])) 
    as.data.frame(x[[i]], optional = TRUE, stringsAsFactors = stringsAsFactors)
  else as.data.frame(x[[i]], optional = TRUE)
  nrows[i] <- .row_names_info(xi)
  ncols[i] <- length(xi)
  namesi <- names(xi)
  if (ncols[i] > 1L) {
    if (length(namesi) == 0L) 
      namesi <- seq_len(ncols[i])
    if (no.vn[i]) 
      vnames[[i]] <- namesi
    else vnames[[i]] <- paste(vnames[[i]], namesi, sep = ".")
  }
  else {
    if (length(namesi)) 
      vnames[[i]] <- namesi
    else if (no.vn[[i]]) {
      tmpname <- deparse(object[[i]])[1L]
      if (substr(tmpname, 1L, 2L) == "I(") {
        ntmpn <- nchar(tmpname, "c")
        if (substr(tmpname, ntmpn, ntmpn) == ")") 
          tmpname <- substr(tmpname, 3L, ntmpn - 1L)
        }
      vnames[[i]] <- tmpname
    }
  }
  if (mirn && nrows[i] > 0L) {
    rowsi <- attr(xi, "row.names")
    nc <- nchar(rowsi, allowNA = FALSE)
    nc <- nc[!is.na(nc)]
    if (length(nc) && any(nc)) 
      row.names <- data.row.names(row.names, rowsi, 
                                  i)
  }
  nrows[i] <- abs(nrows[i])
  vlist[[i]] <- xi
}

最新更新