根据id和R中另一列的值创建一个块列

时间:2014-10-15 01:58:09

标签: r

鉴于以下前两列(id和time_diff),我想生成'块'柱

test
   id time_diff   block
1   a        NA       1
2   a         1       1
3   a         1       1
4   a         1       1
5   a         3       1
6   a         3       1
7   b        NA       2
8   b        11       3
9   b         1       3
10  b         1       3
11  b         1       3
12  b        12       4
13  b         1       4
14  c        NA       5
15  c         4       5
16  c         7       5

数据已按ID和时间排序。在给定相同id的情况下,time_diff是基于前一时间和行的时间值的差异来计算的。我想创建一个块ID,它是一个自动增量值,并在遇到具有相同id的新ID或> 10的time_diff时增加。

我如何在R?

中实现这一目标

5 个答案:

答案 0 :(得分:2)

将数据导入为数据框,例如:

df = read.table(text='
   id time_diff   block
1   a        NA       1
2   a         1       1
3   a         1       1
4   a         1       1
5   a         3       1
6   a         3       1
7   b        NA       2
8   b        11       3
9   b         1       3
10  b         1       3
11  b         1       3
12  b        12       4
13  b         1       4
14  c        NA       5
15  c         4       5
16  c         7       5')

你可以像这样做一个单行,以使事件满足你的两个条件:

> new_col = as.vector(cumsum(
     na.exclude(
       c(F,diff(as.numeric(as.factor(df$id)))) |     # change of id OR
       df$time_diff > 10                             # time_diff greater than 10
     )
  ))
> new_col
 [1] 0 0 0 0 0 1 2 2 2 2 3 3 4 4 4

最后使用cbind

将此新列附加到您的数据框
> cbind(df, block = c(0,new_col))
   id time_diff block block
1   a        NA     1     0
2   a         1     1     0
3   a         1     1     0
4   a         1     1     0
5   a         3     1     0
6   a         3     1     0
7   b        NA     2     1
8   b        11     3     2
9   b         1     3     2
10  b         1     3     2
11  b         1     3     2
12  b        12     4     3
13  b         1     4     3
14  c        NA     5     4
15  c         4     5     4
16  c         7     5     4

您会注意到您想要的block变量与我之间的偏差:纠正它很容易,可以在几个不同的步骤完成,我会留给您:)

答案 1 :(得分:2)

@ Jealie方法的另一个变体是:

with(test, cumsum(c(TRUE,id[-1]!=id[-nrow(test)])|time_diff>10))
#[1] 1 1 1 1 1 1 2 3 3 3 3 4 4 5 5 5

答案 2 :(得分:1)

在向Jealie和akrun学习之后,我提出了这个想法。

mydf %>%
    mutate(group = cumsum(time_diff > 10 |!duplicated(id)))

#   id time_diff block group
#1   a        NA     1     1
#2   a         1     1     1
#3   a         1     1     1
#4   a         1     1     1
#5   a         3     1     1
#6   a         3     1     1
#7   b        NA     2     2
#8   b        11     3     3
#9   b         1     3     3
#10  b         1     3     3
#11  b         1     3     3
#12  b        12     4     4
#13  b         1     4     4
#14  c        NA     5     5
#15  c         4     5     5
#16  c         7     5     5

答案 3 :(得分:0)

以下是使用dplyr的方法:

require(dplyr)

set.seed(999)
test <- data.frame(
  id = rep(letters[1:4], each = 3),
  time_diff = sample(4:15)
)


test %>%
  mutate(
    b = as.integer(id) - lag(as.integer(id)),
    more10 = time_diff > 10,
    increment = pmax(b, more10, na.rm = TRUE),
    increment = ifelse(row_number() == 1, 1, increment),
    block = cumsum(increment)
  ) %>%
  select(id, time_diff, block)

答案 4 :(得分:0)

尝试:

> df
   id time_diff
1   a        NA
2   a         1
3   a         1
4   a         1
5   a         3
6   a         3
7   b        NA
8   b        11
9   b         1
10  b         1
11  b         1
12  b        12
13  b         1
14  c        NA
15  c         4
16  c         7

block= c(1)
for(i in 2:nrow(df))
    block[i] = ifelse(df$time_diff[i]>10 || df$id[i]!=df$id[i-1], 
                  block[i-1]+1,
                  block[i-1])
df$block = block

df
   id time_diff block
1   a        NA     1
2   a         1     1
3   a         1     1
4   a         1     1
5   a         3     1
6   a         3     1
7   b        NA     2
8   b        11     3
9   b         1     3
10  b         1     3
11  b         1     3
12  b        12     4
13  b         1     4
14  c        NA     5
15  c         4     5
16  c         7     5