使用 Elastic Stack 来分析奥运数据(一)

1,293 阅读9分钟

最近冬奥会在中国北京顺利举行。这是一件举国高兴的事。在历届都有许多的奥运数据,我们是否可以使用 Elastic Stack 来分析这些数据,并为我国的体育事业提供一些洞察呢?

最近,孩子学校布置了一个寒假的科技信息作用。内容如下:

1、使用网络及其他方式,完成数据搜集,收集2014、2018、2022三届冬奥会的相关数据,例如举办国家、城市、日期、吉祥物、获得前20(以金牌计)的国家,金、银、铜牌数量等相关信息,同学可以根据爱好,选择五种自己喜爱的运动,并查找此三届冬奥会中,中国、美国、俄罗斯、日本、德国在此五个项目上的奖牌情况。同学可以根据自己的思考,搜集更多的相关数据或信息。

同学思考:(1)如何才能保证自己所搜集数据的准确性。

                 (2)如何才能通过整理、分析以上数据,从我国运动员的获奖数据等信息中,对我国青少年冰雪体育教育提出自己的小建议。

2、在获得以上数据后,同学可以根据需要,把它们填写在EXCEL等数据处理软件中。可以自主决定是放在一个文件中,还是放在多个文件中,是整理在一个工作表中,还是放置在不同的工作表中。

3、对数据进行整理后,可以用图表等方式形象表达出来,并根据数据表、图表,撰写自己对于我国青少年冰雪体育教育提出自己的见解,如发现的问题,造成问题的原因,你的解决方案等。

首先,我得申明,我不是什么 Excel 表格高手,我也不知道该如何来使用 Excel 表来完成上面的工作。我倒是觉得使用 Elastic Stack 能完美地解决这个问题。

在今天的展示中,我将使用 Elastic Stack 8.0 来解决这个问题,尽管其他版本的 Elastic Stack 没有多大区别。在 Elastic Stack 8.0 中,一个最大的变化就是 Index patterns 界面变为 Data views。

准备数据

我在网上搜了很多的数据。目前我觉得最为完整的数据就是在 Kaggle 上的数据,虽然它并没有最近两届的数据。它的数据是在2018年进行整理的。在百度上,有许多的数据,有些是金牌排行榜,有些是一些国家的分析图,但是总体来说,还没有一个完成的数据。如果谁有找到可以完整的下载的数据,请告诉我。

在 Kaggle 网站上,我可以下载这样的两个文件:

  • athlete_events.csv
  • noc_regions.csv

在 athlete_events.csv 文件中,我们可以看到如下的内容:

athlete_events.csv



1.  "ID","Name","Sex","Age","Height","Weight","Team","NOC","Games","Year","Season","City","Sport","Event","Medal"
2.  "1","A Dijiang","M",24,180,80,"China","CHN","1992 Summer",1992,"Summer","Barcelona","Basketball","Basketball Men's Basketball",NA
3.  "2","A Lamusi","M",23,170,60,"China","CHN","2012 Summer",2012,"Summer","London","Judo","Judo Men's Extra-Lightweight",NA
4.  "3","Gunnar Nielsen Aaby","M",24,NA,NA,"Denmark","DEN","1920 Summer",1920,"Summer","Antwerpen","Football","Football Men's Football",NA


在这个表格中,我们可以查看到一个运行员的名字,性别,年龄,身高,体重,团队,代表的国家,年份,所参加的是冬季奥运会或者是夏季奥运会,参数的种类,获得奖牌的情况。

在 noc_regions.csv 中,我们可以看到如下的内容:

noc_regions.csv



1.  NOC,region,notes
2.  AFG,Afghanistan,
3.  AHO,Curacao,Netherlands Antilles
4.  ALB,Albania,
5.  ALG,Algeria,
6.  AND,Andorra,
7.  ANG,Angola,
8.  ANT,Antigua,Antigua and Barbuda
9.  ANZ,Australia,Australasia
10.  ARG,Argentina,
11.  ARM,Armenia,
12.  ARU,Aruba,
13.  ASA,American Samoa,
14.  AUS,Australia,


显然这个表格,可以办个我们查找那些缩写的字母,比如 AFG 所代表的国家名称。在我们的设计中,我们使用 ingest pipeline 来把这个数据表格里的国家名称丰富到最终的表格中去,因为我们大多数人熟悉的还是这个国家的名称,而不是 AND,ARG 等这样的缩写所代表的国家的名称。

创建 regions 索引

首先,我们来摄入 noc_regions.csv 文件。创建一个叫做 regions 的索引:

 我们选择下载的  noc_regions.csv 文件。点击 Import:

 我们可以点击 Advanced 来查看这个 regions 索引的 mapping。如果我们不太满意这个 mapping,我们可以进行修改。目前我们不做任何的调整。点击 Import:

上面显示我们已经成功地摄入了230个文档。 

创建丰富数据策略

由于我们想把 regions 索引里的 region 丰富到最终的数据中,我们必须创建一个 enrich policy:

有关 enrich policy 方面的知识,请阅读我之前的文章 “Elasticsearch:如何使用 Elasticsearch ingest 节点来丰富日志和指标”。我们定义如下的 enrich policy:



1.  PUT /_enrich/policy/enrich-region-policy
2.  {
3.    "match": {
4.      "indices": "regions",
5.      "match_field": "NOC",
6.      "enrich_fields": [
7.        "region"
8.      ]
9.    }
10.  }


我们使用 execute enrich policy API 为该策略创建 enrich 索引: 

PUT /_enrich/policy/enrich-region-policy/_execute

我们到目前为止已经成功地创建了一个丰富策略。这个策略将在下面摄入运动员信息时将会被用到。

清洗 althelete 事件数据

虽然,我们也可以直接使用 Kibana 来摄入 athlete_events.csv,但是在进行这个之前,我们还是先用 python 来对数据进行清洗一下。我们可以使用 jupyter 来帮助我们处理数据:



1.  import pandas as pd

3.  df = pd.read_csv('./athlete_events.csv')

5.  df.head()


在上面,我们使用 panda 来读入 athlete_event.csv。我们发现有271116个数据。



1.  nan_values = df.isna()
2.  nan_columns = nan_values.any()

4.  columns_with_nan = df.columns[nan_columns].tolist()
5.  print(columns_with_nan)


我们查一查到底哪一些项不是数值的项:

 也就是说在上面的 Age,Height,Weight 及 Medal 中含有非数值项。



1.  df[['Age','Height','Weight']] = df[['Age','Height','Weight']].fillna(0)

3.  df.Medal = df.Medal.fillna('None')

5.  df.Age = df.Age.astype(int)


我们把非数值像填为0,在 Medal 项里,如果没有数值,我们填写 “None"。

 最后,我们把清洗过的文件的名称叫做 cleaned_olympic.csv,并保存在当前的文件目录下。在下面的操作,我们将以这个文件来进行操作,而不是之前的 althlete_events.csv 文件。



1.  $ pwd
2.  /Users/liuxg/data/olympic
3.  $ ls 
4.  archive (13).zip    cleaned_olympic.csv noc_regions.csv
5.  athlete_events.csv  ingest.py           olympic.ipynb


摄入运动员资料

在这一步,我们将把刚刚生成的 cleaned_olympic.csv 摄入到 Elasticsearch 中。我们打开这个文件,并为这个文件添加一个 header:

id,name,sex,age,height,weight,team,NOC,game,year,season,city,sports,event,medal

这样 cleaned_olympic.csv 文件就像这样的:

 有了这个 header,我们接下来就来使用 Kibana 来摄入这个文件:

我们选择 cleaned_olympic.csv 文件作为输入文件:

我们选择 olympic 作为索引的名称。接下来,我们需要调整一下这个索引的 mapping:

我们把 event 设置为 keyword 是为了之后来统计奖牌牌的数量。我们的奖牌牌数量不能按照 sports 来进行统计,这是因为团体赛中,一个奖牌可能是由很多的运动员公共拥有的,而且对于男女团队来说,同样的运动,sports 都是一样的。我们只有统计 event 才能真正得到奖牌的数量。另外 year 我们先定义为 keyword。我们需要使用 UTC 来设置其时间值。在默认的情况下,它使用当前机器的时域(time zone)来进行转换。

我们接下来修改右边的 pipeline:

 我们添加如下的一个 date processor:

 1.      {
2.        "date" : {
3.          "field" : "year",
4.          "target_field" : "@timestamp",
5.          "formats" : ["yyyy"],
6.          "timezone" : "UTC"
7.        }
8.      }

我们添加一个叫做 @timestamp 的字段。它的值由 year 这个字段转换而来。我们设置其时间为 UTC 时间。

接下来,我们需要需要运用之前配置的丰富策略。我们想把 region 这个字段也添加到摄入的索引中。我们需要添加如下的 enrich processor:

 1.      {
2.        "enrich": {
3.          "policy_name": "enrich-region-policy",
4.          "field": "NOC",
5.          "target_field": "region1",
6.          "max_matches": "1"
7.        }
8.      }

 上面的这个 processor 的作用是:当 NOC 是 match 的话,那么,在 regions 这个索引里的 region 见会被自动添加到索引中。经过这个 enrich processor 的处理后,会有一个叫做 region1.region 的字段。我们接下来想把这个字段的值重新命令为 region 字段,这样更便于我们分析数据。我们添加如下的 rename processor:

 1.      {
2.        "rename": {
3.          "if": "ctx.containsKey('region1')",
4.          "field": "region1.region",
5.          "target_field": "region"
6.        }
7.      }

 经过这样的处理后,我们可以删除之前的 region1 字段:

 1.      {
2.        "remove": {
3.          "if": "ctx.containsKey('region1')",
4.          "field": "region1"
5.        }
6.      } 

 到目前为止,我们的 mapping  及 pipeline 都已经设置好了。我们点击上面的 Import 按钮:

上面显示,我们已经成功地摄入了 271116 个文档。这也是截止数据被整理时候的所有的运动员的资料。我们点击 View index in Discover。

 我们能看到所有的数据。 我们可以看到一个叫做 region 的字段,它来自于 regions 索引,如果有相应匹配的 NOC 的话。同时我们看见了一个叫做 @timestamp 的字段。这个是由 date processor 而来的。

在上面的 Discover 界面中,尽管我们看到了一个叫做 @timestamp 的字段,但是它不是一时域的形式来显示的。我们需要进行调整。

我们来删除已经创建的 olympic data view。我们创建一个新的 data view:

这样我们就创建了一个崭新的 olympic data view。我们再次回到 Discover j界面,并重新选择这个索引:

在上面的视图中,我们可以清楚地看到自奥运会以来到 2016 年截至的所有的运动员的资料。为了验证数据的正确性,我们来搜索一下参加2008年运动员的总人数:

从上面,我们可以清楚地看出来参加2008年北京运动会的所有运动员人数为13602个。

好了今天的展示就到这里。我们在这篇文章中,详细地介绍了如何把一个奥运会的 csv 文件摄入到 Elasticsearch 中。我们将在下一篇文章 “使用 Elastic Stack 来分析奥运数据(二)” 中,详细地介绍如何可视化这些数据。