我有一个非常简单的问题,但我可能没有想到vector-y足以有效地解决它。我尝试了两种不同的方法,现在他们已经在两台不同的计算机上循环了很长时间。我希望我可以说比赛让比赛变得更加精彩,但是... ......嗯。
我有很长的数据(每人多行,每人一行观察)我基本上想要一个变量,告诉我这个人已经被观察过的频率。
我有前两列,想要第三个一个:
person wave obs
pers1 1999 1
pers1 2000 2
pers1 2003 3
pers2 1998 1
pers2 2001 2
现在我正在使用两种循环方法。两者都非常缓慢(150k行)。我确定我错过了一些东西,但我的搜索查询对我来说并没有真正帮助我(很难说出问题)。
感谢您的任何指示!
# ordered dataset by persnr and year of observation
person.obs <- person.obs[order(person.obs$PERSNR,person.obs$wave) , ]
person.obs$n.obs = 0
# first approach: loop through people and assign range
unp = unique(person.obs$PERSNR)
unplength = length(unp)
for(i in 1:unplength) {
print(unp[i])
person.obs[which(person.obs$PERSNR==unp[i]),]$n.obs =
1:length(person.obs[which(person.obs$PERSNR==unp[i]),]$n.obs)
i=i+1
gc()
}
# second approach: loop through rows and reset counter at new person
pnr = 0
for(i in 1:length(person.obs[,2])) {
if(pnr!=person.obs[i,]$PERSNR) { pnr = person.obs[i,]$PERSNR
e = 0
}
e=e+1
person.obs[i,]$n.obs = e
i=i+1
gc()
}
答案 0 :(得分:14)
Marek在this question中的答案在过去证明非常有用。我把它写下来并且几乎每天都使用它,因为它快速而有效。我们将使用ave()
和seq_along()
。
foo <-data.frame(person=c(rep("pers1",3),rep("pers2",2)),year=c(1999,2000,2003,1998,2011))
foo <- transform(foo, obs = ave(rep(NA, nrow(foo)), person, FUN = seq_along))
foo
person year obs
1 pers1 1999 1
2 pers1 2000 2
3 pers1 2003 3
4 pers2 1998 1
5 pers2 2011 2
使用plyr
library(plyr)
ddply(foo, "person", transform, obs2 = seq_along(person))
person year obs obs2
1 pers1 1999 1 1
2 pers1 2000 2 2
3 pers1 2003 3 3
4 pers2 1998 1 1
5 pers2 2011 2 2
答案 1 :(得分:4)
使用data.table和dplyr个套餐的一些替代方案。
<强> data.table:强>
library(data.table)
setDT(foo)[, rn := 1:.N, by = person] # setDT(foo) is needed to convert to a data.table
或使用新的rowid
函数( v1.9.7 + ,目前仅在the development version中可用)
setDT(foo)[, rn := rowid(person)]
都给出了:
> foo person year rn 1: pers1 1999 1 2: pers1 2000 2 3: pers1 2003 3 4: pers2 1998 1 5: pers2 2011 2
如果您想要真正的排名,则应使用frank
函数:
setDT(foo)[, rn := frank(year, ties.method = 'dense'), by = person]
<强> dplyr:强>
library(dplyr)
# method 1
foo <- foo %>% group_by(person) %>% mutate(rn = row_number())
# method 2
foo <- foo %>% group_by(person) %>% mutate(rn = 1:n())
两者都给出了类似的结果:
> foo Source: local data frame [5 x 3] Groups: person [2] person year rn (fctr) (dbl) (int) 1 pers1 1999 1 2 pers1 2000 2 3 pers1 2003 3 4 pers2 1998 1 5 pers2 2011 2
答案 2 :(得分:2)
by
可以解决这个问题吗?
> foo <-data.frame(person=c(rep("pers1",3),rep("pers2",2)),year=c(1999,2000,2003,1998,2011),obs=c(1,2,3,1,2))
> foo
person year obs
1 pers1 1999 1
2 pers1 2000 2
3 pers1 2003 3
4 pers2 1998 1
5 pers2 2011 2
> by(foo, foo$person, nrow)
foo$person: pers1
[1] 3
------------------------------------------------------------
foo$person: pers2
[1] 2