【问题标题】:R - store a matrix into a single dataframe cellR - 将矩阵存储到单个数据框单元格中
【发布时间】:2012-11-22 01:42:21
【问题描述】:

我正在尝试将整个矩阵/数组存储到数据框的一个单个单元格中,但不太记得该怎么做。

现在在你说它不能完成之前,我确定我记得有人问过一个关于 SO 是在哪里完成的问题,尽管这不是问题的重点,所以我找不到了。

例如,您可以将矩阵存储在矩阵的单个单元格中,如下所示:

myMat <- array(list(), dim=c(2, 2))
myMat[[1, 1]] <- 1:5
myMat[[1, 2]] <- 6:10

#     [,1]      [,2]     
#[1,] Integer,5 Integer,5
#[2,] NULL      NULL

诀窍在于使用双括号[[]]

现在我只是不知道如何为数据框做这件事(或者如果可以的话):

# attempt to make a dataframe like above (except if I use list() it gets
# interpreted to mean the `m` column doesn't exist)
myDF <- data.frame(i=1:5, m=NA)
myDF[[1, 'm']] <- 1:5
# Error in `[[<-.data.frame`(`*tmp*`, 1, "m", value = 1:5) : 
#  more elements supplied than there are to replace

# this seems to work but I have to do myDF$m[[1]][[1]] to get the 1:5,
# whereas I just want to do myDF$m[[1]].
myDF[[1, 'm']] <- list(1:5)

我想我快到了。通过最后一次尝试,我可以使用myDF[[1, 'm']] 来检索list(1:5),从而通过myDF[[1, 'm']][[1]] 来获取1:5,但我更愿意只使用myDF[[1, 'm']] 并获取1:5

【问题讨论】:

  • 类似:dat&lt;-data.frame(cars, m=I(matrix(rnorm(10*nrow(cars)), nrow(cars)))); dat[["m"]]?
  • @sebastian-c 不,我希望dat[[i, 'm']] 中的矩阵为每个i 为一行,而不是dat[['m']] 为矩阵。
  • 虽然有可能,但我建议不要这样做 - 许多内部数据框代码假定列是原子向量,并在您输入列表时中断。每次我将列表放入数据框时,我都会后悔。

标签: r dataframe


【解决方案1】:

我想我解决了。重要的是初始化数据框,以便该列准备好接受矩阵。

为此,您需要给它一个列表数据类型。注意I 以保护list()

myDF <- data.frame(i=integer(), m=I(list()))

然后你可以像往常一样添加行

myDF[1, 'i'] <- 1

然后用[[]] 表示法添加矩阵

myDF[[1, 'm']] <- matrix(rnorm(9), 3, 3)

使用[[]] 符号访问:

> myDF$m[[1]]
          [,1]       [,2]       [,3]
[1,] 0.3307403 -0.2031316  1.5995385
[2,] 0.4588922  0.1631086 -0.2754463
[3,] 0.0568791  1.0358552 -0.1623794

要使用非零行进行初始化,您可以这样做(注意I 用于保护向量,vector('list', 5) 用于初始化长度为 5 的 列表以避免浪费内存):

myDF <- data.frame(i=1:5, m=I(vector('list', 5)))
myDF$m[[1]] <- matrix(rnorm(9), 3, 3)

【讨论】:

    【解决方案2】:

    我认为诀窍可能是将其作为列表插入:

    set.seed(123)
    dat <- data.frame(women, m=I(replicate(nrow(women), matrix(rnorm(4), 2, 2), 
                    simplify=FALSE)))
    
    
    str(dat)
    'data.frame':   15 obs. of  3 variables:
     $ height: num  58 59 60 61 62 63 64 65 66 67 ...
     $ weight: num  115 117 120 123 126 129 132 135 139 142 ...
     $ m     :List of 15
      ..$ : num [1:2, 1:2] -0.5605 -0.2302 1.5587 0.0705
      ..$ : num [1:2, 1:2] 0.129 1.715 0.461 -1.265
      ...
      ..$ : num [1:2, 1:2] -1.549 0.585 0.124 0.216
      ..- attr(*, "class")= chr "AsIs"
    
    dat[[1, "m"]]
               [,1]       [,2]
    [1,] -0.5604756 1.55870831
    [2,] -0.2301775 0.07050839
    
    dat[[2, "m"]]
              [,1]       [,2]
    [1,] 0.1292877  0.4609162
    [2,] 1.7150650 -1.2650612
    

    编辑:所以问题实际上是关于初始化然后分配。鉴于此,您应该能够像您的问题中那样定义一个 data.frame,如下所示:

    data.frame(i=1:5, m=I(vector(mode="list", length=5)))
    

    然后您可以像这样分配给它:

    dat[[2, "m"]] <- matrix(rnorm(9), 3, 3)
    

    【讨论】:

    • 但是我如何在 per-cell 的基础上进行分配,因为这需要我在创建时知道每个值,并且分配 dat[[1, 'm']] &lt;- list(matrix...) 仍然需要 dat$m[[1]][[1]] 到访问而不是dat$m[[1]]?
    • dat[[i, "m"]] &lt;- matrix(rnorm(4), 2, 2)dat[[i, "m"]] &lt;- matrix(rnorm(9), 3, 3) 一样工作。
    • 但是如果我将 dat 创建为dat &lt;- data.frame(i=1:5, m=NA),则以这种方式分配是行不通的。我认为它必须适当地初始化(我不知道m的值要提前输入)
    • 是的,解决了。重要的是数据框被 initialised 使用 list() 作为每个单元格的数据类型,然后分配工作。最好也将其初始化为 0 行,因为我事先不知道该列的矩阵。
    • @mathematical.coffee 我正要建议data.frame(i=1:5, m=I(vector(mode="list", length=5))); dat[[2, "m"]] &lt;- matrix(rnorm(9), 3, 3)。鉴于它是一个数据框,您应该知道行数。编辑:看到您的解决方案后,您基本上将它们初始化为长度均为 0。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2015-07-20
    相关资源
    最近更新 更多