2022-08-19

求索集 - 九 小潘小潘...

求索集 - 九 小潘小潘告诉我, 拜仁慕尼黑还有多少德国球员

2022-23赛季, 欧洲各大联赛重燃战火, 今年的转会市场依然火爆, 切尔西完全没有因为阿布的离去影响转会, 1.87亿欧元转会投入冠绝欧洲.

2022欧洲转会榜

图片源自懂球帝

1、切尔西 1.87亿欧元

2、巴萨 1.53亿欧元

3、拜仁 1.38亿欧元

4、阿森纳 1.32亿欧元

5、西汉姆联 1.24亿欧元

6、曼城 1.22亿欧元

7、热刺 1.2亿欧元

8、诺丁汉森林 1.19亿欧元

9、巴黎 1.07亿欧元

10、利兹联 1.06亿欧元

不出意外, 第四一定是我厂…

这里值得注意的是, 德甲巨人, 欧洲王者, 南大王, 真伦敦之王拜仁慕尼黑花了1.38亿. 不过问题来了, 大手笔引进了荷兰的德里赫特和赫拉芬贝赫, 还有塞内加尔的马内, 德国球迷难免就含糊了, 作为德国国家队的摇篮, 拜仁慕尼黑还有多少德国球员? 都是外援了, 德国国家队可怎么办? 要知道今年可是世界杯年, 多少德国球迷都备好了巴伐利亚啤酒和大香肠等着看德意志军团一雪2018世界杯的耻辱, 重铸辉煌呢.

正好数据分析学到这里了, 咱们就请小潘告诉我们, 拜仁还剩几个德国本土球员吧.

这里的小潘不是大郎的老婆, 西门大官人的相好, 打虎英雄的仇敌, 我们的金莲女士. 小潘是我给Pandas起的外号. Pandas, Python的数据分析库, 大名鼎鼎的数据分析工具, 数据分析师不可不会的基础工具. 小潘, 我们出发!

没学数据分析我们都能知道, 数据分析的一般流程是 明确问题, 数据获取, 数据整理, 数据探索, 分析结果和数据展示. 当然数据分析的核心价值还有最后一步, 就是基于分析结果的预测模型.

好, 下面就开始数据获取和数据整理. 我们使用JupyterLab来完成:

首先, 导入需要的包

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import numpy as np
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import matplotlib.pyplot as plt

# windows解决中文乱码
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签

# mac解决中文乱码
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']

plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号

Pandas用来进行数据分析, Numpy是Python最棒的数学包, 主要是处理数据用. matplotlib 主要是用来画图

下面开始导入数据. 我在导入数据时发现一个问题, 就是如果让Python直接读拜仁慕内黑百度百科的页面, 就会报错, 错的一塌糊涂. 后来只好把网页保存到了本地, 再读取就正常了.

1
2
3
4
tables = pd.read_html('examples/BayerMunich.html')
bayermunich = tables[0]
bayermunich = bayermunich[:-1]
bayermunich

这里我得说, 这Pandas从网页里抓表格的能力太NB了, 比之前我写爬虫用的BeautifulSoup简单的多得多, 直接tables[0] 就能把页面里的第一张表, 也就是拜仁阵容表给抓出来, 而BeautifulSoup还得靠抓取HTML标记, 看来以后做羞羞哒事情简单多了呢…

现在拜仁慕尼黑就以Numpy的DataFrame格式保存好了:

号码 姓名 协会 位置 生日 合同期限 身高/cm
0 1 曼努埃尔·诺伊尔 德国 门将 1986.03.27 2024.06.30 193
1 2 达约·于帕梅卡诺 法国/几内亚比绍 后卫 1998.10.27 2026.06.30 186
2 4 马泰斯·德利赫特 荷兰 后卫 1999.08.12 2027.06.30 189
3 5 邦雅曼·帕瓦尔 法国 后卫 1996.03.28 2024.06.30 186
4 6 约书亚·基米希 德国 中场 1995.02.08 2025.06.30 176
5 7 塞尔日·格纳布里 德国/科特迪瓦 中场 1995.07.14 2026.06.30 175
6 8 莱昂·戈列茨卡 德国 中场 1995.02.06 2026.06.30 189
7 10 勒鲁瓦·萨内 德国/法国 中场 1996.01.11 2025.06.30 184
8 11 金斯利·科曼 法国/瓜德罗普 前锋 1996.06.13 2027.06.30 178
9 13 埃里克·马克西姆·舒波-莫廷 喀麦隆/德国 前锋 1989.03.23 2023.06.30 191
10 14 保罗·万纳 德国/奥地利 中场 2005.12.23 2027.06.30 185
11 17 萨迪奥·马内 塞内加尔 前锋 1992.04.10 2025.06.30 175
12 18 马塞尔·萨比策 奥地利 中场 1994.03.17 2025.06.30 177
13 19 阿方索·戴维斯 加拿大/利比里亚 后卫 2000.11.02 2025.06.30 181
14 20 布纳·萨尔 塞内加尔/法国 后卫 1992.01.31 2024.06.30 177
15 21 卢卡斯·埃尔南德斯 法国/西班牙 后卫 1996.02.14 2024.06.30 182
16 25 托马斯·穆勒 德国 前锋 1989.09.13 2024.06.30 186
17 26 斯文·乌尔赖希 德国 门将 1988.08.03 2022.06.30 192
18 28 加布里埃尔·维多维奇 克罗地亚/德国 中场 2003.12.01 2025.06.30 180
19 32 约书亚·齐尔克泽 荷兰/尼日利亚 前锋 2001.05.22 2023.06.30 193
20 35 约翰内斯·申克 德国 门将 2003.01.13 2024.06.30 191
21 38 赖安·赫拉芬贝尔赫 荷兰/苏里南 中场 2002.05.16 2027.06.30 190
22 39 马蒂斯·特尔 法国 前锋 2005.04.27 2027.06.30 183
23 40 努赛尔·马兹拉维 摩洛哥/荷兰 后卫 1997.11.14 2026.06.30 183
24 42 贾马尔·穆夏拉 德国/英格兰 中场 2003.02.26 2026.06.30 183
25 44 约瑟普·斯坦尼西奇 克罗地亚/德国 后卫 2000.04.20 2025.06.30 186

Numpy很贴心的把索引也加上了, 我们可以一眼看出, 拜仁慕内黑一线队目前有26名球员.

下面开始数据整理. 我们首先把双国籍球员给找出来:

1
bayermunich[bayermunich['协会'].str.contains('/')]
号码 姓名 协会 位置 生日 合同期限 身高/cm
1 2 达约·于帕梅卡诺 法国/几内亚比绍 后卫 1998.10.27 2026.06.30 186
5 7 塞尔日·格纳布里 德国/科特迪瓦 中场 1995.07.14 2026.06.30 175
7 10 勒鲁瓦·萨内 德国/法国 中场 1996.01.11 2025.06.30 184
8 11 金斯利·科曼 法国/瓜德罗普 前锋 1996.06.13 2027.06.30 178
9 13 埃里克·马克西姆·舒波-莫廷 喀麦隆/德国 前锋 1989.03.23 2023.06.30 191
10 14 保罗·万纳 德国/奥地利 中场 2005.12.23 2027.06.30 185
13 19 阿方索·戴维斯 加拿大/利比里亚 后卫 2000.11.02 2025.06.30 181
14 20 布纳·萨尔 塞内加尔/法国 后卫 1992.01.31 2024.06.30 177
15 21 卢卡斯·埃尔南德斯 法国/西班牙 后卫 1996.02.14 2024.06.30 182
18 28 加布里埃尔·维多维奇 克罗地亚/德国 中场 2003.12.01 2025.06.30 180
19 32 约书亚·齐尔克泽 荷兰/尼日利亚 前锋 2001.05.22 2023.06.30 193
21 38 赖安·赫拉芬贝尔赫 荷兰/苏里南 中场 2002.05.16 2027.06.30 190
23 40 努赛尔·马兹拉维 摩洛哥/荷兰 后卫 1997.11.14 2026.06.30 183
24 42 贾马尔·穆夏拉 德国/英格兰 中场 2003.02.26 2026.06.30 183
25 44 约瑟普·斯坦尼西奇 克罗地亚/德国 后卫 2000.04.20 2025.06.30 186
1
bayermunich[bayermunich['协会'].str.contains('/')].count()

会看到有15人拥有双国籍:

1
2
3
4
5
6
7
8
号码       15
姓名 15
协会 15
位置 15
生日 15
合同期限 15
身高/cm 15
dtype: int64

下面我们就得开始处理这些双国籍了. 拜仁慕内黑百度百科的页面确实做得很好, 凡是标注双国籍的, 编写者会把他效力的国家写在前面, 比如舒波莫廷, 喀麦隆德国双国籍, 但是他为喀麦隆效力. 但是由于编写者没有明确说这样的规则, 本着严谨的态度, 我还是挨个搜索并确定了每位双国籍的球员效力的国家队, 于是就有了这样一个对照表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
nation_convertor = {
'法国/几内亚比绍': '法国',
'德国/科特迪瓦': '德国',
'德国/法国': '德国',
'法国/瓜德罗普': '法国',
'喀麦隆/德国': '喀麦隆',
'德国/奥地利': '德国',
'加拿大/利比里亚': '加拿大',
'塞内加尔/法国': '塞内加尔',
'法国/西班牙': '法国',
'法国/科特迪瓦': '法国',
'克罗地亚/德国': '克罗地亚',
'荷兰/尼日利亚': '荷兰',
'荷兰/苏里南': '荷兰',
'摩洛哥/荷兰': '摩洛哥',
'德国/英格兰': '德国',
'克罗地亚/德国':'克罗地亚'
}

如果有明确规则说/前面的是此球员的效力国家队, 那么只需要用正则表达式就能处理了, 当然了, 正则表达式我不会…

下面就可以开始替换协会里双国籍的情况了:

1
bayermunich = bayermunich.replace(nation_convertor.keys(), nation_convertor.values())

结果是

号码 姓名 协会 位置 生日 合同期限 身高/cm
0 1 曼努埃尔·诺伊尔 德国 门将 1986.03.27 2024.06.30 193
1 2 达约·于帕梅卡诺 法国 后卫 1998.10.27 2026.06.30 186
2 4 马泰斯·德利赫特 荷兰 后卫 1999.08.12 2027.06.30 189
3 5 邦雅曼·帕瓦尔 法国 后卫 1996.03.28 2024.06.30 186
4 6 约书亚·基米希 德国 中场 1995.02.08 2025.06.30 176
5 7 塞尔日·格纳布里 德国 中场 1995.07.14 2026.06.30 175
6 8 莱昂·戈列茨卡 德国 中场 1995.02.06 2026.06.30 189
7 10 勒鲁瓦·萨内 德国 中场 1996.01.11 2025.06.30 184
8 11 金斯利·科曼 法国 前锋 1996.06.13 2027.06.30 178
9 13 埃里克·马克西姆·舒波-莫廷 喀麦隆 前锋 1989.03.23 2023.06.30 191
10 14 保罗·万纳 德国 中场 2005.12.23 2027.06.30 185
11 17 萨迪奥·马内 塞内加尔 前锋 1992.04.10 2025.06.30 175
12 18 马塞尔·萨比策 奥地利 中场 1994.03.17 2025.06.30 177
13 19 阿方索·戴维斯 加拿大 后卫 2000.11.02 2025.06.30 181
14 20 布纳·萨尔 塞内加尔 后卫 1992.01.31 2024.06.30 177
15 21 卢卡斯·埃尔南德斯 法国 后卫 1996.02.14 2024.06.30 182
16 25 托马斯·穆勒 德国 前锋 1989.09.13 2024.06.30 186
17 26 斯文·乌尔赖希 德国 门将 1988.08.03 2022.06.30 192
18 28 加布里埃尔·维多维奇 克罗地亚 中场 2003.12.01 2025.06.30 180
19 32 约书亚·齐尔克泽 荷兰 前锋 2001.05.22 2023.06.30 193
20 35 约翰内斯·申克 德国 门将 2003.01.13 2024.06.30 191
21 38 赖安·赫拉芬贝尔赫 荷兰 中场 2002.05.16 2027.06.30 190
22 39 马蒂斯·特尔 法国 前锋 2005.04.27 2027.06.30 183
23 40 努赛尔·马兹拉维 摩洛哥 后卫 1997.11.14 2026.06.30 183
24 42 贾马尔·穆夏拉 德国 中场 2003.02.26 2026.06.30 183
25 44 约瑟普·斯坦尼西奇 克罗地亚 后卫 2000.04.20 2025.06.30 186

好了, 数据到此为止就处理完毕了. 这应该是数据清洗里最简单的情况了.

下面, 我们看看拜仁慕尼黑还有多少德国球员:

1
bayermunich[bayermunich['协会']=='德国']
号码 姓名 协会 位置 生日 合同期限 身高/cm
0 1 曼努埃尔·诺伊尔 德国 门将 1986.03.27 2024.06.30 193
4 6 约书亚·基米希 德国 中场 1995.02.08 2025.06.30 176
5 7 塞尔日·格纳布里 德国 中场 1995.07.14 2026.06.30 175
6 8 莱昂·戈列茨卡 德国 中场 1995.02.06 2026.06.30 189
7 10 勒鲁瓦·萨内 德国 中场 1996.01.11 2025.06.30 184
10 14 保罗·万纳 德国 中场 2005.12.23 2027.06.30 185
16 25 托马斯·穆勒 德国 前锋 1989.09.13 2024.06.30 186
17 26 斯文·乌尔赖希 德国 门将 1988.08.03 2022.06.30 192
20 35 约翰内斯·申克 德国 门将 2003.01.13 2024.06.30 191
24 42 贾马尔·穆夏拉 德国 中场 2003.02.26 2026.06.30 183
1
2
bayermunich_nation = bayermunich.groupby(['协会']).count().sort_values('号码')
bayermunich_nation
号码 姓名 位置 生日 合同期限 身高/cm
协会
加拿大 1 1 1 1 1 1
喀麦隆 1 1 1 1 1 1
奥地利 1 1 1 1 1 1
摩洛哥 1 1 1 1 1 1
克罗地亚 2 2 2 2 2 2
塞内加尔 2 2 2 2 2 2
荷兰 3 3 3 3 3 3
法国 5 5 5 5 5 5
德国 10 10 10 10 10 10

结果出来了, 拜仁慕内黑 26名一线队球员, 有10名德国本土球员, 在五大联赛里应该就算本土球员不少的了. 而这里诺伊尔, 基米希, 格纳布里, 穆勒应该都是国家队绝对主力, 格列茨卡应该是重要替换球员, 穆夏拉则是绝对的希望之星, 至于萨内, 一言难尽, 一言难尽.

最后就是数据展示, 这也是Python-Pandas-matplotlib的强项:

1
2
3
4
5
6
7
plt.figure(figsize=(10,10))
plt.pie(bayermunich_nation['号码'],
labels = bayermunich_nation.index,
autopct= '%.2f%%',
)
plt.title('拜仁慕尼黑球员国籍示意图')
plt.show()

img