【问题标题】:How do I reduce the dimensions of my data frame in terms of columns by averaging between columns?如何通过列之间的平均来减少我的数据框的列维度?
【发布时间】:2019-05-17 10:12:35
【问题描述】:

我有一个数据框df1,它总结了每 2 米到 39 米深度的水温随时间的变化。举个例子:

df1<-data.frame(Datetime=c("2016-08-18 00:00:00","2016-08-18 00:01:00","2016-08-18 00:02:00","2016-08-18 00:03:00"),
                Site=c("BD","HG","BD","HG"),
                m0=c(2,5,6,1),
                m2=c(3,5,2,4),
                m4=c(4,1,9,3),
                m6=c(2,5,6,1),
                m8=c(3,5,2,4),
                m10=c(2,5,6,1),
                m12=c(4,1,9,3),
                m14=c(3,5,2,4),
                m16=c(2,5,6,1),
                m18=c(4,1,9,3),
                m20=c(3,5,2,4),
                m22=c(2,5,6,1),
                m24=c(4,1,9,3),
                m26=c(3,5,2,4),
                m28=c(2,5,6,1),
                m30=c(4,1,9,3),
                m32=c(3,5,2,4),
                m34=c(2,5,6,1),
                m36=c(4,1,9,3),
                m38=c(3,5,2,4)
                )

> df1
             Datetime Site m0 m2 m4 m6 m8 m10 m12 m14 m16 m18 m20 m22 m24 m26 m28 m30 m32 m34 m36 m38
1 2016-08-18 00:00:00   BD  2  3  4  2  3   2   4   3   2   4   3   2   4   3   2   4   3   2   4   3
2 2016-08-18 00:01:00   HG  5  5  1  5  5   5   1   5   5   1   5   5   1   5   5   1   5   5   1   5
3 2016-08-18 00:02:00   BD  6  2  9  6  2   6   9   2   6   9   2   6   9   2   6   9   2   6   9   2
4 2016-08-18 00:03:00   HG  1  4  3  1  4   1   3   4   1   3   4   1   3   4   1   3   4   1   3   4

我想通过平均适当列之间的水温来计算 8 米而不是 2 米的层的水温。例如,我想将列 m0m2m4m6 转换为一个名为 m3.5 的唯一列,它反映了 0 到 7 米深度之间的平均水温。

如我所愿:

> df1
             Datetime Site m3.5 m11.5 m19.5 m27.5 m35.5
1 2016-08-18 00:00:00   BD 2.75  3.00  2.75  3.25  3.00
2 2016-08-18 00:01:00   HG 4.00  4.00  4.00  3.00  4.00
3 2016-08-18 00:02:00   BD 5.75  4.75  5.75  6.50  4.75
4 2016-08-18 00:03:00   HG 2.25  3.00  2.25  2.75  3.00

有没有人可以用 dplyr 做到这一点?

【问题讨论】:

  • 简单的方法是:df1 %&gt;% rowwise() %&gt;% dplyr::transmute(Datetime= Datetime, Site= Site, m3.5 = mean(c(m0,m2, m4, m6))) .. etc ...但是您是否在寻找更通用的东西?
  • 你想要行的意思还是列的意思?请阅读用户@yarnabrina 对我的回答的评论。

标签: r dplyr


【解决方案1】:

这是一个适用于任意数量列的解决方案

num_meters <- 39
grp <- as.factor(cumsum(seq(0,num_meters, 2) %% 8 == 0))

df <- data.frame(df1[,c(1,2)], 
             t(apply(df1[,-c(1,2)], 1, function(x) tapply(x, grp, mean))))

#            Datetime Site   X1   X2   X3   X4   X5
#1 2016-08-18 00:00:00   BD 2.75 3.00 2.75 3.25 3.00
#2 2016-08-18 00:01:00   HG 4.00 4.00 4.00 3.00 4.00
#3 2016-08-18 00:02:00   BD 5.75 4.75 5.75 6.50 4.75
#4 2016-08-18 00:03:00   HG 2.25 3.00 2.25 2.75 3.00

# in case you also need the colnames that you have specified
colnames(df)[-c(1,2)] <- paste("m", tapply(seq(0,num_meters, 2), grp, mean) + 0.5, sep = "")

【讨论】:

    【解决方案2】:

    使用tidyverse,您也可以这样做:

    df1 %>% 
      gather(var, val, -Datetime, -Site) %>% 
      mutate(group = rep(seq(3.5, 35.5, 8), each = 16)) %>% 
      group_by(group, Site, Datetime) %>% 
      summarise(value = mean(val)) %>% 
      spread(group, value)
    
      Site  Datetime            `3.5` `11.5` `19.5` `27.5` `35.5`
      <fct> <fct>               <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
    1 BD    2016-08-18 00:00:00  2.75   3      2.75   3.25   3   
    2 BD    2016-08-18 00:02:00  5.75   4.75   5.75   6.5    4.75
    3 HG    2016-08-18 00:01:00  4      4      4      3      4   
    4 HG    2016-08-18 00:03:00  2.25   3      2.25   2.75   3  
    

    【讨论】:

      【解决方案3】:

      您可能正在寻找rowMeans

      df1$m3.5 <- rowMeans(df1[, c("m0", "m2", "m4", "m6")])
      

      不需要 dplyr。

      【讨论】:

        【解决方案4】:

        以下是这样做的。

        library(dplyr)
        
        df1 %>%
          mutate(m3.5 = rowMeans(.[3:6]),
                 m11.5 = rowMeans(.[7:10]),
                 m19.5 = rowMeans(.[11:14]),
                 m27.5 = rowMeans(.[15:18]),
                 m35.5 = rowMeans(.[19:22])) %>%
          select(Datetime, Site, m3.5:m35.5)
        #             Datetime Site m3.5 m11.5 m19.5 m27.5 m35.5
        #1 2016-08-18 00:00:00   BD 2.75  3.00  2.75  3.25  3.00
        #2 2016-08-18 00:01:00   HG 4.00  4.00  4.00  3.00  4.00
        #3 2016-08-18 00:02:00   BD 5.75  4.75  5.75  6.50  4.75
        #4 2016-08-18 00:03:00   HG 2.25  3.00  2.25  2.75  3.00
        

        【讨论】:

        • 我想应该是rowMeans
        • 我要列的意思!!我意识到您使用脚本获得的方法与我的预期不符......
        • @Dekike rowMeans 获取您在问题中发布的内容。我可以编辑答案。
        • 这是真的!!我刚刚检查过了。我需要rowMeans 而不是colMeans。谢谢!
        猜你喜欢
        • 1970-01-01
        • 2018-01-17
        • 2016-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-11
        • 2018-12-23
        相关资源
        最近更新 更多