You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 11:05:02