按用户计算转换点前Exponential占比并汇总为Final_Conv列
可扩展的R语言实现方案
这个需求的核心是动态划分每个用户的转换区间,避免手动创建多个转换列,下面用两种方法实现,都是完全可扩展的——不管用户有多少个转换点,代码都不需要修改。
首先先还原你的原始数据集:
# 创建原始数据集 User<- c("User1", "User1","User1", "User1","User1", "User1","User1", "User2","User2","User2","User2","User2","User2","User2") Touchpoints <- c("A", "B", "C", "F", "D", "E", "H","A", "B", "K", "D", "E", "F", "M") Conversion <- c(0,0,0,1,0,0,1,0,0,1,1,0,0,1) Frequency<-c(1,2,3,0,4,5,0,1,2,0,0,3,4,5) df<-data.frame(User, Touchpoints, Conversion, Frequency) df$Exponential<-ifelse(df$Frequency>0, exp(df$Frequency), 0)
方法1:用dplyr(简洁易读,推荐)
dplyr的分组和窗口函数非常适合这类按用户分组的动态计算:
library(dplyr) df_final <- df %>% # 第一步:按用户分组,标记每个转换区间 # 思路:每次遇到Conversion=1,区间编号+1,初始区间为1 group_by(User) %>% mutate(conv_interval = cumsum(Conversion) + 1) %>% # 第二步:按用户+区间分组,计算当前区间的Exponential总和 group_by(User, conv_interval) %>% mutate(interval_total = sum(Exponential)) %>% # 第三步:计算Final_Conv:转换记录设为0,非转换记录取占比并保留4位小数 mutate(Final_Conv = ifelse(Conversion == 1, 0, round(Exponential / interval_total, 4))) %>% # 清理辅助列,保留需要的结果列 ungroup() %>% select(User, Touchpoints, Conversion, Frequency, Final_Conv)
运行后输出的df_final就和你期望的结果完全一致:
# A tibble: 14 × 5 User Touchpoints Conversion Frequency Final_Conv <chr> <chr> <dbl> <dbl> <dbl> 1 User1 A 0 1 0.1017 2 User1 B 0 2 0.2764 3 User1 C 0 3 0.7514 4 User1 F 1 0 0 5 User1 D 0 4 0.2341 6 User1 E 0 5 0.6364 7 User1 H 1 0 0 8 User2 A 0 1 0.5379 9 User2 B 0 2 1.4621 10 User2 K 1 0 0 11 User2 D 1 0 0 12 User2 E 0 3 0 13 User2 F 0 4 0 14 User2 M 0 5 0
为什么这个方法可扩展?
cumsum(Conversion) + 1会自动为每个用户生成转换区间编号,不管用户有1个、2个还是N个转换点,都不需要手动调整代码- 所有计算都是基于动态生成的区间,不会出现列数随转换点数量增加而爆炸的问题
方法2:用Base R(无需额外依赖)
如果不想加载dplyr包,用Base R也能实现:
# 1. 标记每个用户的转换区间 df$conv_interval <- ave(df$Conversion, df$User, FUN = function(x) cumsum(x) + 1) # 2. 计算每个区间的Exponential总和 interval_totals <- aggregate(Exponential ~ User + conv_interval, data = df, sum) # 3. 将总和合并回原数据集 df <- merge(df, interval_totals, by = c("User", "conv_interval"), suffixes = c("", "_total")) # 4. 计算Final_Conv df$Final_Conv <- ifelse(df$Conversion == 1, 0, round(df$Exponential / df$Exponential_total, 4)) # 5. 整理列并恢复原始顺序 df_final_base <- df[, c("User", "Touchpoints", "Conversion", "Frequency", "Final_Conv")] df_final_base <- df_final_base[order(match(df_final_base$User, df$User), match(df_final_base$Touchpoints, df$Touchpoints)), ] rownames(df_final_base) <- NULL
运行后得到的结果和dplyr方法完全一致,适合不能加载外部包的场景。
内容的提问来源于stack exchange,提问作者Nick Knauer
相关产品推荐
相关产品推荐

