ggplot2绘制足球传球网络:如何为散点图所有球员点建立基于传球次数的连线
优化足球传球网络可视化的简洁实现方法
我明白你之前手动逐个筛选传球组合来画连线的做法太繁琐了——不仅重复劳动,还容易出错或遗漏传球关系。其实咱们可以利用数据本身的结构,用更简洁的方式实现你想要的效果:让所有球员点根据传球次数相互连接,线条粗细对应传球数量。
步骤1:整理球员坐标映射
首先,我们需要提取所有球员的平均位置坐标,因为每个球员不管是传球方还是接球方,他们的平均位置是固定的:
# 创建球员平均坐标的映射表,去重得到每个球员唯一的位置 player_coords <- df2 %>% select(player = surname_sender, x = mean_passer_x, y = mean_passer_y) %>% distinct()
步骤2:构建传球网络数据
接下来,把原数据和球员坐标表连接,获取每一次传球的起点(传球者)和终点(接球者)坐标:
# 合并得到包含起点、终点坐标的传球网络数据 pass_network_data <- df2 %>% left_join(player_coords, by = c("surname_sender" = "player")) %>% left_join(player_coords, by = c("surname_receiver" = "player"), suffix = c("_sender", "_receiver"))
步骤3:绘制简洁的传球网络图
用geom_segment替代重复的geom_line,一次画出所有传球连线,同时调整可视化细节让效果更清晰:
library(tidyverse) library(ggsoccer) library(ggrepel) ggplot(pass_network_data) + # 添加自定义尺寸的球场背景 annotate_pitch(dimensions = pitch_custom) + # 绘制传球连线:粗细映射传球次数,调整透明度避免画面杂乱 geom_segment( aes(x = x_sender, y = y_sender, xend = x_receiver, yend = y_receiver, size = passes), alpha = 0.6, color = "gray50" ) + # 绘制球员位置点,用红色突出显示 geom_point( data = player_coords, aes(x = x, y = y), color = "red", size = 4 ) + # 添加球员名字标签,用ggrepel自动避免标签重叠 geom_text_repel( data = player_coords, aes(x = x, y = y, label = player), color = "black", size = 3 ) + # 自定义线条粗细的范围,适配你的传球次数数据 scale_size_continuous(range = c(0.5, 3)) + # 应用ggsoccer的球场主题 theme_pitch() + # 隐藏不必要的图例(如果不需要展示传球次数的刻度) theme(legend.position = "none")
关键优化点说明
geom_segment的优势:它可以直接指定线段的起点和终点坐标,一次调用就能画出所有传球连线,彻底告别重复的geom_line代码- 坐标映射表:避免重复计算球员位置,让数据结构更清晰
geom_text_repel:自动调整标签位置,解决了geom_text容易出现标签重叠的问题- 透明度与尺寸范围:调整
alpha和scale_size_continuous的range参数,让传球网络的层次更分明,不会因为连线过多显得杂乱
内容的提问来源于stack exchange,提问作者Emre Toros
相关产品推荐
相关产品推荐

