【问题标题】:Mutate a dynamic subset of variable改变变量的动态子集
【发布时间】:2022-01-15 14:48:37
【问题描述】:
a = tibble(x = runif(1000,0,10),
           t = rpois(1000,4)
) %>% arrange(t)

我想要一个 l 列,它对与 t < t(x) 关联的值的 x 的子集进行平均。

预期结果:

对于x[t=0]l = NaN

对于x[t=1]l = mean(x[t<1])

对于x[t=2]l = mean(x[t<2])

等等

一个不起作用的代码:

a %>%
  mutate(
  l = mean(x[a$t < .$t])
  ) -> a

现在这可以工作了:

for (i in c(1:1000)) {
  a$l[i] = mean(a$x[a$t < a$t[i]])
}

但不是mutate。我想要一个mutate,以便我可以将它应用到群组等。

为了更好地理解这个问题:假设您必须在某个日期之前对所有 x 进行平均。现在:这个,动态的,在一个变异中。

我认为purrr 可能是必要的,但我讨厌它。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以将mapmutate 一起使用:

    library(tidyverse)
    
    f <- function(lim) mean(a$x[a$t < lim])
    
    a %>% mutate(l = map_dbl(t, f))
    

    针对 OP 解决方案进行测试:

    res <- a %>% mutate(l = map_dbl(t, f))
           
    l <- vector(mode = "numeric", length = 1000)     
    for (i in c(1:1000)) l[i] = mean(a$x[a$t < a$t[i]])
    
    assertthat::are_equal(res$l, l) # TRUE
    

    【讨论】:

    • 我正在让这个 Mutate(map) 在一个有 150 万行和 60 万组的分组 tibble 上运行。 8小时后它仍在运行。这是正常的吗?我认为一个问题是在我的 tibble 中,t 向量是由日期组成的。
    • 这并不让我感到惊讶,map 只是 apply,而这只是一个循环。当 R 必须在内存中保留这么多操作时,它的速度真的会变慢,甚至到了它可能完全崩溃的地步。您可以使用multidplyr 研究多处理。
    • 您可以尝试使用少量随机样本进行测试,更像是 10K 行而不是 1.5M 行,看看是否在合理的时间内完成。如果是这样,那么您可以更加确信是数据大小导致了问题。
    • 对于这类任务,我总是担心选择map 而不是for。显示mapfor 快,但使用for,您可以停止向量运算,然后从您停止的位置开始。从某种意义上说,使用“for”,您总是可以通过打印索引来了解剩余时间... 12 小时并且仍在运行...
    • 结束了。虽然map 本身可以正常工作,但它不考虑groups。虽然这不在明确的问题中,但现在我很想知道要创建一个 map 以将小标题识别为 grouped
    【解决方案2】:

    对于每个t 值,您可以计算x 的平均值,然后计算累积平均值的滞后值。

    library(dplyr)
    
    a %>%
      group_by(t) %>%
      summarise(l = mean(x)) %>%
      mutate(l = lag(cummean(l)))
    
    #       t     l
    #   <int> <dbl>
    # 1     0 NA   
    # 2     1  5.33
    # 3     2  5.45
    # 4     3  5.36
    # 5     4  5.26
    # 6     5  5.16
    # 7     6  5.10
    # 8     7  5.07
    # 9     8  5.12
    #10     9  4.96
    #11    10  4.98
    #12    11  5.15
    #13    12  4.93
    

    如果您想保持数据框中的行数,请将%&gt;% left_join(a, by = 't') 添加到上述答案中。

    数据

    set.seed(123)
    a = tibble(x = runif(1000,0,10),
               t = rpois(1000,4)
    ) %>% arrange(t)
    

    【讨论】:

    • 我认为您的代码在数学上是不正确的,因为它不考虑组的 n,也不考虑转移(1 与 t=0 中的平均值相关联)。即使进行了调整,它也有点笨拙。相比之下,它在 for 循环中的平滑度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多