创建一个列,该列将以另一列的最小值开始取值1,并将值增加1到最大值

时间:2017-02-26 03:52:39

标签: r sorting dataframe

假设我有以下数据框:

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;对于两个组中第二小iy将取值2。也就是说,在每个组中,我将按升序排列yx==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的任何更优雅的功能。

2 个答案:

答案 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))