“Spark全栈:通过报表探索数据”的版本间的差异

来自CloudWiki
跳转至: 导航搜索
调查飞机(实体)
 
(未显示同一用户的1个中间版本)
第126行: 第126行:
  
 
[[文件:bd21081409.png|600px]]
 
[[文件:bd21081409.png|600px]]
 +
 +
===在飞机页面上添加搜索===
 +
/airplanes页面是一个提供飞机数据搜索的好地方。要实现搜索功能,首先需要通过PySpark把飞机数据写入Elasticsearch:
 +
 +
===创建飞机制造商的条形图===
 +
 +
现在有地方可以放置图表了,让我们开始做图表吧!
 +
继续执行脚本ch06/analyze_airplanes.py,我们把图表要用的数据存储到Mongo中:
 +
 +
再接下来就和第5章中制作条形图类似了。我们在report_flask.py中增加一个控制器,从Mongo中读取表的数据,以JSON格式返回:
 +
 +
我们修改all_airplanes.html模板来调用airplane.js,用它来画图表。
 +
 +
[[文件:bd21081410.png|600px]]
 +
 +
===对飞机制造商条形图进行迭代===
 +
等一下,不对劲!还记得吗?我们说过迭代是必不可少的。我们需要对图表进行一番调试,并从图表中推断出我们还要做什么。为什么条形图的条这么细?为什么都紧紧靠在最左边?回忆一下,我们是根据飞机总数的降序来存储数据的:
 +
 +
[[文件:bd21081411.png|600px]]
 +
 +
===实体解析:新一轮图表迭代===
 +
然而,此时的图表还有一个问题——列名有重复,导致空客、麦克唐纳·道格拉斯公司(McDonnel Douglas,简称麦道)、巴西航空工业公司(Embraer)等制造商的数值不准确。我们又要迭代了!这次我们要使用实体解析。
 +
 +
====30秒实体解析====
 +
 +
我们遇到的问题是同一制造商的名字在飞机注册中使用了多种形式。处理这一问题就叫作实体解析,Lise Getoor和Ashwin Machanavajjhala写的实体解析指南中把它定义为“识别并合并真实世界中同一对象的多种表现形式”。实体解析就是把“空中客车(AIRBUS)”和“空中客车公司(AIRBUS INDUSTRIE)”识别为同一个主体的过程。
 +
 +
====在PySpark中解析制造商====
 +
首先查看飞机表中制造商字段的不同值。我们可以使用SQL语句SELECT DISTINCT (Manufacturer) AS Manufacturer并以ORDER BY Manufacturer子句进行排序,然后就会看到近似的记录都靠在一起。接下来,我们就只需要以左对齐的方式打印数据,看看我们得到了什么!
 +
====整洁:实体解析的作用====
 +
原始数据始终是“脏”的。当你深入其中,操作数据、查看数据原始的样子、把它呈现在网页上的表格和图表中,或是提供搜索它的功能时,原始数据的问题就出现了。在操作数据中解决这些问题可以让你清楚地看到真实的趋势。和对于可视化的好处一样,对模型也有好处。这种“整洁”可以让你有效地在数据价值金字塔的下一层构建统计学模型:预测(prediction)。

2021年8月14日 (六) 15:01的最新版本

前言

接下来就是我们的第三个敏捷开发冲刺周期了,我们要把图表页面进一步开发为完整的报表。在这一步骤中,我们会给图表增添交互性,把静态页面变成动态页面,通过链接的网络、表和图表的相关实体使得数据可供探索。这些都是数据价值金字塔中报表阶段的特性

Bd21081401.png

本章的示例代码在Agile_Data_Code_2/tree/master/ch06中

git clone https://github.con/rjurney/Agile_Data_Code_2.git

提取航空公司为实体

为了构建报表,我们需要组合数据集的各种视图。构建这些视图对应的工作是枚举实体。我们在上一章中创建了实体“飞机”,它会是我们继续创建其他实体及建立实体间的关联关系以构建报表的基础。如上一章所述,在我们开始创建数据的视图之前,我们需要构建一个网页来展示图表与表格。那么下面我们就来创建一个新的实体“航空公司”,并且为每家航空公司提供一个页面。

我们从收集一家特定航空公司所有飞机的机尾编号入手。每个商业航班都是由某一家航空公司运营的,各个航空公司又拥有各自的机队,以及基地机场设施和人员,这些都是航空公司业务的核心资产。我们已经为每架飞机创建了页面,因此我们可以利用这一数据来创建每个航空公司的全部机尾编号列表。

使用PySpark把航空公司定义为飞机的分组

我们从准备每个航空公司的飞机机尾编号列表入手,代码如ch06/ extract_airlines.py文件所展示的。这会成为航空公司页面的基础:

# Load the on-time parquet file
on_time_dataframe = spark.read.parquet('data/on_time_performance.parquet')

# The first step is easily expressed as SQL: get all unique tail numbers for each airline
on_time_dataframe.registerTempTable("on_time_performance")
carrier_airplane = spark.sql(
  "SELECT DISTINCT Carrier, TailNum FROM on_time_performance"
  )

# Now we need to store a sorted group for each Carrier, along with a fleet count
airplanes_per_carrier = carrier_airplane.rdd\
  .map(lambda nameTuple: (nameTuple[0], [nameTuple[1]]))\
  .reduceByKey(lambda a, b: a + b)\
  .map(lambda tuple:
      {
        'Carrier': tuple[0], 
        'TailNumbers': sorted(
          filter(
            lambda x: x is not None and x != '', tuple[1] # empty string tail numbers were getting through
            )
          ),
        'FleetCount': len(tuple[1])
      }
    )
airplanes_per_carrier.count() # 14

# Save to Mongo in the airplanes_per_carrier relation
import pymongo_spark
pymongo_spark.activate()
airplanes_per_carrier.saveToMongoDB(
  'mongodb://localhost:27017/agile_data_science.airplanes_per_carrier'
)

在MongoDB中查询航空公司数据

下面来验证数据已经在Mongo中:db.airplanes_per_carrier.find()

在Flask中构建航空公司页面

我们得到了一个简易的航空公司页面,列出了航空公司的机队(见图6-2)。不用担心,我们稍后还会再装点这个页面的。在交付好产品之前,交付一些难看的东西也是很有必要的!

Bd21081402.png

添加回到航空公司页面的链接

创建了航空公司这个实体的页面之后,我们要为先前创建的飞机页面添加跳转回航空公司页面的链接,还有第5章中创建的搜索页面和航班页面也需要添加。我们可以修改飞机、航班及搜索页面的模板来实现这个功能。

创建一个包括所有航空公司的主页

但是谁记得住那些航空公司代码呢?(好吧,我能记住)我们需要给用户一个入口,所以我们要创建一个主页,列出在美国运营的所有航空公司。

我们同时把这个页面设置为本应用的默认首页index.html:

Bd21081403.png

整理半结构化数据的本体关系

现在我们可以尽情探索航空公司、飞机、航班数据了!这是一件大事,对吧?可能算不上,但这是一个好的开始。让我们进一步扩展这个功能,给航班页面里面的飞机和航空公司加上链接。

现在我们可以在查看航班时看到飞机和航空公司的信息——它们的属性及其之间的关系(见图6-4)。这样的结构非常清晰,并且是推荐的一种简单的形式。

Bd21081404.png

我们正在做的事情可以被描述为创建半结构化数据间交互式的本体关系。把我们的流程围绕着构建这一结构关系拆开,对我们来说有几个作用。首先,它创建了一小批工作任务(每个实体一个),可以有效地进入敏捷开发的冲刺。这实现了一种数据敏捷性,并可以将我们的应用程序扩展为更适合浏览的状态。而这反过来又让用户可以自由单击并探索数据集,从而将团队与实际数据的情况连接起来。正如你现在所知,这是敏捷数据科学的一个主题。

改进航空公司页面

我们有了航空公司的页面,下面就给它加上一些多媒体内容,包括文本和图片。我们首先从主数据集中获取航空公司代码列表.


给航空公司代码加上名称

为了给航空公司链接更多数据,我们需要获取每个航空公司代码对应的航空公司名字。这一数据可以在第5章中从OpenFlights(http://openflights.org/data.html)上下载的航空公司数据库中找到。让我们看一下airlines.dat,这里我们已经把它重命名为airlines.csv:

Bd21081405.png

我们仅保留数据中的航空公司名字和两个字母的航空公司代码,然后把它和准点情况数据集中去重的航空公司代码做表连接:

Bd21081406.png

整合维基百科内容

现在我们获取了航空公司的名字,我们可以通过维基百科获取各家航空公司的各种信息,比如简介、标志、公司官网!要这么做的话,我们要使用Python的wikipedia(https://pypi.python.org/pypi/wikipedia/)包,它封装了MediaWiki API(https://www.mediawiki.org/wiki/API:Main_page)

把扩充过的航空公司表发布到MongoDB

现在我们要把扩充过的航空公司表放到先前创建的航空公司网页上。为了实现这个目标,我们需要把新的数据存到Mongo中。由于我们已经有了准备好的JSON文件,因此可以使用mongoimport命令直接把它读取到Mongo中:

在网页上扩充航空公司信息

我们已经扩充了Mongo中航空公司的记录,现在要修改Flask控制器为/airline 页面增加这些数据。如ch06/web/report_flask.py所示:

经过一番优化,我们得到了一个大大改善的航空公司页面(见图6-5)。这一修改意义何在?虽然你的数据可能不会这么轻易地使用维基百科这样的公共数据集进行扩充,但此示例展示了如何合并来自不同来源的数据(不管是私有数据还是公共数据)来组成更好的实体页面。

Bd21081407.png

调查飞机(实体)

在第5章中,我们发现了一些有意思的数据,现在我们再回头看看。让我们从在中间数据集中存储扩充的飞机数据入手

我们先以提出问题开始我们的分析:波音公司(Boeing,简称波音)和空中客车公司(Airbus,简称空客),这两家制造商在美国的商业机队.

Bd21081408.png

SQL嵌套查询vs.数据流编程

这个例子可以很好地解释SQL嵌套查询与数据流编程之间的区别。SQL是声明式的,使用SQL你只需要定义你要什么,而不用管SQL会如何做。而命令式的数据流编程则需要一步一步计算连接的数据并组合成数据流。

不使用嵌套查询的数据流编程

Spark SQL直到2.0版本才支持了嵌套查询。有了各个制造商的飞机数量,我们需要求出总的飞机数量,与已有的各制造商总数连接,然后用各制造商总数除以总飞机数量。我们需要重复使用前面例子中求得的表manufacturer_counts

Spark SQL中的子查询

子查询很好用,使用子查询计算飞机制造商的份额百分比很简单:

创建飞机主页

现在我想以图表的形式在网页上查看这些数据,这意味着我们要找个地方放置图表。是时候创建/airplanes作为飞机主页了,在这个页面上可以对机队进行整体分析。

我们先给/airplanes创建Flask控制器。如ch06/web/report_flask.py所示,我们直接从Mongo中读取数据,并将数据传给模板all_airplanes.html:

Bd21081409.png

在飞机页面上添加搜索

/airplanes页面是一个提供飞机数据搜索的好地方。要实现搜索功能,首先需要通过PySpark把飞机数据写入Elasticsearch:

创建飞机制造商的条形图

现在有地方可以放置图表了,让我们开始做图表吧! 继续执行脚本ch06/analyze_airplanes.py,我们把图表要用的数据存储到Mongo中:

再接下来就和第5章中制作条形图类似了。我们在report_flask.py中增加一个控制器,从Mongo中读取表的数据,以JSON格式返回:

我们修改all_airplanes.html模板来调用airplane.js,用它来画图表。

600px

对飞机制造商条形图进行迭代

等一下,不对劲!还记得吗?我们说过迭代是必不可少的。我们需要对图表进行一番调试,并从图表中推断出我们还要做什么。为什么条形图的条这么细?为什么都紧紧靠在最左边?回忆一下,我们是根据飞机总数的降序来存储数据的:

600px

实体解析:新一轮图表迭代

然而,此时的图表还有一个问题——列名有重复,导致空客、麦克唐纳·道格拉斯公司(McDonnel Douglas,简称麦道)、巴西航空工业公司(Embraer)等制造商的数值不准确。我们又要迭代了!这次我们要使用实体解析。

30秒实体解析

我们遇到的问题是同一制造商的名字在飞机注册中使用了多种形式。处理这一问题就叫作实体解析,Lise Getoor和Ashwin Machanavajjhala写的实体解析指南中把它定义为“识别并合并真实世界中同一对象的多种表现形式”。实体解析就是把“空中客车(AIRBUS)”和“空中客车公司(AIRBUS INDUSTRIE)”识别为同一个主体的过程。

在PySpark中解析制造商

首先查看飞机表中制造商字段的不同值。我们可以使用SQL语句SELECT DISTINCT (Manufacturer) AS Manufacturer并以ORDER BY Manufacturer子句进行排序,然后就会看到近似的记录都靠在一起。接下来,我们就只需要以左对齐的方式打印数据,看看我们得到了什么!

整洁:实体解析的作用

原始数据始终是“脏”的。当你深入其中,操作数据、查看数据原始的样子、把它呈现在网页上的表格和图表中,或是提供搜索它的功能时,原始数据的问题就出现了。在操作数据中解决这些问题可以让你清楚地看到真实的趋势。和对于可视化的好处一样,对模型也有好处。这种“整洁”可以让你有效地在数据价值金字塔的下一层构建统计学模型:预测(prediction)。