如何从数据框创建矩阵?

3

我有一个数据框如下,我想创建一个矩阵,在这个矩阵中,根据3个招募网站(site)和5个招募年份(year),显示平均睡眠时长(SLP)。

SLP site year 
8.6  1   2008  
7.2  1   2005  
6.4  2   2006  
9.5  3   2007  
6.1  2   2009  
3.6  1   2005 
8.6  1   2008  
7.2  1   2005  
6.4  2   2006  
9.5  3   2007  
6.1  2   2009  
5.1  3   2008 
2.1  2   2006  

我的期望输出是:

       1      2      3 
2005  6.00    -      -
2006   -     4.97    -
2007   -      -     9.5
2008  8.60    -     5.1
2009   -     6.10    -

列名是站点的变量,行名是年份的变量,每个单元格中的值是SLP的平均值。我该怎么做?

4个回答

4
我们可以使用 acast
library(reshape2)
acast(df1, year~site, value.var="SLP", mean)

或者使用基础R中的 tapply
with(df1, tapply(SLP, list(year, site), FUN = mean))

4
以下是几种不使用包的解决方案: 1) tapply 这种方法不需要使用任何包。 它生成一个带有空单元格NA值的 "matrix" 输出:
tapply(DF$SLP, DF[c("year", "site")], mean)

提供:

      site
year     1        2   3
  2005 6.0       NA  NA
  2006  NA 4.966667  NA
  2007  NA       NA 9.5
  2008 8.6       NA 5.1
  2009  NA 6.100000  NA

2) aggregate/xtabs 使用 aggregate + xtabs。这将创建一个类为 c("xtabs", "table") 的对象,并对空单元格设置为零值:

fo <- SLP ~ year + site
xtabs(fo, aggregate(fo, DF, mean))

给予;

      site
year          1        2        3
  2005 6.000000 0.000000 0.000000
  2006 0.000000 4.966667 0.000000
  2007 0.000000 0.000000 9.500000
  2008 8.600000 0.000000 5.100000
  2009 0.000000 6.100000 0.000000

3) 聚合/重塑 这也使用了aggregate,但是使用了reshape而不是xtabs。它生成一个带有空单元格NA的数据框r。最后一行使列名与之前的解决方案保持一致,如果这不重要,则可以省略。

 ag <- aggregate(SLP ~ site + year, DF, mean)
 r <- reshape(ag, dir = "wide", idvar = "year", timevar = "site")
 names(r) <- sub(".*[.]", "", names(r))

提供:

> r
  year   1        2   3
1 2005 6.0       NA  NA
3 2006  NA 4.966667  NA
5 2007  NA       NA 9.5
2 2008 8.6       NA 5.1
4 2009  NA 6.100000  NA

注意:所使用的可重现形式中的输入DF为:

DF <- structure(list(SLP = c(8.6, 7.2, 6.4, 9.5, 6.1, 3.6, 8.6, 7.2, 
6.4, 9.5, 6.1, 5.1, 2.1), site = c(1L, 1L, 2L, 3L, 2L, 1L, 1L, 
1L, 2L, 3L, 2L, 3L, 2L), year = c(2008L, 2005L, 2006L, 2007L, 
2009L, 2005L, 2008L, 2005L, 2006L, 2007L, 2009L, 2008L, 2006L
)), .Names = c("SLP", "site", "year"), class = "data.frame", row.names = c(NA, 
-13L))

2

另一种解决方案

library(tidyr)
library(dplyr)

df%>% 
  group_by(year, site) %>%
    summarise(m=mean(SLP)) %>%
  spread(site, m )%>%
as.matrix()

你不需要在命令的第一个参数中包含任何“.”(例如,df %>% group_by(year, site) 将像你的前两行一样正常工作)。Tidyverse 动词自动将数据框作为第一个参数,并使用管道传递给它们的任何内容,除非你另有说明。 - Rose Hartman

0

在@g-grothendieck使用xtabs的基础上,我们可以将其与tableifelse结合起来,以返回相同的结果。

# get a count of the number of observations per matrix cell (filling 0s with 1)
tempTab <- ifelse(with(df, table(year, + site)) == 0, 1, with(df, table(year, + site)))

tempTab

year   1 2 3
  2005 3 1 1
  2006 1 3 1
  2007 1 1 2
  2008 2 1 1
  2009 1 2 1

现在使用xtabs,当多个观测值在一个单元格中时返回值的总和,并除以tempTab得到平均值。
xtabs(SLP ~ year + site, df) / tempTab
      site
year          1        2        3
  2005 6.000000 0.000000 0.000000
  2006 0.000000 4.966667 0.000000
  2007 0.000000 0.000000 9.500000
  2008 8.600000 0.000000 5.100000
  2009 0.000000 6.100000 0.000000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接