译:Getting Started with Spark (in Python) Spark入门

待我学有所成,结发与蕊可好。@ 夏瑾墨

Getting Started with Spark (in Python)
Author:Benjamin Bengfort
Translator:Jooey Zhong


Hadoop 作为处理大数据集的分布式计算标准工具这就是为什么当你路过机场看到广告上的”大数据“的原因。它已经变成大数据的一种操作系统,提供一个让您能使用许多相对廉价的商品化硬件在以超级计算机的角色去进行计算的一个富集工具和技术的生态系统。来自谷歌在2003年和2004年的两个想法使Hadoop能实现:一个分布式存储框架(谷歌文件系统),这是在Hadoop中实现为HDFS和一个分布式计算的框架(MapReduce)。

这两个想法是过去十年中扩展分析,大型机器学习和其他大数据设备出现的主要驱动因素!然而,在技术方面,十年是一个非常长的时间,并且有一些众所周知的限制存在,特别是MapReduce。值得注意的是,MapReduce编程很困难。 你必须将Map和Reduce任务链接在多个步骤中,以便进行大多数分析。这导致了用于执行类似SQL的计算或机器学习的专用系统出现。更糟糕的是,MapReduce需要在每个步骤之间将数据序列化到磁盘,这意味MapReduce作业的I / O成本很高,使得交互式分析和迭代算法过于耗费;

为了解决这些问题,Hadoop已经转向用于计算的更一般的资源管理框架,YARN(又一资源协商器)。YARN实现了下一代MapReduce,但也允许应用程序利用分布式资源,而不必使用MapReduce进行计算。通过泛化集群的管理,研究已经转向分布式计算的概括,扩展了MapReduce中首先想到的想法。

Spark是第一个由这种转变产生,并迅速普及的快速的,通用的分布式计算模式。Spark扩展了MapReduce模型,以使用函数式编程范例支持更多类型的计算,它可以覆盖以前作为基于Hadoop构建的专用系统实现的大量工作流。Spark使用内存缓存来提高性能,因此,它足够快以允许交互式分析(就像你坐在Python解释器上,与集群交互)。缓存还提高了迭代算法的性能,这使得它非常适合数据理论任务,特别是机器学习。

在本文中,我们将首先讨论如何设置Spark以轻松地在本地机器或EC2(Elastic Compute Cloud弹性计算云)上的集群中启动轻松执行分析。然后,我们将在介绍性的层面探索Spark,了解Spark是什么,以及它是如何工作的(希望能激励进一步的探索)。在最后两节中,我们将开始在命令行上与Spark交互,然后演示如何使用Python编写Spark应用程序,并将其作为Spark作业提交到集群。

Spark设置
Spark很简单就能在你的机器上设置和运行。所有你真正需要做的是下载一个预构建的包,只要你有Java 6+和Python 2.6+,你可以简单地在Windows,Mac OS X和Linux上运行Spark二进制。确保Java程序在你的path路径上或者JAVAZ_HOME的环境变量有设置好。同样,python也必须设置好路径。

假设你已经安装好了Java和python:
1.访问Spark下载页面
2.选择最新的Spark版本(在撰写本文时为1.2.0),这是Hadoop 2.4的预构建包,并直接下载。
在这一点上,你必须弄清楚如何去处理取决于你的操作系统。Windows用户,请随时评论在评论部分设置的提示。

一般来说,我的建议是做如下(在POSIX操作系统上):
1.Unzip Spark

~$ tar -xzf spark-1.2.0-bin-hadoop2.4.tgz

2.将解压缩的目录移动到你的应用程序目录(例如在Windows上为C:\ Program Files,或在Linux上为/ opt /)。 你移动它到哪里并不重要,只要你有权限,可以运行二进制文件。我通常在/ srv /我的Ubuntu中安装Hadoop和相关工具,并将使用该目录这里说明。

~$ mv spark-1.2.0-bin-hadoop2.4 /srv/spark-1.2.0

3.将Spark的版本链接到spark目录。 这将允许您只需下载新的/较旧版本的Spark,并修改链接以管理Spark版本,而无需更改路径或环境变量。

~$ ln -s /srv/spark-1.2.0 /srv/spark

4.编辑您的BASH概要文件以将Spark添加到PATH中并设置SPARK_HOME环境变量。 这些助手将在命令行上帮助您。 在Ubuntu上,只需编辑〜/ .bash_profile或〜/ .profile文件,并添加以下内容:

export SPARK_HOME=/srv/spark
export PATH=$SPARK_HOME/bin:$PATH

5.在您发送个人资料(或简单重新启动终端)后,您现在应该可以在本地运行pyspark解释程序。 执行pyspark命令,您应该看到一个结果如下:

~$ pyspark
Python 2.7.8 (default, Dec  2 2014, 12:45:58)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.54)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Spark assembly has been built with Hive, including Datanucleus jars on classpath
Using Sparks default log4j profile: org/apache/spark/log4j-defaults.properties
[… snip …]
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  `_/
   /__ / .__/\_,_/_/ /_/\_\   version 1.2.0
      /_/

Using Python version 2.7.8 (default, Dec  2 2014 12:45:58)
SparkContext available as sc.
>>>

此时,Spark以“独立模式”安装并准备在本地机器上使用。 您可以在这里开发应用程序,并提交将在多进程/多线程模式下运行的Spark作业,或者您可以将此机器配置为集群的客户端(尽管这不推荐,因为驱动程序在Spark中扮演重要角色 ”作业“,并应与群集的其余部分位于同一网络中)。可能你在Spark开发之外在本地机器上做的最多的事情是使用spark-ec2脚本在Amazon的云上配置EC2 Spark集群。

最小化Spark的冗长信息
Minimizing the Verbosity of Spark

Spark(和PySpark)的执行可能非常冗长,许多INFO日志消息打印到屏幕上。 这在开发过程中尤其烦人,因为Python堆栈跟踪或print语句的输出可能丢失。 为了减少Spark的冗长,可以在 SPARKHOME/conflog4j SPARK_HOME / conf / log4j.properties.template文件的副本,删除“.template”扩展名。

~$ cp $SPARK_HOME/conf/log4j.properties.template \
      $SPARK_HOME/conf/log4j.properties

编辑新复制的文件,并在代码中的每一行将INFO替换为WARN。 您的log4j.properties文件应类似于:

# Set everything to be logged to the console
log4j.rootCategory=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/dd HH:mm:ss} %p %c{1}: %m%n

# Settings to quiet third party logs that are too verbose
log4j.logger.org.eclipse.jetty=WARN
log4j.logger.org.eclipse.jetty.util.component.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=WARN
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=WARN

现在当你运行PySpark你应该得到更简单的输出消息! 特别感谢@genomegeek在District Data Labs workshop的研讨会上指出来!

将IPython Notebook与Spark结合使用
当Google搜索有用的Spark提示时,我发现了一些帖子,提到如何使用IPython notebook配置PySpark。IPython Notebook是数据科学家以交互方式呈现他们的科学和理论工作的一个重要工具,集成了文本和Python代码。对于许多数据科学家,IPython笔记本是他们第一次介绍Python和被广泛使用,所以我认为这将是值得被写在在这篇文章里的。

这里的大多数说明是从IPython笔记本:使用PySpark设置IPython。 但是,我们将专注于在您的本地计算机上而不是在EC2集群上以独立模式将IPython shell连接到PySpark。 如果你想在集群上使用PySpark / IPython,请随时查看这些说明,如果你这样做,请评论它是怎么回事!

1.为我们的Spark配置创建iPython笔记本配置文件。

~$ ipython profile create spark
[ProfileCreate] Generating default config file: u'$HOME/.ipython/profile_spark/ipython_config.py'
[ProfileCreate] Generating default config file: u'$HOME/.ipython/profile_spark/ipython_notebook_config.py'
[ProfileCreate] Generating default config file: u'$HOME/.ipython/profile_spark/ipython_nbconvert_config.py'

记下已创建配置文件的位置,并按照以下步骤替换相应的路径:
2.在以下路径中创建文件

$HOME/.ipython/profile_spark/startup/00-pyspark-setup.py

加上这些:

import os
import sys

# Configure the environment
if 'SPARK_HOME' not in os.environ:
    os.environ['SPARK_HOME'] = '/srv/spark'

# Create a variable for our root path
SPARK_HOME = os.environ['SPARK_HOME']

# Add the PySpark/py4j to the Python Path
sys.path.insert(0, os.path.join(SPARK_HOME, "python", "build"))
sys.path.insert(0, os.path.join(SPARK_HOME, "python"))

3.使用我们刚刚创建的配置文件启动IPython Notebook。

~$ ipython notebook --profile spark

在你的笔记本中,你应该看到我们刚刚创建的变量。

print SPARK_HOME

5.在您的IPython Notebook的顶部,请确保添加Sparkcontext。

from pyspark import  SparkContext
sc = SparkContext( 'local', 'pyspark')

6.使用IPython做一个简单的计算测试Spark上下文。

def isprime(n):
    """
    check if integer n is a prime
    """
    # make sure n is a positive integer
    n = abs(int(n))
    # 0 and 1 are not primes
    if n < 2:
        return False
    # 2 is the only even prime number
    if n == 2:
        return True
    # all other even numbers are not primes
    if not n & 1:
        return False
    # range starts with 3 and only needs to go up the square root of n
    # for all odd numbers
    for x in range(3, int(n**0.5)+1, 2):
        if n % x == 0:
            return False
    return True

# Create an RDD of numbers from 0 to 1,000,000
nums = sc.parallelize(xrange(1000000))

# Compute the number of primes in the RDD
print nums.filter(isprime).count()

如果你得到一个没有错误的数字,那么你的内容可以正常工作!

编者注:上面配置了一个IPython context,用于直接调用IPython notebook与PySpark。 但是,您也可以直接使用PySpark启动笔记本,如下所示:

 $ IPYTHON_OPTS="notebook --pylab inline" pyspark

任一方法的工作原理类似,取决于你的使用情况PySpark和IPython。 前者允许你更容易地连接到集群与IPython notebook,因此,这是我喜欢的方法。

在EC2上使用Spark
在我教授使用Hadoop的分布式计算时,我发现很多都可以在伪分布式节点或单节点模式下在本地教授。 然而,为了真正了解发生的事情,集群是必要的。 当数据变得太大时,在学习这些技能和实际计算需求之间经常存在断开。 如果你有一点钱花在学习如何使用Spark的细节上,我建议设置一个快速集群进行实验。 请注意,以每周大约10小时的速度使用的5个Slaves(和1个master)的群集每月将花费大约$ 45.18。

完整的讨论可以在Spark文档中找到:在EC2上运行Spark。 一定要仔细阅读本文档,因为如果您开始这些步骤,您将在EC2群集上付费。 我在这里突出了几个要点:
1.通过AWS控制台获取一组AWS EC2密钥对(访问密钥和密钥)。
2.将密钥对导出到您的环境。 在您的shell中发出这些命令,或将它们添加到您的配置文件。

export AWS_ACCESS_KEY_ID=myaccesskeyid
export AWS_SECRET_ACCESS_KEY=mysecretaccesskey

请注意,不同的实用程序使用不同的环境名称,因此请确保将这些用于Spark脚本。
3.按如下所示启动集群:

~$ cd $SPARK_HOME/ec2
ec2$ ./spark-ec2 -k <keypair> -i <key-file> -s <num-slaves> launch <cluster-name>

4.通过SSH进入集群以运行Spark作业

ec2$ ./spark-ec2 -k <keypair> -i <key-file> login <cluster-name>

5.销毁群集,如下所示。

ec2$ ./spark-ec2 destroy <cluster-name>.

这些脚本将自动创建一个本地HDFS集群,以便向其中添加数据,还有一个copy-dir命令,允许您将代码和数据同步到集群。 但是,最好的办法是简单地使用S3进行数据存储,并创建使用s3:// URI加载数据的RDD。

什么是Spark?
现在我们已经设置了Spark,让我们来讨论一下Spark是什么。 Spark是通用集群计算框架,通过在多台计算机上分布计算,为大型数据集提供高效的内存中计算。 如果你熟悉Hadoop,那么你知道任何分布式计算框架都需要解决两个问题:如何分布数据和如何分布计算。 Hadoop使用HDFS来解决分布式数据问题和MapReduce作为提供有效分布式计算的编程范例。 类似地,Spark有多种语言的函数式编程API,提供比map和reduce更多的操作符,通过一个称为弹性分布式数据集或RDD的分布式数据框架来实现。

RDD本质上是一种编程抽象,表示跨机器分区的对象的只读集合。 RDD可以从谱系重建(因此是容错的),通过并行操作访问,可以从分布式存储器读取和写入,如HDFS或S3,最重要的是,可以在工作器节点的存储器中缓存 重用。 因为RDD可以在内存中缓存,Spark在迭代应用程序中非常有效,在迭代应用程序中,数据在整个算法过程中被重用。 大多数机器学习和优化算法是迭代的,使Spark成为一个非常有效的数据科学工具。 另外,因为Spark是这么快,它可以通过类似于Python REPL的命令行提示以交互方式访问。

Spark库本身包含了许多应用程序元素,它们已经进入大多数大数据应用程序,包括支持类似于SQL的大数据查询,机器学习和图形算法,甚至支持实时流数据。

核心组件是:
1.Spark Core:包含Spark的基本功能; 特别是定义RDDs以及可以对其执行的操作和操作的API。 Spark的其他库都建立在RDD和Spark Core之上。
2.Spark SQL:
提供用于通过称为Hive查询语言(HiveQL)的SQL的Apache Hive变体与Spark交互的API。 每个数据库表都表示为RDD,Spark SQL查询将转换为Spark操作。 对于那些熟悉Hive和HiveQL的人,Spark可以作为替代。
3.Spark Streaming:
实时处理和操作数据的实时流。 存在许多流数据库(例如Apache Storm)用于处理实时数据。 Spark Streaming使程序能够利用这些数据,类似于在数据流入时与正常RDD交互的方式。
4.MLlib:
一个通用机器学习算法库,在RDD上实现为Spark操作。 这个库包含可扩展的学习算法,如分类,回归等,需要跨越大型数据集的迭代操作。 Mahout库,以前的大数据机器学习库的选择,将移动到Spark在未来的实施。
5.GraphX:
用于操作图形和执行并行图形操作和计算的算法和工具集合。 GraphX扩展RDD API以包括用于操作图形,创建子图或访问路径中的所有顶点的操作。
因为这些组件满足许多大数据需求以及许多数据科学任务的算法和计算要求,所以Spark一直在迅速普及。 不仅如此,Spark在Scala,Java和Python中提供了API; 满足许多不同群体的需求,并允许更多的数据科学家轻松地采用Spark作为他们的大数据解决方案。

Spark编程
编程Spark应用程序类似于以前在Hadoop上实现的其他数据流语言。 代码被写入驱动程序中,该程序被懒惰地评估,并且在动作时,驱动程序代码分布在集群中以由RDD的分区上的工作者执行。 然后将结果发送回驱动程序以进行聚合或编译。 本质上,驱动程序创建一个或多个RDD,应用操作来转换RDD,然后在转换的RDD上调用一些动作。

这些步骤概述如下:
1.通过访问存储在磁盘(HDFS,Cassandra,HBase,本地磁盘)上的数据,并行化内存中的一些集合,转换现有RDD或缓存或保存来定义一个或多个RDD。
2.通过将闭包(函数)传递给RDD的每个元素,在RDD上调用操作。 Spark提供超过80个高级运算符,除了Map和Reduce。
3.使用生成的RDD与操作(例如计数,收集,保存等)。 操作启动集群上的计算。

当Spark对工作程序运行闭包时,闭包中使用的任何变量都将复制到该节点,但会在该闭包的本地范围内维护。 Spark提供了两种类型的共享变量,可以以受限方式与所有工作者交互。 广播变量分发给所有工作者,但是是只读的。 广播变量可以用作查找表或禁用词列表。 累加器是工作者可以“添加”到使用关联操作并且通常用作计数器的变量。

Spark应用程序本质上是通过转换和操作来操作RDDs。 未来的帖子将更详细地介绍,但这种理解应该足以执行下面的示例程序。

Spark执行
关于Spark执行的简要说明。 基本上,Spark应用程序作为独立的进程集合运行,由驱动程序中的SparkContext进行协调。 上下文将连接到分配系统资源的一些集群管理器(例如YARN)。 集群中的每个工作线程由一个执行器管理,该执行器又由SparkContext管理。 执行器管理每台机器上的计算以及存储和缓存。

需要注意的是,应用程序代码从驱动程序发送到执行程序,执行程序指定上下文和要运行的各种任务。 执行器与驱动程序进行数据共享或交互。 驱动程序是Spark作业的关键参与者,因此,它们应该与集群在同一个网络上。 这不同于Hadoop代码,您可以从任何地方将作业提交到JobTracker,然后JobTracker处理集群上的执行。
Spark交互
开始使用Spark的最简单方法是通过交互式命令提示符。 要打开PySpark终端,只需在命令行输入pyspark。

~$ pyspark
[… snip …]
>>>

PySpark将自动创建一个SparkContext供您使用,使用本地Spark配置。 它通过sc变量暴露给终端。 让我们创建我们的第一个RDD。

>>> text = sc.textFile("shakespeare.txt")
>>> print text
shakespeare.txt MappedRDD[1] at textFile at NativeMethodAccessorImpl.java:-2

textFile方法将莎士比亚的完整作品加载到名为text的RDD中。 如果检查RDD,您可以看到它是一个MappedRDD,并且文件的路径是从当前工作目录(在正确的路径传递到系统上的shakespeare.txt文件)的相对路径。 让我们开始转换这个RDD,以便计算分布式计算的“hello world”:“wordcount”。

>>> from operator import add
>>> def tokenize(text):
...     return text.split()
...
>>> words = text.flatMap(tokenize)
>>> print words
PythonRDD[2] at RDD at PythonRDD.scala:43

我们首先导入运算符add,这是一个可以用作加法闭包的命名函数。 我们稍后将使用此函数。 我们要做的第一件事是将我们的文本拆分成单词。 我们创建了一个名为tokenize的函数,其参数是一些文本,并且通过简单地分割空格返回该文本中的标记(单词)列表。 然后,我们通过flatMap运算符的应用程序转换文本RDD,并创建了一个名为words的新RDD,并向其传递了closure tokenize。 正如你可以看到,单词是一个PythonRDD,但执行应该是瞬间发生的。 显然,我们还没有将整个莎士比亚数据集分割成单词列表。

如果你已经使用MapReduce完成了Hadoop“wordcount”,你会知道接下来的步骤是将每个字映射到一个键值对,其中键是字,值为1,然后使用 reducer对每个键的1s进行求和。

首先,让我们应用我们map.

>>> wc = words.map(lambda x: (x,1))
>>> print wc.toDebugString()
(2) PythonRDD[3] at RDD at PythonRDD.scala:43
|  shakespeare.txt MappedRDD[1] at textFile at NativeMethodAccessorImpl.java:-2
|  shakespeare.txt HadoopRDD[0] at textFile at NativeMethodAccessorImpl.java:-2

不使用命名函数,我们将使用匿名函数(在Python中使用lambda关键字)。 这行代码将lambda映射到每个单词的元素。 因此,每个x是一个单词,该单词将被匿名闭包转换为一个元组(单词,1)。 为了检查到目前为止的沿袭,我们可以使用toDebugString方法来查看我们的PipelinedRDD是如何转换的。 然后我们可以应用reduceByKey操作来获取我们的字计数,然后将这些字计数写入磁盘。

>>> counts = wc.reduceByKey(add)
>>> counts.saveAsTextFile("wc")

一旦我们最终调用saveAsTextFile操作,分布式作业就会启动,当作业在集群中运行时(或者作为本地机器上的多个进程),您应该看到很多INFO语句。 如果退出解释器,您应该在当前工作目录中看到一个名为“wc”的目录。

$ ls wc/
_SUCCESS   part-00000 part-00001

每个部分文件表示由计算机上的各种进程计算并保存到磁盘的最终RDD的分区。 如果对一个零件文件使用head命令,则应该看到字计数对的元组。

$ head wc/part-00000
(u'fawn', 14)
(u'Fame.', 1)
(u'Fame,', 2)
(u'kinghenryviii@7731', 1)
(u'othello@36737', 1)
(u'loveslabourslost@51678', 1)
(u'1kinghenryiv@54228', 1)
(u'troilusandcressida@83747', 1)
(u'fleeces', 1)
(u'midsummersnightsdream@71681', 1)

请注意,没有一个键按照它们在Hadoop中的原样进行排序(由于Map和Reduce任务之间的必要的shuffle和排序阶段)。 但是,您保证每个键在所有部分文件中只出现一次,因为您对计数RDD使用reduceByKey运算符。 如果需要,您可以使用排序运算符确保在将所有键写入磁盘之前对其进行排序。
写一个Spark 应用
编写Spark应用程序类似于在交互式控制台中使用Spark。 API是相同的。 首先,您需要访问SparkContext,它是由pyspark应用程序为您自动加载的。
在Python中编写Spark应用程序的基本模板如下:

## Spark Application - execute with spark-submit

## Imports
from pyspark import SparkConf, SparkContext

## Module Constants
APP_NAME = "My Spark Application"

## Closure Functions

## Main functionality

def main(sc):
    pass

if __name__ == "__main__":
    # Configure Spark
    conf = SparkConf().setAppName(APP_NAME)
    conf = conf.setMaster("local[*]")
    sc   = SparkContext(conf=conf)

    # Execute Main functionality
    main(sc)

这个模板让你了解Spark应用程序需要什么:导入各种Python库,模块常量,调试和Spark UI的标识应用程序名称,闭包或其他自定义操作函数,最后,一些主要的分析方法 作为驱动程序运行。 在我们的ifmain中,我们创建SparkContext,并使用上下文配置执行main。 这将允许我们轻松地将驱动程序代码导入pyspark上下文而不执行。 注意,这里Spark配置通过setMaster方法硬编码到SparkConf中,但通常只允许从命令行配置此值,因此您将看到此行注释掉。

要关闭或退出程序,请使用sc.stop()或sys.exit0)。

为了演示Spark的常见用法,让我们来看看一个常见的用例,我们在CSV文件中读取数据并计算一些聚合统计信息。 在这种情况下,我们查看美国交通部的准时航班数据,记录美国国内航班起飞和到达时间,以及2014年4月的离港和到达延误。我通常使用 此数据集因为一个月是可管理的探索,但整个数据集需要计算一个集群。 整个应用程序如下:

## Spark Application - execute with spark-submit

## Imports
import csv
import matplotlib.pyplot as plt

from StringIO import StringIO
from datetime import datetime
from collections import namedtuple
from operator import add, itemgetter
from pyspark import SparkConf, SparkContext

## Module Constants
APP_NAME = "Flight Delay Analysis"
DATE_FMT = "%Y-%m-%d"
TIME_FMT = "%H%M"

fields   = ('date', 'airline', 'flightnum', 'origin', 'dest', 'dep',
            'dep_delay', 'arv', 'arv_delay', 'airtime', 'distance')
Flight   = namedtuple('Flight', fields)

## Closure Functions
def parse(row):
    """
    Parses a row and returns a named tuple.
    """

    row[0]  = datetime.strptime(row[0], DATE_FMT).date()
    row[5]  = datetime.strptime(row[5], TIME_FMT).time()
    row[6]  = float(row[6])
    row[7]  = datetime.strptime(row[7], TIME_FMT).time()
    row[8]  = float(row[8])
    row[9]  = float(row[9])
    row[10] = float(row[10])
    return Flight(*row[:11])

def split(line):
    """
    Operator function for splitting a line with csv module
    """
    reader = csv.reader(StringIO(line))
    return reader.next()

def plot(delays):
    """
    Show a bar chart of the total delay per airline
    """
    airlines = [d[0] for d in delays]
    minutes  = [d[1] for d in delays]
    index    = list(xrange(len(airlines)))

    fig, axe = plt.subplots()
    bars = axe.barh(index, minutes)

    # Add the total minutes to the right
    for idx, air, min in zip(index, airlines, minutes):
        if min > 0:
            bars[idx].set_color('#d9230f')
            axe.annotate(" %0.0f min" % min, xy=(min+1, idx+0.5), va='center')
        else:
            bars[idx].set_color('#469408')
            axe.annotate(" %0.0f min" % min, xy=(10, idx+0.5), va='center')

    # Set the ticks
    ticks = plt.yticks([idx+ 0.5 for idx in index], airlines)
    xt = plt.xticks()[0]
    plt.xticks(xt, [' '] * len(xt))

    # minimize chart junk
    plt.grid(axis = 'x', color ='white', linestyle='-')

    plt.title('Total Minutes Delayed per Airline')
    plt.show()

## Main functionality
def main(sc):

    # Load the airlines lookup dictionary
    airlines = dict(sc.textFile("ontime/airlines.csv").map(split).collect())

    # Broadcast the lookup dictionary to the cluster
    airline_lookup = sc.broadcast(airlines)

    # Read the CSV Data into an RDD
    flights = sc.textFile("ontime/flights.csv").map(split).map(parse)

    # Map the total delay to the airline (joined using the broadcast value)
    delays  = flights.map(lambda f: (airline_lookup.value[f.airline],
                                     add(f.dep_delay, f.arv_delay)))

    # Reduce the total delay for the month to the airline
    delays  = delays.reduceByKey(add).collect()
    delays  = sorted(delays, key=itemgetter(1))

    # Provide output from the driver
    for d in delays:
        print "%0.0f minutes delayed\t%s" % (d[1], d[0])

    # Show a bar chart of the delays
    plot(delays)

if __name__ == "__main__":
    # Configure Spark
    conf = SparkConf().setMaster("local[*]")
    conf = conf.setAppName(APP_NAME)
    sc   = SparkContext(conf=conf)

    # Execute Main functionality
    main(sc)

要运行此代码(假定您有一个目录称为一次,两个CSV文件在同一目录中),请使用spark-submit命令如下:

~$ spark-submit app.py

这将使用localhost作为主机创建Spark作业,并在与app.py位于同一目录中的ontime目录中查找两个CSV文件。 最后的结果表明,如果你从美国大陆飞往夏威夷或阿拉斯加,四月份的总延误(以分钟为单位)从早到达到大多数大航空公司的总延迟。 特别要注意的是,我们可以使用matplotlib直接在驱动程序app.py上可视化结果:
这里写图片描述
那么这段代码在干什么呢? 让我们特别看看与Spark最直接相关的工作的主函数。 首先,我们将CSV文件加载到RDD中,然后将split函数映射到它。 split函数使用csv模块解析每行文本,并返回一个表示行的元组。 最后,我们将collect操作传递给RDD,RDD将数据从RDD作为Python列表返回到驱动程序。 在这种情况下,airlines.csv是一个小的跳转表,将允许我们加入航空公司全名的航空公司代码。 我们将这个跳转表存储为Python字典,然后使用sc.broadcast将其广播到集群中的每个节点。

接下来,主函数加载更大的flights.csv。 分割CSV行后,我们将解析函数映射到CSV行,该行将日期和时间转换为Python日期和时间,并适当地投射浮点数。 它还将该行存储为名为Flight的NamedTuple,以实现高效易用。

利用手中的Flight对象的RDD,我们将匿名函数映射到一系列键 - 值对,其中键是航空公司的名称,并且该值是到达和离开延迟的总和。 每个航空公司使用reduceByKey动作和加法运算符将其延迟加在一起,并将该RDD收集回驱动程序(数据中的航空公司数量相对较少)。 最后,延迟按升序排序,然后输出打印到控制台以及使用matplotlib可视化。

这个例子很长,但希望它说明了集群和驱动程序的相互作用(发送分析,然后将结果返回到驱动程序)以及Python代码在Spark应用程序中的作用。

总结
虽然不完全介绍Spark,我们希望你对Spark有更好的感觉,以及如何使用Python进行快速的内存分布式计算。 至少,您应该能够使Spark启动并运行,并在独立模式下或通过Amazon EC2在本地机器上开始探索数据。 你甚至应该能够得到iPython的笔记本设置和配置运行Spark!

Spark不解决分布式存储问题(通常Spark从HDFS获取其数据),但它为分布式计算提供了丰富的函数式编程API。 这个框架建立在弹性分布式数据集或简称“RDD”的思想上。 RDD是表示对象的分区集合的编程抽象,允许对它们执行分布式操作。 RDD是容错的(弹性部分),并且最重要的是,可以存储在工作节点上的存储器中以立即重用。 在存储器存储中提供更快和更容易表示的迭代算法以及实现实时交互分析。

因为Spark库具有Python,Scala和Java中可用的API,以及用于机器学习,流数据,图形算法和类似SQL的查询的内置模块; 它已经迅速成为当今存在的最重要的分布式计算框架之一。 当与YARN结合使用时,Spark不仅不会取代现有的Hadoop集群,而且将来将成为大数据的重要组成部分,开辟了数据科学探索的新途径。

有用的链接
希望你喜欢这篇文章! 写作永远不会在真空中发生,所以这里有一些有用的链接,帮助我写的职位; 你可能想要审查以探索Spark进一步。 请注意,某些图书链接是联属网络链接,这意味着如果您点击它们并购买,您正在帮助支持区域数据实验室!

这是一个介绍性的职位,比典型的区域数据实验室文章,但有一些数据和代码相关的介绍,你可以在这里找到:
Code on Github
Shakespeare Dataset

Airline On Time Datasetis munged fromThe Bureau of Transportation Statistics (US DOT)
District Data Labs also regularly holds a Fast Data Applications with Spark & Python
workshop. If you’re interested in learning more about Spark, you should definitely consider attending. For more information about that and to see when it is being offered next, check out the course page.
Spark Paper
Like Hadoop, Spark has some fundamental papers that I believe should be required reading for serious data scientists that need to do distributed computing on large data sets. The first is a workshop paper from HotOS (hot topics in operating systems) that describes Spark in an easily understandable fashion. The second is a more theoretical paper that describes RDDs in detail.

1.M. Zaharia, M. Chowdhury, M. J. Franklin, S. Shenker, and I. Stoica, “Spark: cluster computing with working sets,” in Proceedings of the 2nd USENIX conference on Hot topics in cloud computing, 2010, pp. 10–10.

2.M. Zaharia, M. Chowdhury, T. Das, A. Dave, J. Ma, M. McCauley, M. J. Franklin, S. Shenker, and I. Stoica, “Resilient distributed datasets: A fault-tolerant abstraction for in-memory cluster computing,” in Proceedings of the 9th USENIX conference on Networked Systems Design and Implementation, 2012, pp. 2–2.

Books on Spark

Learning Spark
Advanced Analytics with Spark
Helpful Blog Posts

Setting up IPython with PySpark
Databricks Spark Reference Applications
Running Spark on EC2
Run Spark and SparkSQL on Amazon Elastic MapReduce
Once again, thanks to @genomegeek for his contributions to this post!

Benjamin Bengfort

February 02, 2015

Paperback: 364 pages Publisher: Apress; 1 edition (August 21, 2015) Language: English ISBN-10: 1484209591 ISBN-13: 978-1484209592 Python Data Analytics will help you tackle the world of data acquisition and analysis using the power of the Python language. At the heart of this book lies the coverage of pandas, an open source, BSD-licensed library providing high-performance, easy-to-use data structures and data analysis tools for the Python programming language. Author Fabio Nelli expertly shows the strength of the Python programming language when applied to processing, managing and retrieving information. Inside, you will see how intuitive and flexible it is to discover and communicate meaningful patterns of data using Python scripts, reporting systems, and data export. This book examines how to go about obtaining, processing, storing, managing and analyzing data using the Python programming language. You will use Python and other open source tools to wrangle data and tease out interesting and important trends in that data that will allow you to predict future patterns. Whether you are dealing with sales data, investment data (stocks, bonds, etc.), medical data, web page usage, or any other type of data set, Python can be used to interpret, analyze, and glean information from a pile of numbers and statistics. This book is an invaluable reference with its examples of storing and accessing data in a database; it walks you through the process of report generation; it provides three real world case studies or examples that you can take with you for your everyday analysis needs.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值