【问题标题】:Including a for loop within a dplyr chain在 dplyr 链中包含一个 for 循环
【发布时间】:2023-03-16 17:36:01
【问题描述】:

我正在清理一些关于客户行为的数据,我想识别并过滤掉客户执行某个事件的时间。由于这是一个更大的数据操作项目的一个元素,理想情况下我想将它作为三行添加到更长的 dplyr 链中。

这里涉及到两个逻辑:

  1. 识别第二个事件的第一行:前一行有 end_pct 值大于 0.9,当前行有 end_pct value 值低于 0.2,并且前一行和当前行具有 相同的 customer_id
  2. 识别后续行:如果前一个 行对 second_event 以及前一行和当前行具有“是” 具有相同的 customer_id
  3. 过滤掉第二次事件

这是我用于这些操作的 dplyr 代码:

mutate(second_time = ifelse(lag(pct_completed,1) > 0.9 & pct_completed < .2 & lag(customer_id,1) == customer_id, "yes", "no")) %>%
mutate(second_time = ifelse(lag(second_time,1)=="yes"&lag(customer_id,1) == customer_id, "yes", second_time)) %>%
filter(second_time = "no")

如果我在正常的 dplyr 链中运行上面的第二个 mutate 函数,它只会将第二个事件中的第二行标记为“是”,而不是任何后续的。因此,我认为我需要编写一个 for 循环来捕获第二阶段中所有剩余的事件。

我附上了一些sample data here 来说明问题。

如果有人对如何编写可合并到 dplyr 链中的 for 循环有任何好的建议,我将不胜感激。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我提出一个更简单的解决方案。

    • 我们按客户分组(因为一切都是在客户中计算的)。
    • 我们检测到事件的变化,类似于您当前的逻辑并设置一个标志。
    • 我们对标志进行累积总和,以计算我们所处的事件。
    • 我们在累积和为 2 时进行过滤。

    .

    df %>% 
      group_by(customer_id) %>% 
      mutate(flag = row_number() > 1 &        #to avoid NA's on the first rows of each customer
               (pct_completed < 0.2) & 
               (lag(pct_completed) > 0.9),
             event_nr = cumsum(flag) + 1) %>% 
      filter(event_nr == 2)
    

    【讨论】:

    • 谢谢@Axeman。如果我想将其合并到更大的命令链中并将数据保持在事件级别,是否在 filter 命令之后添加 ungroup(customer_id)?还是最好在没有过滤器的情况下运行它并创建一个单独的数据框,然后通过 left_join 将其与主数据框合并并然后运行过滤器?
    • 从现有信息中我无法判断。
    • 不用担心,我已经检查过了,实际上我也不需要这样做。您的代码建议完美运行 - 只需注意一点, filter(event_nr == 1) 在上述情况下是正确的,即我想删除第二个及以后的事件。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    • 2011-12-07
    • 1970-01-01
    • 2021-08-05
    • 2014-11-21
    相关资源
    最近更新 更多