r - 如何将 geom_point 创建的散点图的所有点相互连接?
问题描述
我正在尝试在足球场上绘制传球网络。清理数据后它看起来像这样
structure(list(surname_sender = c("Ajite", "Dikmen", "Dikmen",
"Dikmen", "Dikmen", "Jylmaz", "Jylmaz", "Jylmaz", "Kandejas",
"Kandejas", "Kandejas", "Kandejas", "Kizildag", "Kizildag", "Kizildag",
"Kizildag", "Kizildag", "Motta", "Motta", "Motta", "Motta", "Motta",
"Motta", "Nordfel'dt", "Nordfel'dt", "Poloma", "Sio", "Ture",
"Ture", "Ture", "Ture", "Ture", "Uhansson", "Uhansson", "Uhansson",
"Uhansson"), surname_receiver = c("Poloma", "Kizildag", "Poloma",
"Ture", "Uhansson", "Kandejas", "Poloma", "Uhansson", "Motta",
"Nordfel'dt", "Ture", "Uhansson", "Dikmen", "Motta", "Nordfel'dt",
"Ture", "Uhansson", "Dikmen", "Jylmaz", "Kizildag", "Poloma",
"Ture", "Uhansson", "Ture", "Uhansson", "Ture", "Dikmen", "Jylmaz",
"Kandejas", "Kizildag", "Motta", "Poloma", "Kandejas", "Kizildag",
"Sio", "Uhansson"), passes = c(4L, 4L, 4L, 4L, 6L, 4L, 5L, 4L,
4L, 5L, 4L, 9L, 10L, 6L, 4L, 5L, 8L, 5L, 4L, 6L, 4L, 4L, 5L,
4L, 6L, 13L, 5L, 5L, 4L, 9L, 8L, 7L, 14L, 8L, 5L, 4L), mean_passer_x = c(64.7,
44.41875, 44.41875, 44.41875, 44.41875, 68.725, 68.725, 68.725,
75.2919444444445, 75.2919444444445, 75.2919444444445, 75.2919444444445,
29.5423333333333, 29.5423333333333, 29.5423333333333, 29.5423333333333,
29.5423333333333, 44.31, 44.31, 44.31, 44.31, 44.31, 44.31, 8.60416666666667,
8.60416666666667, 58.6384615384615, 52.46, 38.2090952380952,
38.2090952380952, 38.2090952380952, 38.2090952380952, 38.2090952380952,
51.7642857142857, 51.7642857142857, 51.7642857142857, 51.7642857142857
), mean_passer_y = c(46.9, 38.7083333333333, 38.7083333333333,
38.7083333333333, 38.7083333333333, 35.3533333333333, 35.3533333333333,
35.3533333333333, 10.7833333333333, 10.7833333333333, 10.7833333333333,
10.7833333333333, 23.6785, 23.6785, 23.6785, 23.6785, 23.6785,
34.6552777777778, 34.6552777777778, 34.6552777777778, 34.6552777777778,
34.6552777777778, 34.6552777777778, 32.2166666666667, 32.2166666666667,
65.3, 25.7, 46.9388571428571, 46.9388571428571, 46.9388571428571,
46.9388571428571, 46.9388571428571, 7.25, 7.25, 7.25, 7.25)), row.names = c(NA,
-36L), class = c("tbl_df", "tbl", "data.frame"))
我发现的解决方案似乎很无聊和愚蠢:)
library(tidyverse)
library(ggsoccer)
library(ggrepel)
ggplot(df2, aes(mean_passer_x, mean_passer_y)) +
annotate_pitch(dimensions = pitch_custom) +
geom_point(color = "red") +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Kizildag"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Uhansson"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Ture"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Sio"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Dikmen"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Kandejas"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Motta", "Jylmaz"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, color= "red", alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Kizildag", "Ture"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, color= "red", alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Nordfel'dt", "Ture"))) +
geom_line(aes(mean_passer_x, mean_passer_y, size = passes, color= "red", alpha = 0.2),
data = . %>% filter(surname_sender %in% c("Nordfel'dt", "Kizildag"))) +
geom_text(aes(label = surname_sender) ) +
theme_pitch()
最终结果是
我要做的就是通过线将所有点(玩家)相互连接,并根据传球次数定义线的大小。
非常感谢
解决方案
不完全确定您的最终结果。但是,据我所知,在您绘制传递网络之前,您的数据需要进行一些额外的处理。问题是您的 df 的每一行仅包含“发送者”的位置,而不包含接收者的位置。所以
- 我首先提取了所有玩家的姓名和(平均)位置
- 我加入数据集,位置回到你原来的df,我加入接收球员的名字。因此,每一行现在都包含发送和接收玩家的位置。
- 这样做之后,您可以通过使用
geom_segment
和映射passes
on size 的数量来轻松绘制网络。此外,我映射了surname_receiver
颜色以使通道的方向可见。
library(ggplot2)
library(ggsoccer)
library(ggrepel)
library(dplyr)
pos_player <- df2 %>%
select(name = surname_sender, pos_x = mean_passer_x, pos_y = mean_passer_y) %>%
distinct()
df2 %>%
left_join(pos_player, by = c("surname_receiver" = "name")) %>%
group_by(surname_sender) %>%
mutate(is_label = row_number() == 1) %>%
arrange(desc(passes)) %>%
ggplot(aes(x = mean_passer_x, y = mean_passer_y)) +
annotate_pitch() +
geom_segment(aes(xend = pos_x, yend = pos_y, size = passes, color = surname_sender), alpha = 0.5) +
geom_point(color = "red") +
ggrepel::geom_text_repel(aes(label = ifelse(is_label, surname_sender, "")) ) +
scale_color_brewer(type = "qual", palette = "Set3") +
theme_pitch()
推荐阅读
- python - TypeError:参数 1 必须是 pygame.Surface,而不是类型
- sass - 仅共享我的 sass/scss 变量的主题变量
- java - 我正在尝试将商品的基本价格设置为 3 美元,但它与我的数学(java)的其余部分混淆了
- php - 每次使用不同的 POST 输入通过 PHP 从数据库中进行选择
- antivirus - Bitdefender 将我的 C++ 文件检测为病毒
- python - Django 序列化器数据集上下文
- laravel - Laravel - 调用未定义的方法 Illuminate\Notifications\Messages\MailMessage::to()
- python-3.x - Python - collections.abc 子类的现有“标准库”测试用例
- blazor - 如何将 Blazor 组件呈现为 HTML 字符串
- android - Gradle: com.android.support:support-v4:xx.xx 不再支持 AndroidX