- 大数据分析有用的资源
- 大数据分析 - 快速指南
- 大数据分析 - 资源
- 大数据分析 - 讨论
大数据分析 - 快速指南
大数据分析 - 概述
在过去的十年中,人们必须处理的数据量已爆炸性地增长到难以想象的水平,与此同时,数据存储的价格也已系统性地降低。私营公司和研究机构从手机和汽车等设备获取有关用户交互、业务、社交媒体以及传感器的数 TB 数据。这个时代的挑战是如何理解这片海量的数据。这就是大数据分析发挥作用的地方。
大数据分析主要涉及从不同来源收集数据,以可供分析师使用的方式对其进行处理,最后提供对组织业务有用的数据产品。
将从不同来源检索的大量非结构化原始数据转换为对组织有用的数据产品的过程构成了大数据分析的核心。
大数据分析 - 数据生命周期
传统数据挖掘生命周期
为了提供一个框架来组织组织所需的工作并提供来自大数据的清晰见解,将其视为具有不同阶段的循环是有用的。它绝不是线性的,这意味着所有阶段都是相互关联的。该周期与CRISP 方法中描述的更传统的数据挖掘周期有表面上的相似之处。
CRISP-DM 方法论
CRISP -DM 方法代表数据挖掘的跨行业标准流程,是一个描述数据挖掘专家用来解决传统 BI 数据挖掘问题的常用方法的周期。它仍在传统 BI 数据挖掘团队中使用。
看看下面的插图。它显示了 CRISP-DM 方法所描述的周期的主要阶段以及它们如何相互关联。
CRISP-DM 于 1996 年构思,次年作为 ESPRIT 资助计划下的欧盟项目启动。该项目由五家公司牵头:SPSS、Teradata、戴姆勒股份公司、NCR 公司和 OHRA(一家保险公司)。该项目最终被纳入SPSS。该方法非常详细地说明了如何指定数据挖掘项目。
现在让我们更多地了解 CRISP-DM 生命周期中涉及的每个阶段 -
业务理解- 这个初始阶段的重点是从业务角度理解项目目标和要求,然后将这些知识转换为数据挖掘问题定义。初步计划旨在实现目标。可以使用决策模型,尤其是使用决策模型和符号标准构建的决策模型。
数据理解- 数据理解阶段从初始数据收集开始,并继续进行活动,以熟悉数据,识别数据质量问题,发现对数据的第一见解,或检测有趣的子集以形成隐藏的假设信息。
数据准备- 数据准备阶段涵盖从初始原始数据构建最终数据集(将输入建模工具的数据)的所有活动。数据准备任务可能会执行多次,并且不按任何规定的顺序执行。任务包括表、记录和属性选择以及建模工具的数据转换和清理。
建模- 在此阶段,选择并应用各种建模技术,并将其参数校准为最佳值。通常,对于同一数据挖掘问题类型有多种技术。有些技术对数据的形式有特定的要求。因此,常常需要退回到数据准备阶段。
评估- 在项目的这个阶段,您已经构建了一个(或多个)模型,从数据分析的角度来看,该模型似乎具有高质量。在进行模型的最终部署之前,彻底评估模型并检查构建模型所执行的步骤非常重要,以确保它正确实现业务目标。
一个关键目标是确定是否存在一些尚未充分考虑的重要业务问题。在此阶段结束时,应就数据挖掘结果的使用做出决定。
部署- 模型的创建通常不是项目的结束。即使模型的目的是增加数据知识,所获得的知识也需要以对客户有用的方式进行组织和呈现。
根据需求,部署阶段可以像生成报告一样简单,也可以像实施可重复的数据评分(例如段分配)或数据挖掘过程一样复杂。
在许多情况下,执行部署步骤的是客户,而不是数据分析师。即使分析师部署了模型,客户也必须提前了解需要执行的操作,以便实际使用所创建的模型。
SEMMA方法论
SEMMA 是 SAS 开发的另一种用于数据挖掘建模的方法。它代表Sample(样本)、E xplore(探索)、Modify(修改)、Model(模型)和A sses(评估)。这是其阶段的简要描述 -
样本- 该过程从数据采样开始,例如,选择用于建模的数据集。数据集应足够大以包含足够的信息以供检索,但又应足够小以有效使用。此阶段还处理数据分区。
探索- 此阶段涵盖通过在数据可视化的帮助下发现变量之间的预期和意外关系以及异常来理解数据。
修改- 修改阶段包含选择、创建和转换变量以准备数据建模的方法。
模型- 在模型阶段,重点是将各种建模(数据挖掘)技术应用于准备好的变量,以创建可能提供所需结果的模型。
评估- 建模结果的评估显示了所创建模型的可靠性和有用性。
CRISP-DM 和 SEMMA 之间的主要区别在于,SEMMA 侧重于建模方面,而 CRISP-DM 更重视建模之前的周期阶段,例如了解要解决的业务问题、了解和预处理要处理的数据。用作输入,例如机器学习算法。
大数据生命周期
在当今的大数据背景下,以前的方法要么不完整,要么不是最优的。例如,SEMMA方法完全忽略了不同数据源的数据收集和预处理。这些阶段通常构成了成功的大数据项目的大部分工作。
大数据分析周期可以通过以下阶段来描述 -
- 业务问题定义
- 研究
- 人力资源评估
- 数据采集
- 数据修改
- 数据存储
- 探索性数据分析
- 建模和评估的数据准备
- 造型
- 执行
在本节中,我们将简要介绍大数据生命周期的每个阶段。
业务问题定义
这是传统 BI 和大数据分析生命周期中的一个共同点。通常,定义问题并正确评估它可能为组织带来多少潜在收益是大数据项目的一个重要阶段。提到这一点似乎是显而易见的,但必须评估该项目的预期收益和成本是多少。
研究
分析其他公司在相SymPy况下的做法。这涉及寻找适合您公司的解决方案,即使它涉及根据您公司拥有的资源和要求调整其他解决方案。在此阶段,应定义未来阶段的方法。
人力资源评估
一旦问题被定义,继续分析当前员工是否能够成功完成项目是合理的。传统的BI团队可能无法为所有阶段提供最优的解决方案,因此在项目开始之前就应该考虑是否需要外包部分项目或雇用更多人员。
数据采集
这部分是大数据生命周期的关键;它定义了交付结果数据产品所需的配置文件类型。数据收集是该过程的一个重要步骤;它通常涉及从不同来源收集非结构化数据。举个例子,它可能涉及编写一个爬虫来从网站检索评论。这涉及到处理文本,可能是不同语言的文本,通常需要大量时间才能完成。
数据修改
一旦从网络等检索数据,就需要以易于使用的格式存储。为了继续查看评论示例,我们假设数据是从不同的站点检索的,每个站点都有不同的数据显示。
假设一个数据源以星级评分的形式给出评论,因此可以将其解读为响应变量y ∈ {1, 2, 3, 4, 5} 的映射。另一个数据源使用两个箭头系统提供评论,一个用于向上投票,另一个用于向下投票。这意味着响应变量的形式为y ∈ {positive, negative}。
为了组合两个数据源,必须做出决定以使这两个响应表示等效。这可以涉及将第一数据源响应表示转换为第二形式,将一颗星视为负面,将五颗星视为正面。此过程通常需要分配大量时间才能高质量交付。
数据存储
数据处理后,有时需要将其存储在数据库中。关于这一点,大数据技术提供了很多替代方案。最常见的替代方案是使用 Hadoop 文件系统进行存储,为用户提供有限版本的 SQL,称为 HIVE 查询语言。从用户的角度来看,这使得大多数分析任务能够以与传统 BI 数据仓库中类似的方式完成。其他需要考虑的存储选项包括 MongoDB、Redis 和 SPARK。
周期的这个阶段与人力资源知识有关,即他们实现不同架构的能力。传统数据仓库的修改版本仍在大规模应用程序中使用。例如,Teradata 和 IBM 提供可以处理 TB 级数据的 SQL 数据库;postgreSQL 和 MySQL 等开源解决方案仍在大规模应用程序中使用。
尽管不同存储在后台的工作方式存在差异,但从客户端来看,大多数解决方案都提供 SQL API。因此,对 SQL 的良好理解仍然是大数据分析的一项关键技能。
这个阶段先验似乎是最重要的话题,实际上,事实并非如此。这甚至不是一个必要的阶段。可以实现一个处理实时数据的大数据解决方案,因此在这种情况下,我们只需要收集数据来开发模型,然后实时实现它。因此根本不需要正式存储数据。
探索性数据分析
一旦数据被清理并以可以从中检索见解的方式存储,数据探索阶段就必不可少。此阶段的目标是理解数据,这通常是通过统计技术并绘制数据来完成的。这是评估问题定义是否有意义或可行的良好阶段。
建模和评估的数据准备
此阶段涉及重塑先前检索到的清理数据,并使用统计预处理来进行缺失值插补、离群值检测、归一化、特征提取和特征选择。
造型
前一阶段应该生成多个用于训练和测试的数据集,例如预测模型。此阶段涉及尝试不同的模型并期待解决手头的业务问题。在实践中,通常希望模型能够提供对业务的一些洞察。最后,选择最佳模型或模型组合,评估其在遗漏数据集上的性能。
执行
该阶段开发的数据产品在公司的数据管道中落地。这涉及在数据产品运行时设置验证方案,以跟踪其性能。例如,在实施预测模型的情况下,此阶段将涉及将模型应用于新数据,一旦响应可用,就评估模型。
大数据分析 - 方法论
在方法论方面,大数据分析与实验设计的传统统计方法有很大不同。分析从数据开始。通常我们以解释响应的方式对数据进行建模。此方法的目标是预测响应Behave或了解输入变量与响应的关系。通常,在统计实验设计中,会开发实验并检索数据作为结果。这允许以统计模型可以使用的方式生成数据,其中某些假设成立,例如独立性、正态性和随机化。
在大数据分析中,我们看到的是数据。我们无法设计一个满足我们最喜欢的统计模型的实验。在大规模的分析应用中,仅仅清理数据就需要大量的工作(通常是80%的工作量),因此它可以被机器学习模型使用。
在真正的大规模应用中,我们没有可以遵循的独特方法。通常,一旦定义了业务问题,就需要一个研究阶段来设计要使用的方法。然而,一般准则是值得提及的,并且适用于几乎所有问题。
大数据分析中最重要的任务之一是统计建模,这意味着有监督和无监督的分类或回归问题。一旦数据被清理和预处理,可用于建模,应注意使用合理的损失指标评估不同的模型,然后一旦模型被实施,应报告进一步的评估和结果。预测建模的一个常见陷阱是只实现模型而不测量其性能。
大数据分析 - 核心交付成果
正如大数据生命周期中提到的,开发大数据产品所产生的数据产品在大多数情况下是以下一些 -
机器学习实现- 这可以是分类算法、回归模型或分割模型。
推荐系统- 目标是开发一个根据用户Behave推荐选择的系统。Netflix是这种数据产品的典型例子,它根据用户的评分推荐其他电影。
仪表板- 业务通常需要工具来可视化聚合数据。仪表板是一种使这些数据可访问的图形机制。
临时分析- 通常,业务领域有问题、假设或神话,可以通过对数据进行临时分析来回答。
大数据分析 - 主要利益相关者
在大型组织中,为了成功开发大数据项目,需要有管理层支持该项目。这通常涉及找到一种方法来展示项目的业务优势。对于为项目寻找赞助商的问题,我们没有独特的解决方案,但下面给出了一些指导方针 -
检查与您感兴趣的项目类似的其他项目的赞助商是谁以及在哪里。
在关键管理职位上拥有个人联系人会有所帮助,因此如果项目有前途,就可以触发任何联系。
谁会从你的项目中受益?一旦项目步入正轨,谁将成为您的客户?
制定一个简单、清晰且令人兴奋的提案,并与组织中的关键参与者分享。
为项目寻找赞助商的最佳方法是了解问题以及实施后产生的数据产品是什么。这种理解将有助于让管理层相信大数据项目的重要性。
大数据分析 - 数据分析师
数据分析师具有面向报告的配置文件,具有使用 SQL 从传统数据仓库中提取和分析数据的经验。他们的任务通常是数据存储或报告一般业务结果。数据仓库绝不简单,它只是与数据科学家所做的不同。
许多组织都在努力在市场上寻找有能力的数据科学家。然而,选择潜在的数据分析师并教他们成为数据科学家的相关技能是一个好主意。这绝不是一项微不足道的任务,通常需要在定量领域攻读硕士学位的人,但这绝对是一个可行的选择。下面列出了合格的数据分析师必须具备的基本技能 -
- 业务理解
- SQL编程
- 报告设计与实施
- 仪表板开发
大数据分析 - 数据科学家
数据科学家的角色通常与预测建模、开发细分算法、推荐系统、A/B 测试框架等任务相关,并且经常处理原始非结构化数据。
他们的工作性质要求对数学、应用统计和编程有深刻的理解。数据分析师和数据科学家之间有一些共同的技能,例如查询数据库的能力。两者都分析数据,但数据科学家的决策可以对组织产生更大的影响。
以下是数据科学家通常需要具备的一组技能 -
- 使用统计包进行编程,例如:R、Python、SAS、SPSS 或 Julia
- 能够清理、提取和探索来自不同来源的数据
- 统计模型的研究、设计和实现
- 深厚的统计、数学和计算机科学知识
在大数据分析中,人们通常会混淆数据科学家和数据架构师的角色。事实上,差异非常简单。数据架构师定义存储数据的工具和架构,而数据科学家则使用该架构。当然,如果临时项目需要,数据科学家应该能够设置新工具,但基础设施定义和设计不应成为其任务的一部分。
大数据分析 - 问题定义
通过本教程,我们将开发一个项目。本教程后续的每一章都涉及小型项目部分中较大项目的一部分。这被认为是一个应用教程部分,将提供对现实世界问题的接触。在这种情况下,我们将从项目的问题定义开始。
项目介绍
该项目的目标是开发一种机器学习模型,以使用简历 (CV) 文本作为输入来预测人们的时薪。
使用上面定义的框架,定义问题很简单。我们可以将X = {x 1 , x 2 , …, x n }定义为用户的 CV,其中每个特征可以以最简单的方式表示该单词出现的次数。那么响应是真实有价值的,我们试图预测个人的时薪(以美元为单位)。
这两个考虑因素足以得出结论,所提出的问题可以用监督回归算法来解决。
问题定义
问题定义可能是大数据分析流程中最复杂且最容易被忽视的阶段之一。为了定义数据产品要解决的问题,经验是必须的。大多数有抱负的数据科学家在这个阶段几乎没有经验。
大多数大数据问题可以按以下方式分类 -
- 监督分类
- 监督回归
- 无监督学习
- 学习排名
现在让我们详细了解这四个概念。
监督分类
给定特征矩阵X = {x 1 , x 2 , ..., x n }我们开发一个模型 M 来预测定义为y = {c 1 , c 2 , ..., cn }的不同类别。例如:给定保险公司客户的交易数据,可以开发一个模型来预测客户是否会流失。后者是一个二元分类问题,其中有两个类或目标变量:流失和非流失。
其他问题涉及预测多个类别,我们可能有兴趣进行数字识别,因此响应向量将定义为:y = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},最先进的模型将是卷积神经网络,特征矩阵将定义为图像的像素。
监督回归
在这种情况下,问题定义与前面的示例非常相似;差异取决于响应。在回归问题中,响应 y ∈ ℜ,这意味着响应是实值。例如,我们可以开发一个模型来根据个人简历的语料库来预测其时薪。
无监督学习
管理层常常渴望新的见解。细分模型可以提供这种洞察力,以便营销部门为不同细分市场开发产品。开发分割模型的一个好方法是选择与所需分割相关的特征,而不是考虑算法。
例如,在一家电信公司,根据手机使用情况对客户进行细分是很有趣的。这将涉及忽略与分割目标无关的特征并仅包含那些与分割目标相关的特征。在这种情况下,这将选择诸如一个月内使用的短信数量、入站和出站分钟数等特征。
学习排名
这个问题可以被认为是回归问题,但它有其特殊性,值得单独处理。该问题涉及给定文档集合,我们寻求在给定查询的情况下找到最相关的排序。为了开发监督学习算法,需要在给定查询的情况下标记排序的相关性。
值得注意的是,为了开发监督学习算法,需要对训练数据进行标记。这意味着,为了训练一个模型来识别图像中的数字,我们需要手动标记大量示例。有一些 Web 服务可以加速此过程,并且通常用于此任务,例如 amazon Mechanical Turk。事实证明,学习算法在提供更多数据时可以提高其性能,因此在监督学习中实际上必须标记相当数量的示例。
大数据分析 - 数据收集
数据收集在大数据周期中发挥着最重要的作用。互联网为各种主题提供了几乎无限的数据源。该领域的重要性取决于业务类型,但传统行业可以获取多种外部数据源并将其与交易数据结合起来。
例如,假设我们想要构建一个推荐餐馆的系统。第一步是收集数据,在本例中是收集来自不同网站的餐馆评论并将其存储在数据库中。由于我们对原始文本感兴趣,并将其用于分析,因此用于开发模型的数据存储在何处并不那么相关。这听起来可能与大数据主要技术相矛盾,但为了实现大数据应用,我们只需要让它实时工作。
推特迷你项目
定义问题后,下一步就是收集数据。以下小型项目的想法是致力于从网络收集数据并将其结构化以用于机器学习模型。我们将使用 R 编程语言从 twitter Rest API 收集一些推文。
首先创建一个 twitter 帐户,然后按照twitteR包vignette中的说明创建一个 twitter 开发者帐户。这是这些说明的摘要 -
填写基本信息后,进入“设置”选项卡,选择“读取、写入和访问私信”。
执行此操作后请务必单击“保存”按钮
在“详细信息”选项卡中,记下您的消费者密钥和消费者秘密
在 R 会话中,您将使用 API 密钥和 API 秘密值
最后运行以下脚本。这将从github 上的存储库安装twitteR包。
install.packages(c("devtools", "rjson", "bit64", "httr")) # Make sure to restart your R session at this point library(devtools) install_github("geoffjentry/twitteR")
我们有兴趣获取包含字符串“big mac”的数据,并找出哪些主题在此方面脱颖而出。为此,第一步是从 Twitter 收集数据。下面是我们的 R 脚本,用于从 Twitter 收集所需的数据。此代码也可以在 bda/part1/collect_data/collect_data_twitter.R 文件中找到。
rm(list = ls(all = TRUE)); gc() # Clears the global environment library(twitteR) Sys.setlocale(category = "LC_ALL", locale = "C") ### Replace the xxx’s with the values you got from the previous instructions # consumer_key = "xxxxxxxxxxxxxxxxxxxx" # consumer_secret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # access_token = "xxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # access_token_secret= "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # Connect to twitter rest API setup_twitter_oauth(consumer_key, consumer_secret, access_token, access_token_secret) # Get tweets related to big mac tweets <- searchTwitter(’big mac’, n = 200, lang = ’en’) df <- twListToDF(tweets) # Take a look at the data head(df) # Check which device is most used sources <- sapply(tweets, function(x) x$getStatusSource()) sources <- gsub("</a>", "", sources) sources <- strsplit(sources, ">") sources <- sapply(sources, function(x) ifelse(length(x) > 1, x[2], x[1])) source_table = table(sources) source_table = source_table[source_table > 1] freq = source_table[order(source_table, decreasing = T)] as.data.frame(freq) # Frequency # Twitter for iPhone 71 # Twitter for Android 29 # Twitter Web Client 25 # recognia 20
大数据分析——清理数据
收集数据后,我们通常会拥有具有不同特征的多种数据源。最直接的步骤是使这些数据源同质化并继续开发我们的数据产品。但是,这取决于数据的类型。我们应该问自己,将数据同质化是否可行。
也许数据来源完全不同,如果来源同质化,信息损失会很大。在这种情况下,我们可以考虑替代方案。一个数据源可以帮助我构建回归模型,而另一个数据源可以帮助我构建分类模型吗?是否有可能利用异质性对我们有利,而不是仅仅丢失信息?做出这些决定使分析变得有趣且具有挑战性。
就评论而言,每个数据源都可以有一种语言。同样,我们有两个选择 -
同质化- 它涉及将不同的语言翻译成我们拥有更多数据的语言。翻译服务的质量是可以接受的,但如果我们想用API翻译大量的数据,成本会很高。有一些软件工具可用于此任务,但成本也很高。
异构化- 是否有可能为每种语言开发一个解决方案?由于检测语料库的语言很简单,我们可以为每种语言开发一个推荐器。这将涉及根据可用语言数量调整每个推荐器的更多工作,但如果我们有几种可用语言,这绝对是一个可行的选择。
推特迷你项目
在本例中,我们需要首先清理非结构化数据,然后将其转换为数据矩阵,以便对其应用主题建模。一般来说,当从 Twitter 获取数据时,有几个我们不感兴趣的字符,至少在数据清理过程的第一阶段是这样。
例如,在获取推文后,我们得到这些奇怪的字符:“<ed><U+00A0><U+00BD><ed><U+00B8><U+008B>”。这些可能是表情符号,因此为了清理数据,我们将使用以下脚本删除它们。此代码也可在 bda/part1/collect_data/cleaning_data.R 文件中找到。
rm(list = ls(all = TRUE)); gc() # Clears the global environment source('collect_data_twitter.R') # Some tweets head(df$text) [1] "I’m not a big fan of turkey but baked Mac & cheese <ed><U+00A0><U+00BD><ed><U+00B8><U+008B>" [2] "@Jayoh30 Like no special sauce on a big mac. HOW" ### We are interested in the text - Let’s clean it! # We first convert the encoding of the text from latin1 to ASCII df$text <- sapply(df$text,function(row) iconv(row, "latin1", "ASCII", sub = "")) # Create a function to clean tweets clean.text <- function(tx) { tx <- gsub("htt.{1,20}", " ", tx, ignore.case = TRUE) tx = gsub("[^#[:^punct:]]|@|RT", " ", tx, perl = TRUE, ignore.case = TRUE) tx = gsub("[[:digit:]]", " ", tx, ignore.case = TRUE) tx = gsub(" {1,}", " ", tx, ignore.case = TRUE) tx = gsub("^\\s+|\\s+$", " ", tx, ignore.case = TRUE) return(tx) } clean_tweets <- lapply(df$text, clean.text) # Cleaned tweets head(clean_tweets) [1] " WeNeedFeminlsm MAC s new make up line features men woc and big girls " [1] " TravelsPhoto What Happens To Your Body One Hour After A Big Mac "
数据清理迷你项目的最后一步是清理文本,我们可以将其转换为矩阵并应用算法。根据clean_tweets向量中存储的文本,我们可以轻松地将其转换为词袋矩阵并应用无监督学习算法。
大数据分析 - 汇总数据
报告在大数据分析中非常重要。每个组织都必须定期提供信息来支持其决策过程。此任务通常由具有 SQL 和 ETL(提取、传输和加载)经验的数据分析师来处理。
负责此任务的团队有责任将大数据分析部门产生的信息传播到组织的不同领域。
以下示例演示了数据汇总的含义。导航到文件夹bda/part1/summarize_data,然后在该文件夹内双击summarize_data.Rproj文件将其打开。然后,打开Summarize_data.R脚本并查看代码,并按照提供的说明进行操作。
# Install the following packages by running the following code in R. pkgs = c('data.table', 'ggplot2', 'nycflights13', 'reshape2') install.packages(pkgs)
ggplot2包非常适合数据可视化。data.table包是在R中进行快速且内存高效的汇总的绝佳选择。最近的基准测试显示它甚至比用于类似任务的 python 库pandas还要快。
使用以下代码查看数据。此代码也可在bda/part1/summarize_data/summarize_data.Rproj文件中找到。
library(nycflights13) library(ggplot2) library(data.table) library(reshape2) # Convert the flights data.frame to a data.table object and call it DT DT <- as.data.table(flights) # The data has 336776 rows and 16 columns dim(DT) # Take a look at the first rows head(DT) # year month day dep_time dep_delay arr_time arr_delay carrier # 1: 2013 1 1 517 2 830 11 UA # 2: 2013 1 1 533 4 850 20 UA # 3: 2013 1 1 542 2 923 33 AA # 4: 2013 1 1 544 -1 1004 -18 B6 # 5: 2013 1 1 554 -6 812 -25 DL # 6: 2013 1 1 554 -4 740 12 UA # tailnum flight origin dest air_time distance hour minute # 1: N14228 1545 EWR IAH 227 1400 5 17 # 2: N24211 1714 LGA IAH 227 1416 5 33 # 3: N619AA 1141 JFK MIA 160 1089 5 42 # 4: N804JB 725 JFK BQN 183 1576 5 44 # 5: N668DN 461 LGA ATL 116 762 5 54 # 6: N39463 1696 EWR ORD 150 719 5 54
下面的代码有一个数据汇总的例子。
### Data Summarization # Compute the mean arrival delay DT[, list(mean_arrival_delay = mean(arr_delay, na.rm = TRUE))] # mean_arrival_delay # 1: 6.895377 # Now, we compute the same value but for each carrier mean1 = DT[, list(mean_arrival_delay = mean(arr_delay, na.rm = TRUE)), by = carrier] print(mean1) # carrier mean_arrival_delay # 1: UA 3.5580111 # 2: AA 0.3642909 # 3: B6 9.4579733 # 4: DL 1.6443409 # 5: EV 15.7964311 # 6: MQ 10.7747334 # 7: US 2.1295951 # 8: WN 9.6491199 # 9: VX 1.7644644 # 10: FL 20.1159055 # 11: AS -9.9308886 # 12: 9E 7.3796692 # 13: F9 21.9207048 # 14: HA -6.9152047 # 15: YV 15.5569853 # 16: OO 11.9310345 # Now let’s compute to means in the same line of code mean2 = DT[, list(mean_departure_delay = mean(dep_delay, na.rm = TRUE), mean_arrival_delay = mean(arr_delay, na.rm = TRUE)), by = carrier] print(mean2) # carrier mean_departure_delay mean_arrival_delay # 1: UA 12.106073 3.5580111 # 2: AA 8.586016 0.3642909 # 3: B6 13.022522 9.4579733 # 4: DL 9.264505 1.6443409 # 5: EV 19.955390 15.7964311 # 6: MQ 10.552041 10.7747334 # 7: US 3.782418 2.1295951 # 8: WN 17.711744 9.6491199 # 9: VX 12.869421 1.7644644 # 10: FL 18.726075 20.1159055 # 11: AS 5.804775 -9.9308886 # 12: 9E 16.725769 7.3796692 # 13: F9 20.215543 21.9207048 # 14: HA 4.900585 -6.9152047 # 15: YV 18.996330 15.5569853 # 16: OO 12.586207 11.9310345 ### Create a new variable called gain # this is the difference between arrival delay and departure delay DT[, gain:= arr_delay - dep_delay] # Compute the median gain per carrier median_gain = DT[, median(gain, na.rm = TRUE), by = carrier] print(median_gain)
大数据分析 - 数据探索
探索性数据分析是 John Tuckey (1977) 提出的概念,它基于统计学的新视角。塔基的想法是,在传统统计学中,数据并没有以图形方式进行探索,而只是用于检验假设。开发工具的第一次尝试是在斯坦福大学完成的,该项目被称为prim9。该工具能够在九个维度上可视化数据,因此能够提供数据的多变量视角。
近年来,探索性数据分析是必须的,并且已被纳入大数据分析生命周期。强大的 EDA 能力可以增强在组织中发现洞察力并有效沟通的能力。
基于塔基的想法,贝尔实验室开发了S编程语言,以提供用于统计的交互界面。S 的想法是通过易于使用的语言提供广泛的图形功能。当今世界,在大数据的背景下,基于S编程语言的R是最流行的分析软件。
以下程序演示了探索性数据分析的使用。
以下是探索性数据分析的示例。此代码也可在part1/eda/exploratory_data_analysis.R文件中找到。
library(nycflights13) library(ggplot2) library(data.table) library(reshape2) # Using the code from the previous section # This computes the mean arrival and departure delays by carrier. DT <- as.data.table(flights) mean2 = DT[, list(mean_departure_delay = mean(dep_delay, na.rm = TRUE), mean_arrival_delay = mean(arr_delay, na.rm = TRUE)), by = carrier] # In order to plot data in R usign ggplot, it is normally needed to reshape the data # We want to have the data in long format for plotting with ggplot dt = melt(mean2, id.vars = ’carrier’) # Take a look at the first rows print(head(dt)) # Take a look at the help for ?geom_point and geom_line to find similar examples # Here we take the carrier code as the x axis # the value from the dt data.table goes in the y axis # The variable column represents the color p = ggplot(dt, aes(x = carrier, y = value, color = variable, group = variable)) + geom_point() + # Plots points geom_line() + # Plots lines theme_bw() + # Uses a white background labs(list(title = 'Mean arrival and departure delay by carrier', x = 'Carrier', y = 'Mean delay')) print(p) # Save the plot to disk ggsave('mean_delay_by_carrier.png', p, width = 10.4, height = 5.07)
该代码应生成如下所示的图像 -
大数据分析 - 数据可视化
为了理解数据,将其可视化通常很有用。通常在大数据应用中,人们的兴趣在于寻找洞察力,而不仅仅是制作漂亮的图表。以下是使用绘图理解数据的不同方法的示例。
要开始分析航班数据,我们可以首先检查数值变量之间是否存在相关性。此代码也可在bda/part1/data_visualization/data_visualization.R文件中找到。
# Install the package corrplot by running install.packages('corrplot') # then load the library library(corrplot) # Load the following libraries library(nycflights13) library(ggplot2) library(data.table) library(reshape2) # We will continue working with the flights data DT <- as.data.table(flights) head(DT) # take a look # We select the numeric variables after inspecting the first rows. numeric_variables = c('dep_time', 'dep_delay', 'arr_time', 'arr_delay', 'air_time', 'distance') # Select numeric variables from the DT data.table dt_num = DT[, numeric_variables, with = FALSE] # Compute the correlation matrix of dt_num cor_mat = cor(dt_num, use = "complete.obs") print(cor_mat) ### Here is the correlation matrix # dep_time dep_delay arr_time arr_delay air_time distance # dep_time 1.00000000 0.25961272 0.66250900 0.23230573 -0.01461948 -0.01413373 # dep_delay 0.25961272 1.00000000 0.02942101 0.91480276 -0.02240508 -0.02168090 # arr_time 0.66250900 0.02942101 1.00000000 0.02448214 0.05429603 0.04718917 # arr_delay 0.23230573 0.91480276 0.02448214 1.00000000 -0.03529709 -0.06186776 # air_time -0.01461948 -0.02240508 0.05429603 -0.03529709 1.00000000 0.99064965 # distance -0.01413373 -0.02168090 0.04718917 -0.06186776 0.99064965 1.00000000 # We can display it visually to get a better understanding of the data corrplot.mixed(cor_mat, lower = "circle", upper = "ellipse") # save it to disk png('corrplot.png') print(corrplot.mixed(cor_mat, lower = "circle", upper = "ellipse")) dev.off()
此代码生成以下相关矩阵可视化 -
我们可以在图中看到数据集中的一些变量之间存在很强的相关性。例如,到达延误和出发延误似乎高度相关。我们可以看到这一点,因为椭圆显示两个变量之间几乎呈线性关系,但是,从这个结果中找到因果关系并不容易。
我们不能说,当两个变量相关时,一个变量就会影响另一个变量。此外,我们在图中发现飞行时间和距离之间存在很强的相关性,这是相当合理的预期,因为随着距离的增加,飞行时间应该会增加。
我们还可以对数据进行单变量分析。箱形图是可视化分布的一种简单有效的方法。以下代码演示了如何使用 ggplot2 库生成箱线图和网格图。此代码也可在bda/part1/data_visualization/boxplots.R文件中找到。
source('data_visualization.R') ### Analyzing Distributions using box-plots # The following shows the distance as a function of the carrier p = ggplot(DT, aes(x = carrier, y = distance, fill = carrier)) + # Define the carrier in the x axis and distance in the y axis geom_box-plot() + # Use the box-plot geom theme_bw() + # Leave a white background - More in line with tufte's principles than the default guides(fill = FALSE) + # Remove legend labs(list(title = 'Distance as a function of carrier', # Add labels x = 'Carrier', y = 'Distance')) p # Save to disk png(‘boxplot_carrier.png’) print(p) dev.off() # Let's add now another variable, the month of each flight # We will be using facet_wrap for this p = ggplot(DT, aes(carrier, distance, fill = carrier)) + geom_box-plot() + theme_bw() + guides(fill = FALSE) + facet_wrap(~month) + # This creates the trellis plot with the by month variable labs(list(title = 'Distance as a function of carrier by month', x = 'Carrier', y = 'Distance')) p # The plot shows there aren't clear differences between distance in different months # Save to disk png('boxplot_carrier_by_month.png') print(p) dev.off()
大数据分析 - R 简介
本节专门向用户介绍 R 编程语言。R可以从cran网站下载。对于 Windows 用户,安装 rtools和rstudio IDE非常有用。
R背后的一般概念是充当用 C、C++ 和 Fortran 等编译语言开发的其他软件的接口,并为用户提供分析数据的交互式工具。
导航到书籍 zip 文件bda/part2/R_introduction的文件夹并打开R_introduction.Rproj文件。这将打开 RStudio 会话。然后打开 01_vectors.R 文件。逐行运行脚本并按照代码中的注释进行操作。学习的另一个有用选项是仅键入代码,这将帮助您习惯 R 语法。在 R 中,注释是用 # 符号编写的。
为了显示书中R代码的运行结果,在代码评估后,对R返回的结果进行了注释。这样,您就可以复制粘贴书中的代码,并直接在 R 中尝试其中的部分内容。
# Create a vector of numbers numbers = c(1, 2, 3, 4, 5) print(numbers) # [1] 1 2 3 4 5 # Create a vector of letters ltrs = c('a', 'b', 'c', 'd', 'e') # [1] "a" "b" "c" "d" "e" # Concatenate both mixed_vec = c(numbers, ltrs) print(mixed_vec) # [1] "1" "2" "3" "4" "5" "a" "b" "c" "d" "e"
我们来分析一下前面的代码发生了什么。我们可以看到可以用数字和字母创建向量。我们不需要事先告诉 R 我们想要什么类型的数据类型。最后,我们能够创建一个包含数字和字母的向量。向量 mix_vec 已将数字强制转换为字符,我们可以通过可视化值如何打印在引号内来看到这一点。
以下代码显示了函数类返回的不同向量的数据类型。通常使用 class 函数来“询问”一个对象,询问他的类是什么。
### Evaluate the data types using class ### One dimensional objects # Integer vector num = 1:10 class(num) # [1] "integer" # Numeric vector, it has a float, 10.5 num = c(1:10, 10.5) class(num) # [1] "numeric" # Character vector ltrs = letters[1:10] class(ltrs) # [1] "character" # Factor vector fac = as.factor(ltrs) class(fac) # [1] "factor"
R 还支持二维对象。在下面的代码中,有 R 中使用的两种最流行的数据结构的示例:矩阵和 data.frame。
# Matrix M = matrix(1:12, ncol = 4) # [,1] [,2] [,3] [,4] # [1,] 1 4 7 10 # [2,] 2 5 8 11 # [3,] 3 6 9 12 lM = matrix(letters[1:12], ncol = 4) # [,1] [,2] [,3] [,4] # [1,] "a" "d" "g" "j" # [2,] "b" "e" "h" "k" # [3,] "c" "f" "i" "l" # Coerces the numbers to character # cbind concatenates two matrices (or vectors) in one matrix cbind(M, lM) # [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] # [1,] "1" "4" "7" "10" "a" "d" "g" "j" # [2,] "2" "5" "8" "11" "b" "e" "h" "k" # [3,] "3" "6" "9" "12" "c" "f" "i" "l" class(M) # [1] "matrix" class(lM) # [1] "matrix" # data.frame # One of the main objects of R, handles different data types in the same object. # It is possible to have numeric, character and factor vectors in the same data.frame df = data.frame(n = 1:5, l = letters[1:5]) df # n l # 1 1 a # 2 2 b # 3 3 c # 4 4 d # 5 5 e
如前面的示例所示,可以在同一对象中使用不同的数据类型。一般来说,这就是数据在数据库中的呈现方式,API 部分数据是文本或字符向量和其他数字。分析师的工作是确定分配哪种统计数据类型,然后为其使用正确的 R 数据类型。在统计学中,我们通常认为变量有以下类型 -
- 数字
- 名义或绝对
- 序数
在 R 中,向量可以属于以下类别 -
- 数字 - 整数
- 因素
- 有序因子
R 为每种统计类型的变量提供了一种数据类型。然而,有序因子很少使用,但可以通过函数因子创建或有序。
以下部分讨论索引的概念。这是一个非常常见的操作,处理选择对象的部分并对它们进行转换的问题。
# Let's create a data.frame df = data.frame(numbers = 1:26, letters) head(df) # numbers letters # 1 1 a # 2 2 b # 3 3 c # 4 4 d # 5 5 e # 6 6 f # str gives the structure of a data.frame, it’s a good summary to inspect an object str(df) # 'data.frame': 26 obs. of 2 variables: # $ numbers: int 1 2 3 4 5 6 7 8 9 10 ... # $ letters: Factor w/ 26 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10 ... # The latter shows the letters character vector was coerced as a factor. # This can be explained by the stringsAsFactors = TRUE argumnet in data.frame # read ?data.frame for more information class(df) # [1] "data.frame" ### Indexing # Get the first row df[1, ] # numbers letters # 1 1 a # Used for programming normally - returns the output as a list df[1, , drop = TRUE] # $numbers # [1] 1 # # $letters # [1] a # Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z # Get several rows of the data.frame df[5:7, ] # numbers letters # 5 5 e # 6 6 f # 7 7 g ### Add one column that mixes the numeric column with the factor column df$mixed = paste(df$numbers, df$letters, sep = ’’) str(df) # 'data.frame': 26 obs. of 3 variables: # $ numbers: int 1 2 3 4 5 6 7 8 9 10 ... # $ letters: Factor w/ 26 levels "a","b","c","d",..: 1 2 3 4 5 6 7 8 9 10 ... # $ mixed : chr "1a" "2b" "3c" "4d" ... ### Get columns # Get the first column df[, 1] # It returns a one dimensional vector with that column # Get two columns df2 = df[, 1:2] head(df2) # numbers letters # 1 1 a # 2 2 b # 3 3 c # 4 4 d # 5 5 e # 6 6 f # Get the first and third columns df3 = df[, c(1, 3)] df3[1:3, ] # numbers mixed # 1 1 1a # 2 2 2b # 3 3 3c ### Index columns from their names names(df) # [1] "numbers" "letters" "mixed" # This is the best practice in programming, as many times indeces change, but variable names don’t # We create a variable with the names we want to subset keep_vars = c("numbers", "mixed") df4 = df[, keep_vars] head(df4) # numbers mixed # 1 1 1a # 2 2 2b # 3 3 3c # 4 4 4d # 5 5 5e # 6 6 6f ### subset rows and columns # Keep the first five rows df5 = df[1:5, keep_vars] df5 # numbers mixed # 1 1 1a # 2 2 2b # 3 3 3c # 4 4 4d # 5 5 5e # subset rows using a logical condition df6 = df[df$numbers < 10, keep_vars] df6 # numbers mixed # 1 1 1a # 2 2 2b # 3 3 3c # 4 4 4d # 5 5 5e # 6 6 6f # 7 7 7g # 8 8 8h # 9 9 9i
大数据分析 - SQL 简介
SQL 代表结构化查询语言。它是传统数据仓库和大数据技术中使用最广泛的从数据库中提取数据的语言之一。为了演示 SQL 的基础知识,我们将使用示例。为了专注于语言本身,我们将在 R 中使用 SQL。就编写 SQL 代码而言,这与在数据库中完成的操作完全相同。
SQL的核心是三个语句:SELECT、FROM和WHERE。以下示例利用了最常见的 SQL 用例。导航到文件夹bda/part2/SQL_introduction并打开SQL_introduction.Rproj文件。然后打开01_select.R脚本。为了在 R 中编写 SQL 代码,我们需要安装sqldf包,如以下代码所示。
# Install the sqldf package install.packages('sqldf') # load the library library('sqldf') library(nycflights13) # We will be working with the fligths dataset in order to introduce SQL # Let’s take a look at the table str(flights) # Classes 'tbl_d', 'tbl' and 'data.frame': 336776 obs. of 16 variables: # $ year : int 2013 2013 2013 2013 2013 2013 2013 2013 2013 2013 ... # $ month : int 1 1 1 1 1 1 1 1 1 1 ... # $ day : int 1 1 1 1 1 1 1 1 1 1 ... # $ dep_time : int 517 533 542 544 554 554 555 557 557 558 ... # $ dep_delay: num 2 4 2 -1 -6 -4 -5 -3 -3 -2 ... # $ arr_time : int 830 850 923 1004 812 740 913 709 838 753 ... # $ arr_delay: num 11 20 33 -18 -25 12 19 -14 -8 8 ... # $ carrier : chr "UA" "UA" "AA" "B6" ... # $ tailnum : chr "N14228" "N24211" "N619AA" "N804JB" ... # $ flight : int 1545 1714 1141 725 461 1696 507 5708 79 301 ... # $ origin : chr "EWR" "LGA" "JFK" "JFK" ... # $ dest : chr "IAH" "IAH" "MIA" "BQN" ... # $ air_time : num 227 227 160 183 116 150 158 53 140 138 ... # $ distance : num 1400 1416 1089 1576 762 ... # $ hour : num 5 5 5 5 5 5 5 5 5 5 ... # $ minute : num 17 33 42 44 54 54 55 57 57 58 ...
select 语句用于从表中检索列并对它们进行计算。ej1中演示了最简单的 SELECT 语句。我们还可以创建新变量,如ej2所示。
### SELECT statement ej1 = sqldf(" SELECT dep_time ,dep_delay ,arr_time ,carrier ,tailnum FROM flights ") head(ej1) # dep_time dep_delay arr_time carrier tailnum # 1 517 2 830 UA N14228 # 2 533 4 850 UA N24211 # 3 542 2 923 AA N619AA # 4 544 -1 1004 B6 N804JB # 5 554 -6 812 DL N668DN # 6 554 -4 740 UA N39463 # In R we can use SQL with the sqldf function. It works exactly the same as in a database # The data.frame (in this case flights) represents the table we are querying and goes in the FROM statement # We can also compute new variables in the select statement using the syntax: # old_variables as new_variable ej2 = sqldf(" SELECT arr_delay - dep_delay as gain, carrier FROM flights ") ej2[1:5, ] # gain carrier # 1 9 UA # 2 16 UA # 3 31 AA # 4 -17 B6 # 5 -19 DL
SQL 最常用的功能之一是 group by 语句。这允许计算另一个变量的不同组的数值。打开脚本 02_group_by.R。
### GROUP BY # Computing the average ej3 = sqldf(" SELECT avg(arr_delay) as mean_arr_delay, avg(dep_delay) as mean_dep_delay, carrier FROM flights GROUP BY carrier ") # mean_arr_delay mean_dep_delay carrier # 1 7.3796692 16.725769 9E # 2 0.3642909 8.586016 AA # 3 -9.9308886 5.804775 AS # 4 9.4579733 13.022522 B6 # 5 1.6443409 9.264505 DL # 6 15.7964311 19.955390 EV # 7 21.9207048 20.215543 F9 # 8 20.1159055 18.726075 FL # 9 -6.9152047 4.900585 HA # 10 10.7747334 10.552041 MQ # 11 11.9310345 12.586207 OO # 12 3.5580111 12.106073 UA # 13 2.1295951 3.782418 US # 14 1.7644644 12.869421 VX # 15 9.6491199 17.711744 WN # 16 15.5569853 18.996330 YV # Other aggregations ej4 = sqldf(" SELECT avg(arr_delay) as mean_arr_delay, min(dep_delay) as min_dep_delay, max(dep_delay) as max_dep_delay, carrier FROM flights GROUP BY carrier ") # We can compute the minimun, mean, and maximum values of a numeric value ej4 # mean_arr_delay min_dep_delay max_dep_delay carrier # 1 7.3796692 -24 747 9E # 2 0.3642909 -24 1014 AA # 3 -9.9308886 -21 225 AS # 4 9.4579733 -43 502 B6 # 5 1.6443409 -33 960 DL # 6 15.7964311 -32 548 EV # 7 21.9207048 -27 853 F9 # 8 20.1159055 -22 602 FL # 9 -6.9152047 -16 1301 HA # 10 10.7747334 -26 1137 MQ # 11 11.9310345 -14 154 OO # 12 3.5580111 -20 483 UA # 13 2.1295951 -19 500 US # 14 1.7644644 -20 653 VX # 15 9.6491199 -13 471 WN # 16 15.5569853 -16 387 YV ### We could be also interested in knowing how many observations each carrier has ej5 = sqldf(" SELECT carrier, count(*) as count FROM flights GROUP BY carrier ") ej5 # carrier count # 1 9E 18460 # 2 AA 32729 # 3 AS 714 # 4 B6 54635 # 5 DL 48110 # 6 EV 54173 # 7 F9 685 # 8 FL 3260 # 9 HA 342 # 10 MQ 26397 # 11 OO 32 # 12 UA 58665 # 13 US 20536 # 14 VX 5162 # 15 WN 12275 # 16 YV 601
SQL 最有用的功能是连接。连接意味着我们想要将表 A 和表 B 组合在一张表中,使用一列来匹配两个表的值。实际上,连接有不同类型,首先这些将是最有用的:内连接和左外连接。
# Let’s create two tables: A and B to demonstrate joins. A = data.frame(c1 = 1:4, c2 = letters[1:4]) B = data.frame(c1 = c(2,4,5,6), c2 = letters[c(2:5)]) A # c1 c2 # 1 a # 2 b # 3 c # 4 d B # c1 c2 # 2 b # 4 c # 5 d # 6 e ### INNER JOIN # This means to match the observations of the column we would join the tables by. inner = sqldf(" SELECT A.c1, B.c2 FROM A INNER JOIN B ON A.c1 = B.c1 ") # Only the rows that match c1 in both A and B are returned inner # c1 c2 # 2 b # 4 c ### LEFT OUTER JOIN # the left outer join, sometimes just called left join will return the # first all the values of the column used from the A table left = sqldf(" SELECT A.c1, B.c2 FROM A LEFT OUTER JOIN B ON A.c1 = B.c1 ") # Only the rows that match c1 in both A and B are returned left # c1 c2 # 1 <NA> # 2 b # 3 <NA> # 4 c
大数据分析 - 图表和图形
分析数据的第一种方法是对其进行可视化分析。这样做的目标通常是找到变量和变量的单变量描述之间的关系。我们可以将这些策略分为 -
- 单变量分析
- 多变量分析
单变量图形方法
单变量是一个统计术语。在实践中,这意味着我们想要独立于其余数据来分析变量。允许有效地做到这一点的图是 -
箱线图
箱线图通常用于比较分布。这是直观检查分布之间是否存在差异的好方法。我们可以看看不同切工的钻石价格是否存在差异。
# We will be using the ggplot2 library for plotting library(ggplot2) data("diamonds") # We will be using the diamonds dataset to analyze distributions of numeric variables head(diamonds) # carat cut color clarity depth table price x y z # 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 # 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 # 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31 # 4 0.29 Premium I VS2 62.4 58 334 4.20 4.23 2.63 # 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 # 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 ### Box-Plots p = ggplot(diamonds, aes(x = cut, y = price, fill = cut)) + geom_box-plot() + theme_bw() print(p)
我们可以在图中看到不同切工类型的钻石价格分布存在差异。
直方图
source('01_box_plots.R') # We can plot histograms for each level of the cut factor variable using facet_grid p = ggplot(diamonds, aes(x = price, fill = cut)) + geom_histogram() + facet_grid(cut ~ .) + theme_bw() p # the previous plot doesn’t allow to visuallize correctly the data because of the differences in scale # we can turn this off using the scales argument of facet_grid p = ggplot(diamonds, aes(x = price, fill = cut)) + geom_histogram() + facet_grid(cut ~ ., scales = 'free') + theme_bw() p png('02_histogram_diamonds_cut.png') print(p) dev.off()
上述代码的输出如下 -
多元图形方法
探索性数据分析中的多变量图形方法的目的是发现不同变量之间的关系。有两种常用方法可以实现此目的:绘制数值变量的相关矩阵或简单地绘制原始 d