如何用tidyverse复现飞镖联赛数据的宽转长(对应Stata代码)
使用tidyverse复现飞镖联赛数据宽转长及logit回归流程
1. 模拟宽格式参考数据
先构建与典型飞镖联赛宽格式匹配的模拟数据,你可以替换为自身真实数据的字段名与内容:
library(tidyverse) # 模拟宽格式飞镖联赛数据 wide_darts_data <- tibble( match_id = 1:10, player1 = paste0("Player_", sample(1:20, 10)), player2 = paste0("Player_", sample(1:20, 10)), winner = sample(c(1, 0), 10, replace = TRUE), # 1=player1获胜,0=player2获胜 avg1 = round(rnorm(10, 85, 10), 1), # 第1局平均分 avg2 = round(rnorm(10, 85, 10), 1), avg3 = round(rnorm(10, 85, 10), 1), avg4 = round(rnorm(10, 85, 10), 1), avg5 = round(rnorm(10, 85, 10), 1), remaining1 = sample(0:100, 10), # 第1局剩余分数 remaining2 = sample(0:100, 10), remaining3 = sample(0:100, 10), remaining4 = sample(0:100, 10), remaining5 = sample(0:100, 10) )
2. 宽格式转长格式(保留最多5局结构)
利用pivot_longer实现结构转换,自动提取局数并过滤未进行的对局:
# 转换为长格式 long_darts_data <- wide_darts_data %>% pivot_longer( cols = starts_with(c("avg", "remaining")), # 匹配所有局相关字段 names_to = c(".value", "leg"), # .value保留字段前缀(avg/remaining),leg存储局数 names_pattern = "(avg|remaining)(\\d)" # 正则匹配前缀与局数数字 ) %>% mutate( leg = as.integer(leg), # 将局数转为整数类型 .by = match_id, is_played = !is.na(avg) # 标记该局是否实际进行 ) %>% filter(is_played) %>% # 过滤未进行的对局 select(-is_played) # 移除临时标记列
字段命名适配提示
如果你的宽格式字段是leg1_avg_player1这类分选手的命名,可调整正则规则:
# 适配分选手的局数据格式 pivot_longer( cols = starts_with("leg"), names_to = c("leg", "metric", "player"), names_pattern = "leg(\\d)_(avg|remaining)_player(\\d)" )
3. 数据验证
确认转换后的数据结构与每场比赛的局数分布:
# 查看长格式数据结构 glimpse(long_darts_data) # 统计每场比赛的实际局数 long_darts_data %>% count(match_id, name = "leg_count")
4. Logit回归分析
根据分析需求选择局级或整场比赛级的回归模型:
场景1:整场比赛结果的Logit回归
先聚合每局特征为比赛级统计量,再拟合模型:
# 聚合每场比赛的局级特征 match_level_data <- long_darts_data %>% group_by(match_id, winner) %>% summarise( avg_total_avg = mean(avg), # 所有局的平均分均值 min_remaining = min(remaining), # 剩余分数最小值 max_avg = max(avg), # 单局最高平均分 leg_count = n(), # 总局数 .groups = "drop" ) # 拟合Logit回归模型 logit_model <- glm(winner ~ avg_total_avg + min_remaining + max_avg + leg_count, data = match_level_data, family = binomial(link = "logit")) # 查看模型结果 summary(logit_model)
场景2:局级结果的Logit回归
若存在每局的获胜标记,直接拟合局级模型:
# 模拟局级获胜标记(替换为真实规则) long_darts_data <- long_darts_data %>% mutate( leg_winner = ifelse(avg > mean(avg, .by = match_id), 1, 0) ) # 拟合局级Logit模型 leg_logit_model <- glm(leg_winner ~ avg + remaining, data = long_darts_data, family = binomial(link = "logit")) summary(leg_logit_model)
内容的提问来源于stack exchange,提问作者Emre Toros
相关产品推荐
相关产品推荐

