Dataframe ,其中列包含R中的矩阵

0s0u357o  于 2023-04-09  发布在  其他
关注(0)|答案(6)|浏览(108)

我试着把一些矩阵放在R中的dataframe中,比如:

m <- matrix(c(1,2,3,4), nrow=2, ncol=2)
df <- data.frame(id=1, mat=m)

但是当我这样做的时候,我得到了一个2行3列的 Dataframe ,而不是一个1行2列的 Dataframe 。
阅读文档时,我必须使用I()对矩阵进行转义。

df <- data.frame(id=1, mat=I(m))

str(df)
'data.frame':   2 obs. of  2 variables:
 $ id : num  1 1
 $ mat: AsIs [1:2, 1:2] 1 2 3 4

据我所知,dataframe包含矩阵的每一行的一行,而mat字段是矩阵列值的列表。
因此,我如何获得一个包含矩阵的 Dataframe ?
谢谢!

kq0g1dla

kq0g1dla1#

我觉得data.frames包含矩阵的方式很奇怪,但是:我所知道实现这一点的唯一方法隐藏在stats:::simulate.lm
试试这个,戳进去看看发生了什么:

d <- data.frame(y=1:5,n=5)
g0 <- glm(cbind(y,n-y)~1,data=d,family=binomial)
debug(stats:::simulate.lm)
s <- simulate(g0,n=5)

这是一个奇怪的后门解决方案。创建一个列表,将其类更改为data.frame,然后(这是必需的)手动设置namesrow.names(如果你不执行最后的步骤,数据仍然会在对象中,但它会打印出来,就好像它没有行一样...)

m1 <- matrix(1:10,ncol=2)
m2 <- matrix(5:14,ncol=2)
dd <- list(m1,m2)
class(dd) <- "data.frame"
names(dd) <- LETTERS[1:2]
row.names(dd) <- 1:5
dd
txu3uszq

txu3uszq2#

一种更简单的方法是使用矩阵的占位符定义数据框

m <- matrix(c(1, 2, 3, 4), nrow = 2, ncol = 2) 
df <- data.frame(id = 1, mat = rep(0, nrow(m)))

然后分配矩阵。不需要玩列表的类或使用*apply()函数。

df$mat <- m
13z8s7eq

13z8s7eq3#

我在试图理解 pls 包中的汽油数据时遇到了同样的问题。使用$完成这项工作。首先,让我们创建一个矩阵,我们称之为spectrum_mat,然后是一个名为response_var1的向量。

spectra_mat = matrix(1:45, 9, 5)
response_var1 = seq(1:9)

现在,我们将向量response_var1放入一个新的 Dataframe 中-我们称之为df。

df = data.frame(response_var1)
df$spectra = spectra_mat

为了检查

str(df)

'data.frame':   9 obs. of  2 variables:
 $ response_var1: int  1 2 3 4 5 6 7 8 9
 $ spectra      : int [1:9, 1:5] 1 2 3 4 5 6 7 8 9 10 ...
x7rlezfr

x7rlezfr4#

包含矩阵列的数据框在特定场景中确实有其用途。这些场景是指数据集中的每个观测都有某个变量的整个向量的情况。我遇到过两种常见情况:
1.贝叶斯分析:你为每个观测值创建一个后验预测,所以对于newdata中的每一“行”,你都有一个完整的向量(该向量的长度是MCMC迭代的次数)。
1.功能数据分析:每一个“观察”本身就是一个函数,你把观察到的函数的实现作为一个向量存储起来。
如果您正在处理数据框,有几种明显的方法可以处理这些数据,但这两种方法都效率低下。我将使用贝叶斯案例作为示例:
1.“超宽”格式:除了数据框的其他列之外,向量的每个元素都有一列。这使得数据框非常宽,通常很难处理。它也使得仅引用与后验对应的列变得困难。
1.“超长”(整洁)格式:这是非常内存密集的,因为数据框的所有其他列都必须在后验的每次迭代中重复。
1.列表列:您可以创建一个列表,其中每个元素都是与数据框该行的后验向量相对应的向量。这里的问题是,您要做的大多数操作都需要将后验列表取消为矩阵,并且列表/取消列表是不必要的计算。
带有矩阵列的数据框是这种情况的一个非常有用的解决方案。后验结果停留在与数据框具有相同行数的矩阵中。但是该矩阵仅被识别为数据框中的单个“列”,并且使用df$mat引用该列将返回矩阵。您甚至可以使用一些dplyr函数(如过滤)返回矩阵的相应行,但这有点experimental
创建矩阵列最简单的方法是两步。首先创建不带矩阵列的数据框,然后通过简单的赋值添加矩阵列。我还没有找到一个一步完成此操作的解决方案,它不涉及I(),这会更改列类型。

m <- matrix(c(1,2,3,4), nrow=2, ncol=2)
df <- data.frame(id = rep(1, nrow(m)))
df$mat <- m
names(df)
# [1] "id"  "mat"
str(df)
# 'data.frame': 2 obs. of  2 variables:
#  $ id : num  1 1
#  $ mat: num [1:2, 1:2] 1 2 3 4
hgtggwj0

hgtggwj05#

你得到的结果(2行x 3列)是R的预期结果,因为它相当于cbind一个向量(id,有循环)和一个矩阵(m)。
IMO,如果你真的想绑定不同的数据结构,最好使用listarray(当维度一致时,不允许混合数字和因子值)。否则,如果两者具有相同的行数,只需将cbind矩阵绑定到现有的data.frame即可。例如

x1 <- replicate(2, rnorm(10))
x2 <- replicate(2, rnorm(10))
x12l <- list(x1=x1, x2=x2)
x12a <- array(rbind(x1, x2), dim=c(10,2,2))

结果显示

> str(x12l)
List of 2
 $ x1: num [1:10, 1:2] -0.326 0.552 -0.675 0.214 0.311 ...
 $ x2: num [1:10, 1:2] -0.164 0.709 -0.268 -1.464 0.744 ...
> str(x12a)
 num [1:10, 1:2, 1:2] -0.326 0.552 -0.675 0.214 0.311 ...

如果您计划使用不同维度的矩阵,并且以与外部数据相同的方式(对于行)组织列表,则列表更易于使用。框架可以轻松地将其子集化。下面是一个示例:

df1 <- data.frame(grp=gl(2, 5, labels=LETTERS[1:2]), 
                  age=sample(seq(25,35), 10, rep=T))
with(df1, tapply(x12l$x1[,1], list(grp, age), mean))

您还可以使用lapply(用于列表)和apply(用于数组)函数。

cigdeys3

cigdeys36#

为了得到一个 *data.frame,其中有1行和2列 *,你必须把matrix放在list里面。

m <- matrix(1:4, 2)

x <- list2DF(list(id=1, mat=list(m)))
x
#  id        mat
#1  1 1, 2, 3, 4

str(x)
#'data.frame':   1 obs. of  2 variables:
# $ id : num 1
# $ mat:List of 1
#  ..$ : int [1:2, 1:2] 1 2 3 4

y <- data.frame(id=1, mat=I(list(m)))
y
#  id        mat
#1  1 1, 2, 3, 4

str(y)
#'data.frame':   1 obs. of  2 variables:
# $ id : num 1
# $ mat:List of 1
#  ..$ : int [1:2, 1:2] 1 2 3 4
#  ..- attr(*, "class")= chr "AsIs"

使用I()创建data.frame时,直接创建一个包含matrix* 的列的 *data.frame,其中给定的数据具有2行2列,这将是直接的。没有AsIs的替代方案可以是稍后插入它,正如其他人所示。

m <- matrix(1:4, 2)

x <- data.frame(id=1, mat=I(m))
str(x)
'data.frame':   2 obs. of  2 variables:
 $ id : num  1 1
 $ mat: 'AsIs' int [1:2, 1:2] 1 2 3 4

y <- data.frame(id=rep(1, nrow(m)))
y[["m"]] <- m
#y["m"] <- m   #Alternative
#y[,"m"] <- m  #Alternative
#y$m <- m      #Alternative
str(y)
#'data.frame':   2 obs. of  2 variables:
# $ id: num  1 1
# $ m : int [1:2, 1:2] 1 2 3 4

z <- `[<-`(data.frame(id=rep(1, nrow(m))), , "mat", m)
str(z)
#'data.frame':   2 obs. of  2 variables:
# $ id : num  1 1
# $ mat: int [1:2, 1:2] 1 2 3 4

或者,数据可以存储在list中。

m <- matrix(1:4, 2)
x <- list(id=1, mat=m)
x
#$id
#[1] 1
#
#$mat
#     [,1] [,2]
#[1,]    1    3
#[2,]    2    4

str(x)
#List of 2
# $ id : num 1
# $ mat: int [1:2, 1:2] 1 2 3 4

相关问题