添加计算序列号的列

  • 本文关键字:序列号 计算 添加 r
  • 更新时间 :
  • 英文 :


我想添加一个计算连续值数的列。 我在这里看到的大部分是如何计算重复值 (1,1,1,1,1(,我想在数字上升 1 时计算 a ( 5,6,7,8,9(。 ID列是我所拥有的,计数器列是我想创建的。 谢谢!

ID Counter  
5  1  
6  2  
7  3  
8  4  
10 1  
11 2  
13 1  
14 2  
15 3  
16 4 

使用dplyr包的解决方案。这个想法是计算每个数字之间的差异以创建一个分组列,然后为每个组分配计数器。

library(dplyr)
dat2 <- dat %>%
mutate(Diff = ID - lag(ID, default = 0),
Group = cumsum(Diff != 1)) %>%
group_by(Group) %>%
mutate(Counter = row_number()) %>%
ungroup() %>%
select(-Diff, -Group)
dat2
# # A tibble: 10 x 2
#       ID Counter
#    <int>   <int>
#  1     5       1
#  2     6       2
#  3     7       3
#  4     8       4
#  5    10       1
#  6    11       2
#  7    13       1
#  8    14       2
#  9    15       3
# 10    16       4

数据

dat <- read.table(text = "ID
5   
6  
7  
8  
10  
11  
13  
14  
15  
16",
header = TRUE, stringsAsFactors = FALSE)

循环版本很简单:

for (i in 2:length(ID)) 
if (diff(ID)[i-1] == 1) 
counter[i] <- counter[i-1] +1
else
counter[i] <- 1

但是这个循环对于 n> 10^4 的表现会非常糟糕!我会试着想一个矢量解决方案!

您可以使用

s=df$ID-shift(df$ID)
s[is.na(s)]=1   
ave(s,cumsum(s!=1),FUN=seq_along)
[1] 1 2 3 4 1 2 1 2 3 4

这个只使用高效的向量算术。思路如下:

1.取ID差额的累计和

2.如果跳跃大于 1,则减去该值

cum <- c(0, cumsum(diff(ID)))  # take the cumulative difference of ID
ccm <- cum * c(1, (diff(ID) > 1))  # those with jump > 1 will remain its value
# subtract value with jump > 1 for all following numbers (see Link for reference)
# note: rep(0, n) is because ccm[...] starts at first non null value
counter <- cum - c(rep(0, which(diff(dat) != 1)[1]),
ccm[which(ccm != 0)][cumsum(ccm != 0)]) + 1
enter code here

注释

  • nacnudus 的高效填充函数参考:使用上面行的值填充数据框

  • 限制:Id 必须单调递增

这应该可以有效地处理您的数百万数据!

另一种解决方案:

breaks <- c(which(diff(ID)!=1), length(ID))
x <- c(breaks[1], diff(breaks))
unlist(sapply(x, seq_len))

最新更新