【问题标题】:Aggregating combination sequences聚合组合序列
【发布时间】:2017-09-22 17:54:21
【问题描述】:

我有想要通过user_id 聚合的示例数据集。每条记录代表一个注册。

> test
   user_id                time    plan
1        1 2017-06-23 20:00:00 monthly
2        2 2017-07-20 20:00:00 monthly
3        3 2017-06-03 20:00:00 monthly
4        1 2017-07-03 20:00:00 monthly
5        2 2017-05-11 20:00:00  yearly
6        3 2017-07-27 20:00:00  yearly
7        1 2017-05-09 20:00:00  yearly
8        2 2017-01-15 19:00:00  yearly
9        3 2017-08-18 20:00:00  yearly
10       1 2017-01-30 19:00:00 monthly

每个用户都以不同的顺序注册了不同的计划 (time)。 比如用户1的序列是monthly-yearly-monthly- monthly,那么用户1切换了两次次。

用户 2 拥有yearly-yearly-monthly,因此用户 2 已切换一次

用户 3 已从 monthly-yearly-yearly 离开,因此用户 3 已切换一次

> test[order(test$time),] 
   user_id                time    plan
8        2 2017-01-15 19:00:00  yearly
10       1 2017-01-30 19:00:00 monthly
7        1 2017-05-09 20:00:00  yearly
5        2 2017-05-11 20:00:00  yearly
3        3 2017-06-03 20:00:00 monthly
1        1 2017-06-23 20:00:00 monthly
4        1 2017-07-03 20:00:00 monthly
2        2 2017-07-20 20:00:00 monthly
6        3 2017-07-27 20:00:00  yearly
9        3 2017-08-18 20:00:00  yearly

我的目标是总结开关的组合,换句话说,总结有多少用户从yearlymonthly,有多少用户从monthlyyearly,有多少用户多次切换计划。以下数据集的输出可能如下所示:

> output
            type count
1 monthly-yearly     1
2 yearly-monthly     1
3       multiple     1

如何按user_id 进行分组,然后将R 中的字符串序列减少为multiplemonthly-yearlyyearly-monthly?任何建议或意见将不胜感激。

上面的数据集:

> dput(test)
structure(list(user_id = c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1), time = structure(c(1498262400, 
1500595200, 1496534400, 1499126400, 1494547200, 1501200000, 1494374400, 
1484524800, 1503100800, 1485820800), class = c("POSIXct", "POSIXt"
)), plan = c("monthly", "monthly", "monthly", "monthly", "yearly", 
"yearly", "yearly", "yearly", "yearly", "monthly")), .Names = c("user_id", 
"time", "plan"), row.names = c(NA, -10L), class = "data.frame")

【问题讨论】:

    标签: r dplyr data.table sequence


    【解决方案1】:

    这是另一种方式:

    test[order(user_id, time), 
      .(plan = first(plan))
    , by=.(user_id, rleid(user_id, plan))][, 
      if (.N < 3L) paste(plan, collapse="-") 
      else "multiple"
    , by=user_id][, 
      .N
    , by=.(pattern = V1)]
    
    #           pattern N
    # 1:       multiple 1
    # 2: yearly-monthly 1
    # 3: monthly-yearly 1
    

    翻译为 dplyr,基于@AndrewGustar 的回答:

    library(dplyr)
    
    test %>% 
        group_by(user_id) %>%
        arrange(time) %>% 
        summarise(pattern = 
          if (length(r <- rle(plan)$values) < 3) paste(r, collapse="-") 
          else "multiple"
        ) %>% 
        count(pattern)
    
    # # A tibble: 3 x 2
    #          pattern     n
    #            <chr> <int>
    # 1 monthly-yearly     1
    # 2       multiple     1
    # 3 yearly-monthly     1
    

    它是如何工作的

    要分解它的工作原理,请尝试部分运行它,直到每个]%&gt;% 之前的括号。

    它...

    1. 使用rleid 对每个plan 值的运行进行分组;
    2. 按运行序列总结每个用户,为 3+ 的任何序列写“多个”;
    3. 并根据这些摘要对用户进行计数。

    它不使用plan 的特定值。

    【讨论】:

      【解决方案2】:

      这是使用dplyr 和有用的rle 函数(运行长度编码)的一种方法..

      library(dplyr)
      
      output <- test %>% group_by(user_id) %>% #group by id
            arrange(time) %>%                  #sort by date
            summarise(first=first(plan),switches=length(rle(plan)$values)) %>% 
                                               #find first plan and number of switches
            mutate(type=ifelse(switches>2,"multiple",
                           ifelse(first=="monthly","monthly-yearly","yearly-monthly"))) %>% 
                                               #convert these to your three types
            count(type)                        #short for group_by and n()
      
      output
                  type     n
                 <chr> <int>
      1 monthly-yearly     1
      2       multiple     1
      3 yearly-monthly     1
      

      【讨论】:

      • 谢谢,但是“找到第一个计划”是什么意思?第一个计划是什么意思?
      • 该客户的第一个是每月还是每年。这样,如果 rle=2,我们就可以判断开关的方向。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-28
      • 2013-02-03
      • 2014-05-29
      • 2018-06-29
      • 1970-01-01
      • 2023-01-10
      • 1970-01-01
      相关资源
      最近更新 更多