R,dplyr:n_distinct的累积版本

ste*_*ish 6 r cumsum dplyr

我有一个数据帧如下.它按列排序time.

输入 -

df = data.frame(time = 1:20,
            grp = sort(rep(1:5,4)),
            var1 = rep(c('A','B'),10)
            )

head(df,10)
   time grp var1
1   1   1    A
2   2   1    B
3   3   1    A
4   4   1    B
5   5   2    A
6   6   2    B
7   7   2    A
8   8   2    B
9   9   3    A
10 10   3    B
Run Code Online (Sandbox Code Playgroud)

我想创建另一个变量var2,它var1到目前为止计算不同的值,即直到time每个组的那个点grp.这与我使用时的情况略有不同n_distinct.

预期产量 -

   time grp var1 var2
1   1   1    A    1
2   2   1    B    2
3   3   1    A    2
4   4   1    B    2
5   5   2    A    1
6   6   2    B    2
7   7   2    A    2
8   8   2    B    2
9   9   3    A    1
10 10   3    B    2
Run Code Online (Sandbox Code Playgroud)

我想为此创建一个函数cum_n_distinct并将其用作 -

d_out = df %>%
  arrange(time) %>%
  group_by(grp) %>%
  mutate(var2 = cum_n_distinct(var1))
Run Code Online (Sandbox Code Playgroud)

ste*_*ish 6

一个dplyr解决方案,从@ akrun的回答启发-

这种逻辑基本上是为每个组设置to的每个唯一值的第一个匹配项,然后将set设置var11rest ,然后在其上应用-0grpcumsum

df = df %>%
  arrange(time) %>%
  group_by(grp,var1) %>%
  mutate(var_temp = ifelse(row_number()==1,1,0)) %>%
  group_by(grp) %>%
  mutate(var2 = cumsum(var_temp)) %>%
  select(-var_temp)

head(df,10)

Source: local data frame [10 x 4]
Groups: grp

   time grp var1 var2
1     1   1    A    1
2     2   1    B    2
3     3   1    A    2
4     4   1    B    2
5     5   2    A    1
6     6   2    B    2
7     7   2    A    2
8     8   2    B    2
9     9   3    A    1
10   10   3    B    2
Run Code Online (Sandbox Code Playgroud)


Bro*_*ieG 5

假设time已经按顺序排序,首先定义一个累积的不同函数:

dist_cum <- function(var)
  sapply(seq_along(var), function(x) length(unique(head(var, x))))
Run Code Online (Sandbox Code Playgroud)

然后是ave用于创建组的基本解决方案(注意,假设var1是因子),然后将我们的函数应用于每个组:

transform(df, var2=ave(as.integer(var1), grp, FUN=dist_cum))
Run Code Online (Sandbox Code Playgroud)

一个data.table解决方案,基本上还是在做同样的事情:

library(data.table)
(data.table(df)[, var2:=dist_cum(var1), by=grp])
Run Code Online (Sandbox Code Playgroud)

而且dplyr,同样的事情:

library(dplyr)
df %>% group_by(grp) %>% mutate(var2=dist_cum(var1))
Run Code Online (Sandbox Code Playgroud)