8

我有一个 R 数据框:

a <- 1:12  
list <- c(rep("x",3),rep("y",4),rep("z",3),rep("x",2))  
data <- data.frame(a,list)

data  
 a list  
 1    x  
 2    x  
 3    x  
 4    y  
 5    y  
 6    y  
 7    y  
 8    z  
 9    z  
10    z  
11    x  
12    x

我想创建一个新列,每次“list”的值更改时从 1 开始计数,即在此示例中:

b <- c(1:3,1:4,1:3,1:2)    
data <- data.frame(a,list,b)  

我远不是 R 方面的专家,而且我一生都无法找到一种有效的方法来做到这一点。我的主要问题似乎是“列表”的任何值都可以随时返回,但是对于一个值的块的长度没有规则。有没有人有任何想法?谢谢!

4

2 回答 2

6

我会rle()用来获取运行长度,list然后使用方便的函数从返回的组件sequence()生成所需的计数器:$lengthsrle()

R> sequence(rle(as.character(data$list))$lengths)
 [1] 1 2 3 1 2 3 4 1 2 3 1 2

请注意,我们必须转换list为原子向量(在我的情况下为字符向量),因为rle().

要将其放入 中data,然后将其包装在一个调用中,例如

data <- transform(data, b = sequence(rle(as.character(list))$lengths))

这使

R> data <- transform(data, b = sequence(rle(as.character(list))$lengths))
R> data
    a list b
1   1    x 1
2   2    x 2
3   3    x 3
4   4    y 1
5   5    y 2
6   6    y 3
7   7    y 4
8   8    z 1
9   9    z 2
10 10    z 3
11 11    x 1
12 12    x 2
于 2012-10-29T09:44:06.347 回答
5

关键思想是使用rle()(运行长度编码)data$list(在将其强制为原子向量之后 - 毕竟,我们对特定条目不感兴趣)。然后我们使用seq()创建从 1 开始并以计算的运行长度结束的序列。最后,我们将所有这些序列粘贴在一起:

unlist(lapply(rle(as.numeric(data$list))$lengths,FUN=seq,from=1))
于 2012-10-29T09:41:24.043 回答