假设我们有以下数据库:
ID Shoot hit
1 10 2
1 9 3
1 8 1
2 10 8
2 8 8
2 11 10
2 7 2
3 9 2
4 6 6
4 6 5
.
.
我希望在每个组中分配数字,在这种情况下,每个ID如:
ID Shoot hit number.in.group
1 10 2 1
1 9 3 2
1 8 1 3
2 10 8 1
2 8 8 2
2 11 10 3
2 7 2 4
3 9 2 1
4 6 6 1
4 6 5 2
.
.
我可以使用循环轻松完成。像这样的东西会起作用:
df$number.in.group = rep(1,nrow(df))
for(i in 2:nrow(df))
if(df$ID[i]==df$ID[i-1]){
df$number.in.group[i] = df$number.in.group[i-1] + 1 }
我的问题是,除了使用循环之外,还有其他功能或更优雅的方法吗?
答案 0 :(得分:8)
您可以使用rle
和sequence
:
dat <- read.table(text = "ID Shoot hit
+ 1 10 2
+ 1 9 3
+ 1 8 1
+ 2 10 8
+ 2 8 8
+ 2 11 10
+ 2 7 2
+ 3 9 2
+ 4 6 6
+ 4 6 5",sep = "",header = TRUE)
> sequence(rle(dat$ID)$lengths)
[1] 1 2 3 1 2 3 4 1 1 2
的确,我认为sequence
的目的只是为了这个目的。
答案 1 :(得分:6)
> dat$number.in.group <- ave(dat$ID,dat$ID, FUN=seq_along)
> dat
ID Shoot hit number.in.group
1 1 10 2 1
2 1 9 3 2
3 1 8 1 3
4 2 10 8 1
5 2 8 8 2
6 2 11 10 3
7 2 7 2 4
8 3 9 2 1
9 4 6 6 1
10 4 6 5 2
答案 2 :(得分:2)
可能有更好的方法,但可以在ID上使用tapply并在返回序列的函数中进行折腾。
# Example data
dat <- data.frame(ID = rep(1:3, c(2, 3, 5)), val = rnorm(10))
# Using tapply with a function that returns a sequence
dat$number.in.group <- unlist(tapply(dat$ID, dat$ID, function(x){seq(length(x))}))
dat
导致
> dat
ID val number.in.group
1 1 -0.454652118 1
2 1 -2.391824247 2
3 2 0.530832021 1
4 2 -1.671043812 2
5 2 -0.045261549 3
6 3 2.311162484 1
7 3 -0.525635803 2
8 3 0.008588811 3
9 3 0.078942033 4
10 3 0.324156111 5
答案 3 :(得分:2)
df$number.in.group <- unlist(lapply(as.vector(unlist(rle(df$ID)[1])), function(x) 1:x))
答案 4 :(得分:2)
使用dplyr
dat <- data.frame(ID = rep(1:3, c(2, 3, 5)), val = rnorm(10))
library(dplyr)
dat %>% group_by(ID) %>%
mutate(number.in.group = 1:n())
答案 5 :(得分:1)
这是另一种解决方案
require(plyr)
ddply(dat, .(ID), transform, num_in_grp = seq_along(hit))
答案 6 :(得分:0)
我比较了你的anwsers和IShouldBuyABoat是最有希望的。我发现即使数据集没有根据分组变量进行排序,也可以应用函数ave。
让我们考虑数据集:
dane<-data.frame(g1=c(-1,-2,-2,-2,-3,-3,-3,-3,-3),
g2=c('reg','pl','reg','woj','woj','reg','woj','woj','woj'))
Joran anwser并应用于我的例子:
> sequence(rle(as.character(dane$g2))$lengths)
[1] 1 1 1 1 2 1 1 2 3
Simon Urbanek的主张和结果:
> unlist(lapply(table(dane$g2),seq.int))
pl reg1 reg2 reg3 woj1 woj2 woj3 woj4 woj5
1 1 2 3 1 2 3 4 5
IShouldBuyABoat代码提供正确的anwser:
> as.numeric(ave(as.character(dane$g1),as.character(dane$g1),FUN=seq_along))
[1] 1 1 2 3 1 2 3 4 5