将矩阵转换为数据帧:在一种情况下工作,而不是另一种情况

时间:2013-07-25 20:44:42

标签: r matrix dataframe

下面是一个示例会话输出的剪辑。在其中,我使用matrix()函数创建一个矩阵,并将其简单地转换为具有as.data.frame()函数的数据框。在第二部分中,我还创建了一个矩阵,但是通过一个不同的过程(我想要工作的那个),但即使str()给出了类似的输出,转换到数据帧时也会出错。有什么想法吗?

编辑:最后,我添加了一行,我将(重新)矩阵转换为矩阵,然后将其转换为数据帧。它可以工作,但我不应该根据我在str()的{​​{1}}输出中看到的那些不能被转换成数据帧的东西重铸。所以我知道如何修复,但我不明白为什么我需要做额外的步骤来这样做。

test_mx

2 个答案:

答案 0 :(得分:11)

虽然@ agstudy的答案解决了您的问题并让您及时了解最新的软件包,但它并没有尝试理解为什么会发生这种情况。

要了解原因,请返回第test_mx = cast(melt(dat, id.vars="t"), variable ~ t)行。我将在这里创建两个对象,以便我们进行一些比较:

test_mx <- test_mx_cast <- cast(melt(dat, id.vars="t"), variable ~ t)
class(test_mx)
# [1] "cast_df"    "data.frame"
class(test_mx_cast)
# [1] "cast_df"    "data.frame"

嗯。这个cast_df课程是什么?事实证明,“重塑”方法已经过去并定义了几种新方法。例如,请参阅methods(as.data.frame)methods(as.matrix)

> methods(as.matrix)
[1] as.matrix.cast_df     as.matrix.cast_matrix as.matrix.data.frame  as.matrix.default    
[5] as.matrix.dist*       as.matrix.noquote     as.matrix.POSIXlt     as.matrix.raster*    

   Non-visible functions are asterisked
> methods(as.data.frame)
 [1] as.data.frame.aovproj*        as.data.frame.array           as.data.frame.AsIs           
 [4] as.data.frame.cast_df         as.data.frame.cast_matrix     as.data.frame.character      
 [7] as.data.frame.complex         as.data.frame.data.frame      as.data.frame.Date           
[10] as.data.frame.default         as.data.frame.difftime        as.data.frame.factor         
[13] as.data.frame.ftable*         as.data.frame.function*       as.data.frame.idf*           
[16] as.data.frame.integer         as.data.frame.list            as.data.frame.logical        
[19] as.data.frame.logLik*         as.data.frame.matrix          as.data.frame.model.matrix   
[22] as.data.frame.numeric         as.data.frame.numeric_version as.data.frame.ordered        
[25] as.data.frame.POSIXct         as.data.frame.POSIXlt         as.data.frame.raw            
[28] as.data.frame.table           as.data.frame.ts              as.data.frame.vector         

   Non-visible functions are asterisked

注意上面^^ as.matrix的第一和第二种方法以及as.data.frame的第四和第五种方法。

这是什么意思?好吧,在您创建test_mx以将data.frame转换为matrix后,您去了几行。这主要是因为您希望确保第一列最终为rownames,并且不会将整个矩阵强制转换为字符矩阵。

tmp_rownames = as.character(test_mx[,1])
test_mx = test_mx[,-1]
tmp_colnames = colnames(test_mx)
test_mx = as.matrix(test_mx)
rownames(test_mx) = tmp_rownames
colnames(test_mx) = tmp_colnames
test_mx
#               0           1            2          3
# a1 -0.079811371  0.82820704 -0.193860367 -1.1269632
# b1 -0.009402418 -1.19348155 -0.004519269  0.8921427
# c1 -0.784163111 -0.01340952  0.966208235  0.0135557

因为“reshape”已经定义了一个自定义的as.matrix方法,所以你实际上并不需要这样做!

as.matrix(test_mx_cast)
#               0           1            2          3
# a1 -0.079811371  0.82820704 -0.193860367 -1.1269632
# b1 -0.009402418 -1.19348155 -0.004519269  0.8921427
# c1 -0.784163111 -0.01340952  0.966208235  0.0135557

但这仍然不能完全回答所有问题。为了进一步了解,现在比较两个矩阵:

> test_mx_cast_matrix <- as.matrix(test_mx_cast)
> class(test_mx)
[1] "cast_matrix" "matrix"     
> class(test_mx_cast_matrix)
[1] "cast_matrix" "matrix"     
> str(test_mx)
 num [1:3, 1:4] -0.0798 -0.0094 -0.7842 0.8282 -1.1935 ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:3] "a1" "b1" "c1"
  ..$ : chr [1:4] "0" "1" "2" "3"
> str(test_mx_cast_matrix)
 num [1:3, 1:4] -0.0798 -0.0094 -0.7842 0.8282 -1.1935 ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:3] "a1" "b1" "c1"
  ..$ : chr [1:4] "0" "1" "2" "3"
 - attr(*, "idvars")= chr "variable"
 - attr(*, "rdimnames")=List of 2
  ..$ :'data.frame':    3 obs. of  1 variable:
  .. ..$ variable: Factor w/ 3 levels "a1","b1","c1": 1 2 3
  ..$ :'data.frame':    4 obs. of  1 variable:
  .. ..$ t: int [1:4] 0 1 2 3

嗯。当我们直接使用as.matrix时,“reshape”包添加的所有attributes都会被保留,但是当我们手动执行此过程时,它仍然声称是class相同,但是所有自定义attributes都已被删除。

那又怎样?

好吧,由于R认为test_mxcast_matrix,当您致电as.data.frame时,它实际上会调用as.data.frame.cast_matrix,而不是as.data.frame.matrix

查看as.data.frame.cast_matrix的定义方式,attributes 必要 重新创建data.frame,从而导致错误。以下是该功能的内容:

> as.data.frame.cast_matrix
function (x, row.names, optional, ...) 
{
    unx <- unclass(x)
    colnames(unx) <- rownames(rcolnames(x))
    r.df <- data.frame(rrownames(x), unx, check.names = FALSE)
    class(r.df) <- c("cast_df", "data.frame")
    attr(r.df, "idvars") <- attr(x, "idvars")
    attr(r.df, "rdimnames") <- attr(x, "rdimnames")
    rownames(r.df) <- 1:nrow(r.df)
    r.df
}
<environment: namespace:reshape>

所以,你现在有三个选择:

  1. 升级到“reshape2” - 很好的建议,但请记住,仍然有很多人没有打扰转换。

  2. 正确使用“重塑”,这需要在其创建的对象的strclassattributes处查看更多信息。在这里“正确”使用它本来就是使用as.data.frame(test_mx_cast_matrix)

  3. 指定您要使用的method(当您不知道包是否正在重新定义方法时这是非常安全的 - 通常,当他们创建新类时,您还应该检查是否已经创建了新方法)。比较:

    > as.data.frame(test_mx)        ## Calls `as.data.frame.cast_matrix` ERROR!
    Error in data.frame(rrownames(x), unx, check.names = FALSE) : 
      arguments imply differing number of rows: 0, 3
    > as.data.frame.matrix(test_mx) ## Specifies the `as.data.frame` method. WORKS!
                  0           1            2          3
    a1 -0.079811371  0.82820704 -0.193860367 -1.1269632
    b1 -0.009402418 -1.19348155 -0.004519269  0.8921427
    c1 -0.784163111 -0.01340952  0.966208235  0.0135557
    
  4. 叹息。结束......

答案 1 :(得分:5)

您应该使用reshape2,而不是reshape,因为后者已过时。

castdcast也改变acast

as.data.frame(test_mx)
            0           1            2           3
1 -0.08120468  0.97593052 -0.006127179 -1.15107784
2 -0.04165681 -1.02810193  0.004637454  0.99042403
3 -0.87862063  0.07346341  1.019113669 -0.01769976