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

R语言for循环仅输出末次迭代结果问题排查(足球传球网络分析)

原代码的问题

你的循环跑不出预期结果,是5个明确的逻辑错误导致的,和缺索引没有直接关系:

  • 结果存储逻辑完全错误:你初始化network_metrics时长度设为比赛总场次,和你需要的307个换人结果长度不匹配;且循环内直接执行network_metrics <- density,每次都会把整个结果变量覆盖成单个数值,循环跑完自然只剩最后一次计算的单值。
  • 未处理单场多换人场景:单场比赛存在多次换人,你用which(match_i$type.name == "Substitution")会一次性返回本场所有换人行号,直接拿来切片会把所有换人对应的窗口数据混在一起,根本没有逐个为每个换人单独构建传球网络,必然漏算大量换人事件。
  • 窗口提取逻辑错误:直接从换人行号往前数50行,没有排除行序列中夹杂的其他换人事件,会导致窗口内实际传球数不足50,甚至把换人事件的空字段当成传球边,建图结果完全错误。
  • 存在冗余重复代码:单场数据提取的代码重复写了两次,虽不影响结果但属于无效代码。
  • 未做边界处理:如果某次换人发生时场上累计传球不足50次,直接减50会生成负数行索引,提取到完全无关的行。
修正后可运行代码

核心调整是加一层内层循环遍历单场所有换人事件,单独提取每个换人前的50次有效传球,按索引存储结果,同时处理边界异常:

library(igraph)
# 读取所有比赛ID
match_ids <- unique(pass.sub_dataframe$match_id)
# 初始化结果向量,长度匹配总换人次数
total_subs <- sum(pass.sub_dataframe$type.name == "Substitution")
network_metrics <- numeric(total_subs)
# 结果存储位置计数器
res_pos <- 1

for (i in seq_along(match_ids)) {
  # 提取单场全量数据
  match_data <- pass.sub_dataframe[pass.sub_dataframe$match_id == match_ids[i], ]
  # 单独标记本场所有传球、换人事件的行位置
  all_pass_rows <- which(match_data$type.name == "Pass")
  all_sub_rows <- which(match_data$type.name == "Substitution")
  
  # 内层遍历本场每一次换人
  for (j in seq_along(all_sub_rows)) {
    current_sub_loc <- all_sub_rows[j]
    # 筛选当前换人发生前的所有传球
    prior_passes <- all_pass_rows[all_pass_rows < current_sub_loc]
    
    # 取最近50次传球,不足50次则取全部可用传球
    if (length(prior_passes) >= 50) {
      window_rows <- tail(prior_passes, 50)
    } else {
      window_rows <- prior_passes
      warning(paste0("比赛ID", match_ids[i], "第", j, "次换人前方累计传球不足50次,实际使用", length(window_rows), "条传球计算"))
    }
    
    # 提取传球边表,剔除缺失值
    edge_df <- match_data[window_rows, c("player.name", "pass.recipient.name")]
    edge_df <- na.omit(edge_df)
    
    # 构建有向图计算密度,直接用igraph内置函数避免手写公式出错
    pass_graph <- graph_from_data_frame(edge_df, directed = TRUE)
    network_metrics[res_pos] <- edge_density(pass_graph, loops = FALSE)
    
    # 存储位置后移
    res_pos <- res_pos + 1
  }
}
补充说明
  • 最终network_metrics会按换人事件在原始数据中出现的顺序,返回对应307个密度值。如果需要匹配每次换人的具体信息(比赛、上场/离场球员、换人时间),可以额外建个数据框同步存储这些字段和对应密度,方便后续分析。
  • 代码用igraph内置的edge_density()计算密度,默认适配有向图计算逻辑,自动排除自环影响,比手写公式容错率更高。
  • 加了传球不足50次的兼容逻辑,不会出现负数索引取错数据的问题,警告信息可以帮你定位哪些换人场景的传球窗口长度不足50,按需调整即可。

内容的提问来源于stack exchange,提问作者Jasfr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 00:06:32