【问题标题】:Create a data.frame where a column is a list创建一个 data.frame 列是一个列表
【发布时间】: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(上图)?

【问题讨论】:

    标签: r list dataframe


    【解决方案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) -&gt; i; i %&gt;% 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_frames(也称为tibblestbl_dftbl)本机支持使用data_frame 构造函数创建列表列。要使用它们,请使用它们加载许多库之一,例如 tibbledplyrtidyverse

    > 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 时会出现这种情况。

    【讨论】:

      猜你喜欢
      • 2016-01-02
      • 1970-01-01
      • 2013-07-13
      • 1970-01-01
      • 2022-07-05
      • 1970-01-01
      相关资源
      最近更新 更多