R - 按键

时间:2018-01-23 13:41:57

标签: r data.table run-length-encoding

我有一个发送给用户的消息数据集,有些已成功,有些已失败:

> df.messages <- data.frame(date = c("2018-01-01 12:00","2018-01-01 12:00","2018-01-01 12:00","2018-01-02 12:00","2018-01-02 12:00","2018-01-02 12:00","2018-01-03 12:00","2018-01-03 12:00","2018-01-03 12:00","2018-01-04 12:00","2018-01-04 12:00","2018-01-04 12:00"), id = c(1,2,3,1,2,3,1,2,3,1,2,3), status = c("S","S","S","S","S","F","S","F","F","F","F","S"))
> df.messages
               date id status
1  2018-01-01 12:00  1      S
2  2018-01-01 12:00  2      S
3  2018-01-01 12:00  3      S
4  2018-01-02 12:00  1      S
5  2018-01-02 12:00  2      S
6  2018-01-02 12:00  3      F
7  2018-01-03 12:00  1      S
8  2018-01-03 12:00  2      F
9  2018-01-03 12:00  3      F
10 2018-01-04 12:00  1      F
11 2018-01-04 12:00  2      F
12 2018-01-04 12:00  3      S

以下是注意事项:

  • 每天发送一条消息,超过四天
  • id 1成功(S)三次,然后失败(F)
  • id 2成功两次,然后失败两次
  • id 3成功一次,然后失败两次,然后成功

我想将用户分成四组

  1. 那些总是成功的人
  2. 那些失败,然后成功的
  3. 那些成功的,然后失败而没有再次成功
  4. 那些总是失败的
  5. 然后明白

    • 组2中的用户在再次成功之前失败的最大次数
    • 组2中的用户在再次成功之前失败的最长时间
    • 第3组中的用户失败的最大次数
    • 第3组中的用户失败的最长时间

    理想的输出是

      id group num_f_messages date_f_messages
    1  1     3              1               1
    2  2     3              2               2
    3  3     2              2               2
    

    我知道我需要使用rle()diff(),但它变得越来越复杂,我之前不必进行此类分析。我很丢失。

    我有9MM的行,所以我试图用data.table来完成这个,但欢迎任何解决方案。

    编辑:

    我正在尝试将此功能扩展到更大的数据集。因此,在id 3的消息为“S,F,F,S,F,F,F,S”的情况下,我需要在最终S之前反映最多3个F。

2 个答案:

答案 0 :(得分:1)

你可以试试这个:

require(plyr); require(dplyr)

df.messages %>% 
  group_by(id) %>% 
  summarise(group = ifelse(sum(status == "S") == n(), 1, 
                           ifelse(sum(status == "F") == n(), 4,
                                  ifelse(n_distinct(status) > 1 & 
                                           status[1] == "S" & status[n()] == "S", 2, 3))),
            num_f_messages = sum(status == "F"),
            date_f_messages = n_distinct(date[status == "F"]))

给你:

# A tibble: 3 x 4
     id group num_f_messages date_f_messages
  <dbl> <dbl>          <int>           <int>
1     1     3              1               1
2     2     3              2               2
3     3     2              2               2

答案 1 :(得分:1)

这是一个data.table解决方案。

library(data.table)
library(magrittr)

df.messages <- data.frame(date = c("2018-01-01 12:00","2018-01-01 12:00","2018-01-01 12:00","2018-01-02 12:00","2018-01-02 12:00","2018-01-02 12:00","2018-01-03 12:00","2018-01-03 12:00","2018-01-03 12:00","2018-01-04 12:00","2018-01-04 12:00","2018-01-04 12:00"), id = c(1,2,3,1,2,3,1,2,3,1,2,3), status = c("S","S","S","S","S","F","S","F","F","F","F","S"))
df.messages$status <- as.character(df.messages$status)
setDT(df.messages)


ans <- df.messages[,
            .(
                by_rle = paste0(rle(status)$value, collapse = ""),
                num_f_message = sum(status == "F"),
                date_f_message = length(unique(date[status == "F"]))
            ), 
            by = id] %>%
    # define groups and remove the by_rle columns
    .[by_rle == "S", group := 1] %>%
    .[by_rle == c("SFS"), group := 2] %>%
    .[by_rle == c("SF"), group := 3] %>%
    .[by_rle == "F", group := 4] %>%
    .[, by_rle := NULL] %>%
    setcolorder(c("id", "group", "num_f_message", "date_f_message"))

#    id group num_f_message date_f_message
# 1:  1     3             1              1
# 2:  2     3             2              2
# 3:  3     2             2              2