创建一个 data.frame 列是一个列表
Posted
技术标签:
【中文标题】创建一个 data.frame 列是一个列表【英文标题】:Create a data.frame where a column is a list 【发布时间】:2012-03-21 19:05:50 【问题描述】:我知道如何添加列表列:
> df <- data.frame(a=1:3)
> df$b <- list(1:1, 1:2, 1:3)
> df
a b
1 1 1
2 2 1, 2
3 3 1, 2, 3
这可行,但不行:
> df <- data.frame(a=1:3, b=list(1:1, 1:2, 1:3))
Error in data.frame(1L, 1:2, 1:3, check.names = FALSE, stringsAsFactors = TRUE) :
arguments imply differing number of rows: 1, 2, 3
为什么?
另外,有没有一种方法可以在对data.frame
的一次调用中创建df
(上图)?
【问题讨论】:
【参考方案1】:略显晦涩,来自?data.frame
:
如果将列表或数据框或矩阵传递给“data.frame”,则为 如果每个组件或列已作为单独的参数传递 (除了“model.matrix”类的矩阵和那些受保护的矩阵 “我”)。
(强调)。
所以
data.frame(a=1:3,b=I(list(1,1:2,1:3)))
似乎有效。
【讨论】:
对于那些感兴趣的人,“I”的意思是“抑制对象的交互/转换”。它创建一个相同的对象,但将“AsIs”附加到类集。 “AsIs”类实际上只是供 data.frame() 和 formula() 函数读取。了解更多here。 太棒了,感谢您的解决方案。虽然只是I
用于禁止对象的交互/转换似乎有点太短了:)
@pwilcox 非常有趣。是否有某种方法可以调用对象以了解它是否受 I 保护?我猜是class()
?例如I(iris) -> i; i %>% class() 3 [1] "AsIs" "data.frame"
(返回 AsIs 类)【参考方案2】:
如果您正在使用data.tables
,那么您可以避免调用I()
library(data.table)
# the following works as intended
data.table(a=1:3,b=list(1,1:2,1:3))
a b
1: 1 1
2: 2 1,2
3: 3 1,2,3
【讨论】:
这是data.table
的一个被低估的功能【参考方案3】:
data_frame
s(也称为tibbles
、tbl_df
、tbl
)本机支持使用data_frame
构造函数创建列表列。要使用它们,请使用它们加载许多库之一,例如 tibble
、dplyr
或 tidyverse
。
> data_frame(abc = letters[1:3], lst = list(1:3, 1:3, 1:3))
# A tibble: 3 × 2
abc lst
<chr> <list>
1 a <int [3]>
2 b <int [3]>
3 c <int [3]>
它们实际上是 data.frames
在引擎盖下,但有些修改。它们几乎总是可以正常使用data.frames
。我发现的唯一例外是,当人们进行不适当的类检查时,它们会导致问题:
> #no problem
> data.frame(x = 1:3, y = 1:3) %>% class
[1] "data.frame"
> data.frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] TRUE
> #uh oh
> data_frame(x = 1:3, y = 1:3) %>% class
[1] "tbl_df" "tbl" "data.frame"
> data_frame(x = 1:3, y = 1:3) %>% class == "data.frame"
[1] FALSE FALSE TRUE
> #dont use if with improper testing!
> if(data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something"
Warning message:
In if (data_frame(x = 1:3, y = 1:3) %>% class == "data.frame") "something" :
the condition has length > 1 and only the first element will be used
> #proper
> data_frame(x = 1:3, y = 1:3) %>% inherits("data.frame")
[1] TRUE
我建议在 R 4 Data Science 中阅读有关它们的信息(免费)。
【讨论】:
R 正在移动和成长,我认为这是 2018 年对这个问题的回答,不知何故应该这样标记。 如果它足够受欢迎,它会上升到顶部。我们中的很多人仍然使用基础 R ...【参考方案4】:您可以使用list2DF
创建一个data.frame
,其中列是list
。
x <- list2DF(list(a=1:3, b=list(1:1, 1:2, 1:3)))
#x <- data.frame(a=1:3, list2DF(list(b=list(1:1, 1:2, 1:3)))) #Alternative
x
# a b
#1 1 1
#2 2 1, 2
#3 3 1, 2, 3
str(x)
#'data.frame': 3 obs. of 2 variables:
# $ a: int 1 2 3
# $ b:List of 3
# ..$ : int 1
# ..$ : int 1 2
# ..$ : int 1 2 3
有了这个,data.frame
中的attr
AsIs
就没有了,而使用I
时会出现这种情况。
【讨论】:
以上是关于创建一个 data.frame 列是一个列表的主要内容,如果未能解决你的问题,请参考以下文章
as.data.frame 将嵌套列表展平为单行,而不是为每条记录创建行 [重复]