繁体   English   中英

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

[英]Create a block column based on id and the value of another column in R

给定以下前两列(id和time_diff),我想生成“ block”列

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的time_diff> 10时增加。

如何在R中实现这一目标?

将您的数据作为数据框导入,如下所示:

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

> 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变量与我的block变量之间存在偏移量:纠正它很容易,可以在几个不同的步骤中完成,我留给您:)

@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

向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

这是使用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)

尝试:

> 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM