data.frame,其中包含R中的矩阵

时间:2011-05-26 19:01:37

标签: r dataframe

我正在尝试将一些矩阵放在R中的数据框中,例如:

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

但是当我这样做时,我会得到一个包含2行3列的数据帧,而不是1行2列的数据帧。

阅读文档,我必须使用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

据我了解,数据框对于矩阵的每一行包含一行,而mat字段是矩阵列值的列表。

因此,我如何获得包含矩阵的数据帧?

谢谢!

5 个答案:

答案 0 :(得分:5)

我发现包含矩阵的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

答案 1 :(得分:4)

更简单的方法是使用矩阵

的占位符定义数据框
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

答案 2 :(得分:2)

我在尝试理解 pls 包中的汽油数据时遇到了同样的问题。使用$作业。 首先,让我们创建一个矩阵,让我们称之为spectra_mat,然后称为response_var1。

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

现在我们将向量response_var1放在一个新的数据框中 - 让我们称之为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 ...

答案 3 :(得分:1)

您获得的结果(2行x 3列)是R的预期结果,因为它等于cbind向量(id,带有回收)和矩阵({{ 1}})。

IMO,如果您真的想要绑定不同的数据结构,最好使用mlist(当维度一致时,不允许混合使用数值和因子值)。否则,只有array矩阵到现有data.frame(如果两者具有相同的行数)才能完成工作。例如

cbind

,结果显示

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(用于数组)函数。

答案 4 :(得分:1)

包含矩阵列的数据框确实在特殊情况下使用。在这些情况下,数据集中的每个观测值都有一个带有某个变量的整个向量。我遇到过两种常见的情况:

  1. 贝叶斯分析:您为每个观察值创建一个后验预测,因此对于新数据中的每个“行”,您都有一个完整的向量(该向量的长度是MCMC迭代的次数)。
  2. 功能数据分析:每个“观察”本身就是一个功能,并且您将观察到的该功能的实现存储为向量。

如果您正在使用数据帧,则有几种显而易见的方法来处理这些数据,但效率均很低。我将以贝叶斯案例为例:

  1. “超宽”格式:除了数据框的其他列,矢量的每个元素都有一列。这使得数据帧非常宽,通常很难使用。这也使得仅引用与后验相对应的列变得困难。
  2. “超长”(整洁)格式:占用大量内存,因为在后验的每次迭代中都不必要重复数据帧的所有其他列。
  3. 列表列:您可以创建一个列表,其中每个元素是与数据帧该行的后验相对应的向量。这里的问题是,您要执行的大多数操作都将要求您将后验项重新列出到矩阵中,并且列出/取消列出是不必要的计算。

带有矩阵列的数据框对于这种情况非常有用。后验方保持在矩阵中,该矩阵具有与数据帧相同的行数。但是该矩阵仅在数据帧中被识别为单个“列”,并且使用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