假设我有以下数据框:
set.seed(3)
n=12
x <- rbinom(n,1,0.5)
y <- (x==1) * rexp(n, 1/365)
group <- sample(rep(1:2,each=6))
dat <- data.frame(x, y, group)
dat2 <- with(dat, dat[order(group, y),] )
dat2
变为:
x y group
1 0 0.00000 1
3 0 0.00000 1
2 1 41.79209 1
5 1 57.73478 1
10 1 441.58968 1
6 1 1541.61783 1
4 0 0.00000 2
7 0 0.00000 2
8 0 0.00000 2
9 1 141.78670 2
11 1 432.98895 2
12 1 638.24612 2
现在,我想在i
中创建另一列dat2
,如果x==0
将取值0,并且对于第1组和第1组中的最小y
将取值1 ; 2;对于两个组中第二小i
,y
将取值2。也就是说,在每个组中,我将按升序排列y
,x==0
除外。
列i
如下:
x y group i
1 0 0.00000 1 0
3 0 0.00000 1 0
2 1 41.79209 1 1
5 1 57.73478 1 2
10 1 441.58968 1 3
6 1 1541.61783 1 4
4 0 0.00000 2 0
7 0 0.00000 2 0
8 0 0.00000 2 0
9 1 141.78670 2 1
11 1 432.98895 2 2
12 1 638.24612 2 3
为此,我首先将数据框dat2
拆分为组:
dat3 <- split(dat2, dat2$group)
dat31 <- dat3[[1]]
dat31$i <- with(dat31, ifelse(x==0, 0, 1:length(x[x==1])) )
但i
根据行数取值。我必须在创建y
的代码中对i
给出一个条件,但我不明白如何纳入这样的条件?
赞赏创建列i
的任何更优雅的功能。
答案 0 :(得分:1)
如果您知道y
正在提升且不会重复,则可以使用cumsum
:
library(dplyr)
dat2 %>% group_by(group) %>% mutate(i = cumsum(y > 0))
## Source: local data frame [12 x 4]
## Groups: group [2]
##
## x y group i
## <int> <dbl> <int> <int>
## 1 0 0.00000 1 0
## 2 0 0.00000 1 0
## 3 1 41.79209 1 1
## 4 1 57.73478 1 2
## 5 1 441.58968 1 3
## 6 1 1541.61783 1 4
## 7 0 0.00000 2 0
## 8 0 0.00000 2 0
## 9 0 0.00000 2 0
## 10 1 141.78670 2 1
## 11 1 432.98895 2 2
## 12 1 638.24612 2 3
或在基地,
dat2$i <- ave(dat2$y, dat2$group, FUN = function(x){cumsum(x > 0)})
如果您不确定有关y
的假设,例如如果您想将i
列直接添加到dat
,可以使用dplyr::dense_rank
,减去1从零开始:
dat2 %>% group_by(group) %>% mutate(i = dense_rank(y) - 1)
你可以在基地重建:
dat2$i <- ave(dat2$y, dat2$group, FUN = function(x){
r <- rank(x);
match(r, sort(unique(r))) - 1
})
全部返回相同的值。
答案 1 :(得分:0)
我们可以使用data.table
。转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT(dat2)
),按&#39;分组&#39;,获取逻辑向量(y > 0
)并找到累积总和(cumsum
)并分配(:=
} )它到新专栏&#39; i&#39;
library(data.table)
setDT(dat2)[, i:= cumsum(y>0) , group]
dat2
# x y group i
#1: 0 0.00000 1 0
#2: 0 0.00000 1 0
#3: 1 41.79209 1 1
#4: 1 57.73478 1 2
#5: 1 441.58968 1 3
#6: 1 1541.61783 1 4
#7: 0 0.00000 2 0
#8: 0 0.00000 2 0
#9: 0 0.00000 2 0
#10:1 141.78670 2 1
#11:1 432.98895 2 2
#12:1 638.24612 2 3
或来自ave
base R
dat2$i <- with(dat2, ave(y > 0, group, FUN = cumsum))