在日常功能迭代分析中,一般会直接看使用该功能和未使用该功能的用户在成功指标上的表现,将两组数据求个差异值就得出功能的效果结论。但是有敏锐的分析师会发现,功能大部分情况下有筛选效应,即使用该功能的用户可能本身质量比较高,活跃比较频繁。用以上的方法估计会导致效果评估失真,那么如何规避混杂因素导致的幸存者偏差。优先考虑的做法是探究一些相关关系因素,用 A/B 测试验证,把因果推断作为备选或探索式分析的手段,但有些场景无法进行 A/B 测试。这里介绍因果推断中的两个方法——匹配和逆概率加权。并将其和直接回归方法的结论进行对比,看看相关和因果的结论到底会差异多少。
因果推断方法一般的通俗理解,A/B 测试不行,创造条件近似 A/B 测试。
案例背景
分析师评估某功能是否可以降低用户流失率。这里的数据不是实验性的,工程上谁也无法控制用户去使用新功能。数据集包含以下列:
流失率(Churn_rate):用户流失的可能性。值越高表示流失的概率越高。
是否使用该功能(is_using):二进制变量,用户是否使用了该功能。
日均使用时长(avg_used_time):用户使用产品的日均时长。
用户信用评分(health):用户自我报告的信用评分状况。以0–100的等级进行测量,数值越高表示信用状况越好。
最近一次使用时间(recency):最近一次使用距离现在的天数。
活跃天数(active_days):最近一个月使用产品的天数。
我们仅使用观察数据来估计该功能使用对流失风险的因果关系。因为这不是随机控制实验(RCT),宣称因果关系似乎有些不准确。但是,如果我们可以绘制正确的 DAG 并针对正确的节点进行调整,则可以得到使用功能→流失的因果关系并求出接近的因果效应。因为这是模拟数据,所以我们知道真正因果关系,即设置真正的平均处理效应(ATE)为 -0.1。平均而言,使用该功能可使流失风险降低 0.1 个单位。
加载数据
library(tidyverse)
library(ggdag) # Make DAGs
library(dagitty) # Do DAG logic with R
library(broom) # Convert models to data frames
library(MatchIt) # Match things
library(modelsummary) # Make side-by-side regression tables
set.seed(1234) # Make all random draws reproducible
data <- read_csv("churn_causal_relationship.csv")
我们建立了这个因果模型,以显示功能使用和流失风险之间关系背后的数据生成过程:
dag <- dagify(
Churn_rate ~ is_using + avg_used_time + health + recency + active_days,
is_using ~ avg_used_time + recency + active_days,
active_days ~ avg_used_time,
exposure = "is_using",
outcome = "Churn_rate",
coords = list(x = c(Churn_rate = 7, is_using = 3, avg_used_time = 4, active_days = 5,
recency = 6, health = 8.5),
y = c(Churn_rate = 2, is_using = 2, avg_used_time = 3, active_days = 1,
recency = 3, health = 2)),
labels = c(Churn_rate = "Risk of Churn", is_using = "Is Using", avg_used_time = "average used time",
health = "Health", recency = "Recency",
active_days = "Activ