people_id activity_id success totl_act success_rate cum_success cum_act cum_success_rate success_rate_trend
(fctr) (fctr) (int) (int) (dbl) (int) (int) (dbl) (dbl)
1 ppl_100 act2_1734928 0 1 0 0 1 0 NA
2 ppl_100 act2_2434093 0 1 0 0 2 0 0
3 ppl_100 act2_3404049 0 1 0 0 3 0 0
4 ppl_100 act2_3651215 0 1 0 0 4 0 0
5 ppl_100 act2_4109017 0 1 0 0 5 0 0
6 ppl_100 act2_898576 0 1 0 0 6 0 0
7 ppl_100002 act2_1233489 1 1 1 1 1 1 1
8 ppl_100002 act2_1623405 1 1 1 2 2 1 0
9 ppl_100003 act2_1111598 1 1 1 1 1 1 0
10 ppl_100003 act2_1177453 1 1 1 2 2 1 0
我是这个样本数据框。我想使用success_rate_trend
变量创建变量cum_success_rate
。面临的挑战是,除了每个唯一activity_id
的第一个活动之外,我希望它为每个people_id
计算,即我想捕获唯一people_id
的成功趋势。我使用以下代码:
success_rate_trend<-vector(mode="numeric", length=nrow(succ_rate_df)-1)
for(i in 2:nrow(succ_rate_df)){
if(succ_rate_df[i,1]!=succ_rate_df[i-1,1]){
success_rate_trend[i] = NA
}
else {
success_rate_trend[i]<-succ_rate_df[i,8]-succ_rate_df[i-1,8]
}}
运行需要永远。我在succ_rate_df
数据框中接近了数百万行。任何人都可以建议如何简化代码并缩短运行时间。
答案 0 :(得分:3)
使用矢量化:
people_id
注意:
(fctr)
是因子变量diff()
。要使用as.integer()
,我们必须使用unclass()
或tbl_df
删除因子类。dplyr
的{{1}}。像索引这样的矩阵不起作用。使用succ_rate_df$people_id
或succ_rate_df[["people_id"]]
代替succ_rate_df[, 1]
。答案 1 :(得分:1)
您应该能够使用矢量化方法进行此计算。这将快几个数量级。
n = nrow(succ_rate_df)
success_rate = succ_rate_df[2:n,1] == succ_rate_df[1:(n-1),1]
is_true = which(success_rate)
success_rate[is_true] = succ_rate_df[is_true+1,8]-succ_rate_df[is_true,8]
success_rate[!success_rate] = NA
李哲元的回答是整洁的。
答案 2 :(得分:0)
我将根据此数据的数据框版本提供答案。您应该学会使用dput
的输出进行发布,以便具有特殊属性的对象(如上面打印的tibble)可以复制到其他用户控制台而不会丢失属性。我还要命名我的数据帧dat
。 ave
函数适用于计算数值向量时,如果希望它们与输入向量的长度相同,但希望这些计算仅限于对向量进行分组。我只使用了一个分组因子,尽管你对这个问题的英语描述表明你想要两个。有一些SO工作示例有两个因素可以用ave
进行分组。
success_rate_trend <- with( dat,
ave( cum_success_rate, people_id, FUN= function(x) c(NA, diff(x) ) ) )
success_rate_trend
[1] NA 0 0 0 0 0 NA 0 NA 0
# not a very interesting result