根据列在每个group_ID中创建顺序subgroup_ID

时间:2017-12-11 14:41:21

标签: r indexing segments

我正在努力寻找一项需要运行超过一千万条记录的非常简单的任务的解决方案。

假设以下数据集:

mydf <- structure(list(group_ID = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 
4, 4, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 
7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 
9), element_index= c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
12L, 13L, 14L, 15L, 16L, 17L, 18L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 
8L, 9L, 1L, 2L, 3L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 1L, 2L, 3L, 4L, 
5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 1L, 2L, 3L, 4L, 5L, 6L, 
7L, 8L, 9L, 10L, 11L, 12L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 3L, 4L, 
5L, 6L, 7L, 8L), value= c(8045762L, 259L, 155L, 167L, 
110L, 175L, 135L, 0L, 0L, 0L, 0L, 150L, 0L, 0L, 115L, 0L, 0L, 
396L, 11175L, 0L, 0L, 0L, 261L, 0L, 170L, 0L, 576L, 5807L, 0L, 
280L, 48663L, 0L, 0L, 497L, 7298L, 0L, 441L, 160725L, 0L, 0L, 
0L, 0L, 335L, 0L, 0L, 0L, 0L, 0L, 0L, 356L, 35462L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 265L, 0L, 0L, 360L, 780L, 0L, 0L, 0L, 371L, 48394L, 
0L, 0L, 0L, 341L, 0L, 0L, 386L)), .Names = c("group_ID", "element_index", 
"value"), class = "data.frame", row.names = c(NA, 75L))

基本上,主要概念是:
1.每个group_ID的第一个元素元素始终subgroup_ID == 1
2.在value == 0增加subgroup_ID时,不得考虑subgroup_id的元素 3. 1 value != 0从<{>} 元素1开始,value != 0每增加一个value != 0 value == 0 (从value != 0的第二个元素的1开始;) 4. subgroup_ID = c(1,1,2,3,4,5,6,7,7,7,7,7,8,8,8,9,9,9,1,1,1,1,1,2,2,3,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,2,2,2,1,1,1,1,1,1,1,1,1,1,2,2,2) solution_df <- data.frame(mydf, subgroup_ID) 元素与subgroup_ID的第一个下一个元素相关联。 观察图片,这意味着元素2和3被分配给元素4的subgroup_ID。

解决方案如下:

subgroup_ID

此问题的目的是让group_ID将每个组划分为细分,而创建1的规则如下:
- 每个subgroup_ID的第一个元素始终为1
- 每次有value != 0

的元素时sendInfo()增加sendInfo()

Example of group_ID == 1

我希望问题很明确,请不要犹豫要求澄清。

3 个答案:

答案 0 :(得分:2)

这里我们假设任何组的规则是用0替换值的第二个非零元素,然后通过从1开始形成结果,并在每次遇到后续非零时递增1。 / p>

由于每个组中第一个值元素根据注释总是非零,我们可以通过暂时将第一个元素替换为零来找到第二个非零,然后在剩下的内容中搜索第一个非零值

没有使用任何包裹。

Seq <- function(x) {
     x[head(which(replace(x, 1, 0) != 0), 1)] <- 0
     cumsum(x != 0)
}
transform(mydf, subid = ave(value, group_ID, FUN = Seq))

给出与问题中显示的答案相同的答案:

   group_ID element_index value subid
1         1             1   123     1
2         1             2     0     1
3         1             3     0     1
4         1             4   456     1
5         1             5   214     2
6         2             1    20     1
7         2             2     0     1
8         2             3    30     1
9         3             1    10     1
10        3             2     0     1
11        3             3    10     1
12        3             4    20     2

答案 1 :(得分:2)

您还可以尝试numpy解决方案

tidyverse

答案 2 :(得分:1)

group_ID <- c(1,1,1,1,1,2,2,2,3,3,3,3)
element_index <- c(1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 3, 4)  #the element are ordered within each group_ID
value <- c(123, 0, 0, 456, 214, 20, 0, 30, 10, 0, 10, 20)
mydf <- data.frame(group_ID, element_index, value)


library(dplyr)

mydf %>%
  group_by(group_ID) %>%
  mutate(v_upd = cumsum(ifelse(value * lag(value, default = 0) != 0, 1, 0)) + 1) %>%
  ungroup()

# # A tibble: 12 x 4
#   group_ID element_index value v_upd
#      <dbl>         <dbl> <dbl> <dbl>
# 1        1             1   123     1
# 2        1             2     0     1
# 3        1             3     0     1
# 4        1             4   456     1
# 5        1             5   214     2
# 6        2             1    20     1
# 7        2             2     0     1
# 8        2             3    30     1
# 9        3             1    10     1
# 10       3             2     0     1
# 11       3             3    10     1
# 12       3             4    20     2

为了更好地理解这个过程,请检查这个(类似的)将每个步骤存储为变量的过程:

mydf %>%
  group_by(group_ID) %>%                             # for each group ID
  mutate(lag1_value = lag(value, default = 0)) %>%   # get the previous value of "value"
  mutate(v = ifelse(value * lag1_value != 0, 1, 0),  # for both current and previous value is different than 0 flag as 1
         v_upd = cumsum(v)+1) %>%                    # get cummulative sum of flags and add 1
  ungroup()                                          # forget the grouping

# # A tibble: 12 x 6
#   group_ID element_index value lag1_value     v v_upd
#      <dbl>         <dbl> <dbl>      <dbl> <dbl> <dbl>
# 1        1             1   123          0     0     1
# 2        1             2     0        123     0     1
# 3        1             3     0          0     0     1
# 4        1             4   456          0     0     1
# 5        1             5   214        456     1     2
# 6        2             1    20          0     0     1
# 7        2             2     0         20     0     1
# 8        2             3    30          0     0     1
# 9        3             1    10          0     0     1
# 10       3             2     0         10     0     1
# 11       3             3    10          0     0     1
# 12       3             4    20         10     1     2