【问题标题】:average in previous group at the same place with another column上一组的平均值与另一列在同一位置
【发布时间】:2020-08-14 10:36:16
【问题描述】:

我有一些数据,我将 mdo 值除以前一组中 mdo 实例的计数。

我也在计算 sog avg。

但我想计算与结果 (mdo/count) 值相同的实例发生的 sog avg。

library(dplyr)
library(lubridate)
library(purrr)

df <- tibble(mydate = as.Date(c("2019-05-11 23:01:00", "2019-05-11 23:02:00", "2019-05-11 23:03:00", "2019-05-11 23:04:00",
                                "2019-05-12 23:05:00", "2019-05-12 23:06:00", "2019-05-12 23:07:00", "2019-05-12 23:08:00",
                                "2019-05-13 23:09:00", "2019-05-13 23:10:00", "2019-05-13 23:11:00", "2019-05-13 23:12:00",
                                "2019-05-14 23:13:00", "2019-05-14 23:14:00", "2019-05-14 23:15:00", "2019-05-14 23:16:00",
                                "2019-05-15 23:17:00", "2019-05-15 23:18:00", "2019-05-15 23:19:00", "2019-05-15 23:20:00",
                                "2019-05-15 23:21:00", "2019-05-15 23:22:00", "2019-05-15 23:23:00", "2019-05-15 23:24:00",
                                "2019-05-15 23:25:00")),
             mdo = c(1500, 1500, 1500, 1500,
                     1500, 1500, NA, 0,
                     0, 0, 900, 900, NA, NA, 1100, 1100,
                     1100, 200, 200, 200,200,
                     1100, 1100, 1100, 0
             ),
             sog = c(12, 12, 12, 11, 10,9,
                     2,8.8, 8.7, 7.8, 11, 11, 12, 11,
                     9.54, 9.8, 10.4,4, 4, 4.5, 3.6,
                     7, 8, 9, 0))

df1 <- df %>%
    mutate(grp = data.table::rleid(mdo))

df1 <- df1 %>%
    #Keep only non-NA value
    filter(!is.na(mdo)) %>%
    #count occurence of each grp
    count(grp, name = 'count') %>%
    #Shift the count to the previous group
    mutate(count = lag(count)) %>%
    #Join with the original data
    right_join(df1, by = 'grp') %>%
    arrange(grp)

group_mdo <- df1 %>%
    select(grp, mdo) %>%
    unique() %>%
    mutate(prev_mdo = lag(mdo, na.rm=TRUE)) %>%
    select(-mdo) %>%
    tidyr::fill(prev_mdo, .direction = "down")


df1 <- df1 %>%
    left_join(group_mdo, by = "grp") %>%
    mutate(result = ifelse(prev_mdo != 0, mdo / count, 0)) %>%
    mutate(sog_avg = ifelse(prev_mdo != 0, map_dbl(.x = grp - 1, ~ mean(sog[grp == .x], na.rm=TRUE), na.rm=TRUE), NA)) 

现在的结果是:

grp count    mydate       mdo   sog prev_mdo result sog_avg
 1    NA    2019-05-11   1500    12    NA     NA     NA  
 1    NA    2019-05-11   1500    12    NA     NA     NA  
 1    NA    2019-05-11   1500    12    NA     NA     NA  
 1    NA    2019-05-11   1500    11    NA     NA     NA  
 1    NA    2019-05-12   1500    10    NA     NA     NA  
 1    NA    2019-05-12   1500     9    NA     NA     NA  
 2    NA    2019-05-12     NA     2    1500   NA     11  
 3     6    2019-05-12     0     8.8   1500   0      2  
 3     6    2019-05-13     0     8.7   1500   0      2  
 3     6    2019-05-13     0     7.8   1500   0      2  
 4     3    2019-05-13   900     11    0      0      NA  
 4     3    2019-05-13   900     11    0      0      NA  
 5    NA    2019-05-14     NA    12    900    NA     11  
 5    NA    2019-05-14     NA    11    900    NA     11  
 6     2    2019-05-14   1100    9.54  900   550    11.5
 6     2    2019-05-14   1100    9.8   900   550    11.5
 6     2    2019-05-15   1100    10.4  900   550    11.5
 7     3    2019-05-15   200     4      1100  66.7   9.91
 7     3    2019-05-15   200     4     1100   66.7   9.91
 7     3    2019-05-15   200     4.5   1100   66.7   9.91
 7     3    2019-05-15   200     3.6   1100   66.7   9.91
 8     4    2019-05-15   1100    7     200    275    4.03
 8     4    2019-05-15   1100    8     200    275    4.03
 8     4    2019-05-15   1100    9     200    275    4.03
 9     3    2019-05-15     0     0     1100     0      8   

我想要的结果:

  grp count    mydate       mdo   sog prev_mdo result sog_avg
     1    NA    2019-05-11   1500    12    NA     NA     NA  
     1    NA    2019-05-11   1500    12    NA     NA     NA  
     1    NA    2019-05-11   1500    12    NA     NA     NA  
     1    NA    2019-05-11   1500    11    NA     NA     NA  
     1    NA    2019-05-12   1500    10    NA     NA     NA  
     1    NA    2019-05-12   1500     9    NA     NA     NA  
     2    NA    2019-05-12     NA     2    1500   NA     NA  
     3     6    2019-05-12     0     8.8   1500   0      0  
     3     6    2019-05-13     0     8.7   1500   0      0  
     3     6    2019-05-13     0     7.8   1500   0      0  
     4     3    2019-05-13   900     11    0      0      0  
     4     3    2019-05-13   900     11    0      0      0  
     5    NA    2019-05-14     NA    12    900    NA     NA  
     5    NA    2019-05-14     NA    11    900    NA     NA  
     6     2    2019-05-14   1100    9.54  900   550    11
     6     2    2019-05-14   1100    9.8   900   550    11
     6     2    2019-05-15   1100    10.4  900   550    11
     7     3    2019-05-15   200     4     1100  66.7   9.91
     7     3    2019-05-15   200     4     1100   66.7   9.91
     7     3    2019-05-15   200     4.5   1100   66.7   9.91
     7     3    2019-05-15   200     3.6   1100   66.7   9.91
     8     4    2019-05-15   1100    7     200    275    4.03
     8     4    2019-05-15   1100    8     200    275    4.03
     8     4    2019-05-15   1100    9     200    275    4.03
     9     3    2019-05-15     0     0     1100     0      0   

result 为 0 时,sog_avg 应为 0,result 为 na 时,sog avg 应为 na。

如果使用之前的组数计算结果,则应该使用之前的值计算 sog avg。

所以,例如:

mdo = 1100,结果为 550,因为前一个非空组中的计数为 2(mdo 值 900)。

1100 / 2 = 550 。此时 sog avg 应为 (11 + 11) / 2 = 11,因为在前一个非空组中计数为 2。

【问题讨论】:

  • 您需要df1 %&gt;% mutate(sog_avg = ifelse(is.na(result) | result == 0, result, sog_avg)) 吗?
  • @RonakShah:嗨,不,我不想要这个。我想按照我所说的正确计算 sog_avg 然后好的,如果结果是 nan 或 zero ,是的
  • lag(mdo, na.rm=TRUE)的时候想做什么? dplyr::lag 没有名为 na.rm = 的参数
  • @Edo:是的,你是对的,不过你可以忽略它。
  • 为什么计数 NAgrp == 5 ?我认为这没有意义。应该是 2。

标签: r dplyr


【解决方案1】:

这是 方法。它广泛使用通过使用基础tabletapply 进行分组的想法,然后滞后这些结果。请注意,如果 mdo 在整个组中不是恒定的,则此答案将失败。

library(data.table)

dt = as.data.table(df)

dt[, grp := rleid(mdo)]

dt[!is.na(mdo), 
   count := {
      cnt = table(grp)
      rep(shift(cnt), cnt)
      }
   ]

setcolorder(dt, c("grp", "count", "mydate", "mdo", "sog"))

dt[,
   prev_mdo := {
     ord = table(grp)
     nafill(rep(shift(mdo[cumsum(ord)]), ord), "locf")
     }
   ]


dt[, result := fifelse(prev_mdo != 0L, mdo / count, 0)]

dt[!is.na(result),
   sog_avg := {
     mn = tapply(sog, grp, mean)
     rep(shift(mn), table(grp))
   }]

dt[result == 0 | is.na(result), sog_avg := result]
dt
#>     grp count     mydate  mdo   sog prev_mdo    result   sog_avg
#>  1:   1    NA 2019-05-11 1500 12.00       NA        NA        NA
#>  2:   1    NA 2019-05-11 1500 12.00       NA        NA        NA
#>  3:   1    NA 2019-05-11 1500 12.00       NA        NA        NA
#>  4:   1    NA 2019-05-11 1500 11.00       NA        NA        NA
#>  5:   1    NA 2019-05-12 1500 10.00       NA        NA        NA
#>  6:   1    NA 2019-05-12 1500  9.00       NA        NA        NA
#>  7:   2    NA 2019-05-12   NA  2.00     1500        NA        NA
#>  8:   3     6 2019-05-12    0  8.80     1500   0.00000  0.000000
#>  9:   3     6 2019-05-13    0  8.70     1500   0.00000  0.000000
#> 10:   3     6 2019-05-13    0  7.80     1500   0.00000  0.000000
#> 11:   4     3 2019-05-13  900 11.00        0   0.00000  0.000000
#> 12:   4     3 2019-05-13  900 11.00        0   0.00000  0.000000
#> 13:   5    NA 2019-05-14   NA 12.00      900        NA        NA
#> 14:   5    NA 2019-05-14   NA 11.00      900        NA        NA
#> 15:   6     2 2019-05-14 1100  9.54      900 550.00000 11.000000
#> 16:   6     2 2019-05-14 1100  9.80      900 550.00000 11.000000
#> 17:   6     2 2019-05-15 1100 10.40      900 550.00000 11.000000
#> 18:   7     3 2019-05-15  200  4.00     1100  66.66667  9.913333
#> 19:   7     3 2019-05-15  200  4.00     1100  66.66667  9.913333
#> 20:   7     3 2019-05-15  200  4.50     1100  66.66667  9.913333
#> 21:   7     3 2019-05-15  200  3.60     1100  66.66667  9.913333
#> 22:   8     4 2019-05-15 1100  7.00      200 275.00000  4.025000
#> 23:   8     4 2019-05-15 1100  8.00      200 275.00000  4.025000
#> 24:   8     4 2019-05-15 1100  9.00      200 275.00000  4.025000
#> 25:   9     3 2019-05-15    0  0.00     1100   0.00000  0.000000
#>     grp count     mydate  mdo   sog prev_mdo    result   sog_avg

【讨论】:

  • 您好,感谢您的帮助。对于第 6 组,正确的结果是 11,因为它引用了 mdo 值 900,其中两个条目的 sog 都是 11。发生这种情况是因为第 5 组具有 na mdo 值,所以在这种情况下,我们会转到前一个非 na 组(其中 mdo 不是 na)。这是第 4 组,在这两种情况下都有 mdo 900 和 sog是 11 岁。我希望对您有所帮助
  • 即使我加载 data.table 库,它仍然显示错误找不到函数 nafill 和 fifelse !
  • 你能再安装一次吗?这些是较新的功能,因此您可能使用的是旧版本的软件包
  • 我已经安装了 1.12.2 版本还是同样的问题
  • 好的,我看到它需要1.13版本,所以我从github安装并运行正常!代码似乎正确!谢谢! (upv)
猜你喜欢
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
  • 2021-08-07
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
  • 2021-08-19
  • 2021-10-31
相关资源
最近更新 更多