我有一个如下数据帧。它按列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
我想创建另一个变量var2
,它到目前为止计算不同的var1
值,即直到每个组time
中的那个点{{1} }。这与我使用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
,并将其用作 -
cum_n_distinct
答案 0 :(得分:6)
逻辑基本上是为每个组dplyr
设置var1
到1
的每个唯一值的第一次出现并休息到0
然后应用grp
在它上面 -
cumsum
答案 1 :(得分:5)
假设东西已经由time
排序,首先定义一个累积的不同函数:
dist_cum <- function(var)
sapply(seq_along(var), function(x) length(unique(head(var, x))))
然后使用ave
创建组的基本解决方案(注意,假定var1
是因子),然后将我们的函数应用于每个组:
transform(df, var2=ave(as.integer(var1), grp, FUN=dist_cum))
data.table
解决方案,基本上做同样的事情:
library(data.table)
(data.table(df)[, var2:=dist_cum(var1), by=grp])
dplyr
,同样的事情:
library(dplyr)
df %>% group_by(grp) %>% mutate(var2=dist_cum(var1))
答案 2 :(得分:2)
尝试:
使用新数据集,基础R中的方法
df$var2 <- unlist(lapply(split(df, df$grp),
function(x) {x$var2 <-0
indx <- match(unique(x$var1), x$var1)
x$var2[indx] <- 1
cumsum(x$var2) }))
head(df,7)
# 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
答案 3 :(得分:1)
这是另一种使用data.table的解决方案,很快。
cum_n_distinct <- function(x, na.include = TRUE){
# Given a vector x, returns a corresponding vector y
# where the ith element of y gives the number of unique
# elements observed up to and including index i
# if na.include = TRUE (default) NA is counted as an
# additional unique element, otherwise it's essentially ignored
temp <- data.table(x, idx = seq_along(x))
firsts <- temp[temp[, .I[1L], by = x]$V1]
if(na.include == FALSE) firsts <- firsts[!is.na(x)]
y <- rep(0, times = length(x))
y[firsts$idx] <- 1
y <- cumsum(y)
return(y)
}
cum_n_distinct(c(5,10,10,15,5)) # 1 2 2 3 3
cum_n_distinct(c(5,NA,10,15,5)) # 1 2 3 4 4
cum_n_distinct(c(5,NA,10,15,5), na.include = FALSE) # 1 1 2 3 3
d_out = df %>%
arrange(time) %>%
group_by(grp) %>%
mutate(var2 = cum_n_distinct(var1))