【问题标题】:Computing for each datafram column the mean of three subsequent row data for each row (R)为每个数据框列计算每行 (R) 的三个后续行数据的平均值
【发布时间】:2020-12-30 13:22:23
【问题描述】:

首先,我的问题的简单 R 示例:

> df
   x  y
1  1  3
2  2  7
3  4  9
4  8  0
5  3  1
6 12 24

我想为每一列计算每一行的三个后续行数据的平均值,这会产生以下数据框。

> dfRes
      xRes     yRes
         x        y
1 2.333333 6.333333
2 4.666667 5.333333
3 5.000000 3.333333
4 7.666667 8.333333
5       NA       NA
6       NA       NA

由于我有很多列和行的非常大的数据框,我想避免使用 for 循环进行此计算。我尝试定义自定义函数以使用可用的sapply 函数。

有人知道 R 中的一个简单解决方案吗?此问题的计算时间相对较快?

---- 更新---- 计算过程应该是这样的:

xRes[1] = mean(x[1] + x[2] + x[3])
xRes[2] = mean(x[2] + x[3] + x[4])
...
xRes[5] = NA # because there is no x[7]

【问题讨论】:

  • 您是如何准确计算示例数据集中的结果的?
  • 这能回答你的问题吗? Calculate the mean of every 13 rows in data frame
  • 第一个值 3.5 或第二个值 14 怎么样?
  • 例如x[1] + x[2] + x[3] = xRes[1]x[2] + x[3] + x[4] = xRes[2] 等。对于 x[5],无法计算平均值,因为我们缺少第 7 行的值。我正在更新我的问题,以便更清楚地说明这一点。
  • 一般而言,您可以通过 lag(x, i) 获取列中的先前值,其中 i 表示您回溯了多远。所以 (lag(x) + lag(x,2) + lag(x,3))/3 会给你你想要的平均值。您甚至不需要为此定义新函数。只需使用 dplyr 并在所有列中使用 mutate。

标签: r performance sapply


【解决方案1】:

您可以使用具有适当窗口大小的滚动函数。

df[] <- lapply(df, zoo::rollmean, 3, fill = NA, align = 'left')

如果您的数据量很大,使用 data.table 可能会有所帮助。

library(data.table)
setDT(df)[, lapply(.SD, frollmean, 3, align = 'left')]

【讨论】:

    【解决方案2】:

    地图功能怎么样? https://www.rdocumentation.org/packages/purrr/versions/0.2.5/topics/map 它实际上是 for-loop 的一个非常好的替代品

    【讨论】:

      【解决方案3】:

      我会将数据框转换为矩阵并将 colMeans 与 nrow 参数一起使用。 解决方案基本上是从这里的答案中复制的:https://stackoverflow.com/a/25151007/7941188

      # devtools::install_github("alistaire47/read.so")
      foo <- read.so::read.so(
      "
         x  y
      1  1  3
      2  2  7
      3  4  9
      4  8  0
      5  3  1
      6 12 24")
      
      foo_mat <- as.matrix(foo)
      
      sapply(foo, function(x) colMeans(matrix(x, nrow = 3)))
      #>             x        y
      #> [1,] 2.333333 6.333333
      #> [2,] 7.666667 8.333333
      

      这取决于长度(矩阵)是 (3) 的倍数。在我链接到的另一篇文章中,有一个解决方案显然可以处理其他情况

      【讨论】:

        【解决方案4】:

        根据this historic answer的方法使用filter

        n <- 3
        df1[] <- lapply(df1, function(x) c(na.omit(filter(x, rep(1 / n, n))), rep(NA, n - 1)))
        df1  
        #          x        y
        # 1 2.333333 6.333333
        # 2 4.666667 5.333333
        # 3 5.000000 3.333333
        # 4 7.666667 8.333333
        # 5       NA       NA
        # 6       NA       NA
        

        数据:

        df1 <- structure(list(x = c(2.33333333333333, 4.66666666666667, 5, 7.66666666666667, 
        NA, NA), y = c(6.33333333333333, 5.33333333333333, 3.33333333333333, 
        8.33333333333333, NA, NA)), row.names = c("1", "2", "3", "4", 
        "5", "6"), class = "data.frame")
        

        【讨论】:

          【解决方案5】:

          使用来自dplyrlagleadmutate

          df%>%
          mutate(x=(lag(x,0)+lead(x)+lead(x,2))/3 , y=(lag(y,0)+lead(y)+lead(y,2))/3)
          

          【讨论】:

            猜你喜欢
            • 2022-01-11
            • 2020-04-02
            • 2020-05-22
            • 2015-08-02
            • 2017-12-04
            • 1970-01-01
            • 2019-09-18
            • 1970-01-01
            • 2021-12-12
            相关资源
            最近更新 更多