没有列名的data.frames会出现意外行为。以下按预期工作:
df <- data.frame(a = 1:5, b = 5:9)
df + 1
## a b
## 1 2 6
## 2 3 7
## 3 4 8
但是如果我们删除列名,那么行为很奇怪:
names(df) <- NULL
df + 1
## data frame with 0 columns and 0 rows
如果使用unname
,setNames
删除名称,则会发生同样的情况。任何关于为什么会发生这种情况的想法(由于某种原因)是预期的行为吗?
修改:
所以有记录表明无名data.frame
的结果不受支持(感谢@neilfws,@ Suren),但我也对发生这种情况的原因感兴趣。我试图找到实际的c(?)代码,使这个简单的例子制动。
答案 0 :(得分:7)
在data.frame
的文档中,它说:
列名称应为非空,并且尝试使用空名称将产生不受支持的结果。
因此,如果列名为空,则预计结果可能不是所需的结果。
答案 1 :(得分:1)
我认为这最终来自R将data.frame
对象视为具有特定属性的列表的事实:
## A list with no attributes
list_no_attr1 <- list(c(1,2,3), c(3,2,1))
## The attributes and class of the list
attributes(list_no_attr1)
#> NULL
class(list_no_attr1)
#> "list"
然后,我们可以手动添加所有data.frame
属性,而无需更改list
的结构:
## Adding the names to the list (not in the attributes)
list2 <- list_no_attr1
attr(list2, "names") <- c("A", "B")
## The attributes and class of the list
attributes(list2)
#> $names
#> [1] "A" "B"
class(list2)
#> "list"
## Adding the "row.names" attributes
list3 <- list2
attr(list3, "row.names") <- c("1", "2", "3")
## The attributes and class of the list
attributes(list3)
#> $names
#> [1] "A" "B"
#> $row.names
#> [1] "1" "2" "3"
class(list3)
#> "list"
这仍然是一个清单。现在,当我们将对象的类更改为"data.frame"
时,它将使用data.frame
的{{1}}的S3方法和所有其他相关函数
print
现在将打印为正确的## Adding a data.frame class attribute
list_data_frame <- list3
attr(list_data_frame, "class") <- "data.frame"
## The attributes and class of the list
attributes(list_data_frame)
#> $names
#> [1] "A" "B"
#> $row.names
#> [1] "1" "2" "3"
#> $class
#> [1] "data.frame"
class(list_data_frame)
#> "data.frame"
。请注意,它的工作方式完全相同,如果我们删除了class属性,可以将data.frame
转换回data.frame
。
list
当然,只有列表中的元素长度相同时才有效:
## The dataframe
data_frame <- data.frame("A" = c(1,2,3), "B" = c(3,2,1))
## The attributes and class of the list
attributes(data_frame)
#> $names
#> [1] "A" "B"
#> $row.names
#> [1] "1" "2" "3"
#> $class
#> [1] "data.frame"
class(data_frame)
#> "data.frame"
## "Converting" into a list
attr(data_frame, "class") <- NULL
attributes(data_frame)
#> $names
#> [1] "A" "B"
#> $row.names
#> [1] "1" "2" "3"
class(data_frame)
#> "list"
如果忽略其他评论中提及的## Creating an unequal list with data.frame attributes
wrong_list <- list(c(1,2,3), c(3,2,1,0))
attr(wrong_list, "names") <- c("A", "B")
attr(wrong_list, "row.names") <- c("1", "2", "3")
attr(wrong_list, "class") <- "data.frame"
wrong_list
#> A B
#> 1 1 3
#> 2 2 2
#> 3 3 1
#> Warning message:
#> In format.data.frame(x, digits = digits, na.encode = FALSE) :
#> corrupt data frame: columns will be truncated or padded with NAs
和names
属性以及此问题的答案,也会出现错误:
row.names