【问题标题】:How to create the matrix from data frame?如何从数据框中创建矩阵?
【发布时间】:2016-12-21 15:40:56
【问题描述】:

我有一个如下的数据框,我想创建一个矩阵,其中根据 3 个招聘站点(站点)和 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 的平均值。我该怎么做?

【问题讨论】:

    标签: r matrix dataframe


    【解决方案1】:

    我们可以使用acast

    library(reshape2)
    acast(df1, year~site, value.var="SLP", mean)
    

    或者使用来自base Rtapply

    with(df1, tapply(SLP, list(year, site), FUN = mean))
    

    【讨论】:

      【解决方案2】:

      以下是一些不使用包的不同解决方案:

      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) 聚合/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。它给出了一个数据框r,其中空单元格的NA。最后一行使列名与之前的解决方案保持一致,如果这不重要,可以省略。

       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))
      

      【讨论】:

        【解决方案3】:

        另一种解决方案

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

        【讨论】:

        • 你不需要任何“.”作为命令中的第一个参数包含在内(例如,df %&gt;% group_by(year, site) 将与您的前两行一样工作)。 Tidyverse 动词会自动将数据框作为第一个参数,并且除非您另外指定,否则将使用通过管道传输给它们的任何内容。
        【解决方案4】:

        在@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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-30
          • 1970-01-01
          • 2018-02-11
          • 2014-11-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多