在数据框中计算计数变量

8

I have an R data frame:

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语言的专家,也无法想出一种高效的方法来解决这个问题。我的主要问题似乎是“list”中的任何值都可能随时返回,但没有规定一个值块的长度。有人有什么想法吗?谢谢!


4
只是一条评论:通常最好不要使用内置名称(例如datalist)作为变量名称 - 如果以后您想要使用 list() 函数,您可能会遇到非常奇怪的错误。 - Stephan Kolassa
事实上,大多数人都不会把他们的狗叫做“狗”!例如。 - Gavin Simpson
是的,你说得对。我会从现在开始记住的。 - Lucy Vanes
2个回答

6

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

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

@user1777393 如果您对答案感到满意,请考虑接受其中之一。在您希望接受的答案旁边使用大勾号。[so] faq 中的 [ask] 部分解释了如何执行此操作以及为什么这样做是有益的/有用的。 - Gavin Simpson

5
关键思想是在将data$list(转换为原子向量后)上使用rle()(run length encoding,即运行长度编码)。然后我们使用seq()创建从1开始到计算出的运行长度结束的序列。最后,我们将所有这些序列粘合在一起。
unlist(lapply(rle(as.numeric(data$list))$lengths,FUN=seq,from=1))

谢谢!这正是我需要的。我不知道那个函数,所以你让我非常开心。 - Lucy Vanes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接