This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
<audio id="audio" title="01丨数据分析全景图及修炼指南" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/af/41/af26f7ef28052417304d5cde188cef41.mp3"></audio>
今天我们的学习正式开始,我想先给你一张数据分析的全景图,让你对后面的学习做到心中有数。
现在,你已经知道了数据分析在现代社会中的重要地位。掌握数据,就是掌握规律。当你了解了市场数据,对它进行分析,就可以得到市场规律。当你掌握了产品自身的数据,对它进行分析,就可以了解产品的用户来源、用户画像等等。所以说数据是个全新的视角。数据分析如此重要,它不仅是新时代的“数据结构+算法”,也更是企业争夺人才的高地。
## 当我们谈论数据分析的时候,都在讲些什么呢?
这里我可以把数据分析分成三个重要的组成部分。
<li>
**数据采集**。它是我们的原材料,也是最“**接地气**”的部分,因为任何分析都要有数据源。
</li>
<li>
**数据挖掘**。它可以说是最“**高大上**”的部分,也是整个商业价值所在。之所以要进行数据分析,就是要找到其中的规律,来指导我们的业务。因此**数据挖掘的核心是挖掘数据的商业价值也就是我们所谈的商业智能BI**。
</li>
<li>
**数据可视化**。它可以说是数据领域中**万金油**的技能,可以让我们直观地了解到数据分析的结果。
</li>
<img src="https://static001.geekbang.org/resource/image/58/68/58a51714cf4fec4ee8f4f66fdb6a5d68.jpg" alt="">
下面我来一一为你讲解一下这三个重要的部分。
## 数据采集
在数据采集部分中,你通常会和数据源打交道,然后使用工具进行采集。
在专栏里我会告诉你都有哪些常用的数据源以及如何获取它们。另外在工具使用中你也将掌握“八爪鱼”这个自动抓取的神器它可以帮你抓取99%的页面源。当然我也会教你如何编写Python爬虫。掌握Python爬虫的乐趣是无穷的。它不仅能让你获取微博上的热点评论自动下载例如“王祖贤”的海报还能自动给微博加粉丝让你掌握自动化的快感。
<img src="https://static001.geekbang.org/resource/image/80/c9/802ba8473014eba2b4431c85a77336c9.jpg" alt="">
## 数据挖掘
第二个部分是数据挖掘,它可以说是知识型的工程,相当于整个专栏中的“算法”部分。首先你要知道它的基本流程、十大算法、以及背后的数学基础。
这一部分我们会接触到一些概念比如关联分析Adaboost算法等等你可能对这些概念还是一知半解没有关系我会详细为你介绍这些“朋友”。
每讲完一个算法原理,我都会带你做一个项目的实战,我精选了一些典型的、有趣的项目,比如对泰坦尼克号乘客进行生存预测、对文档进行自动分类、以及导演是如何选择演员的等等。
掌握了数据挖掘,就好比手握水晶球一样,它会通过历史数据,告诉你未来会发生什么。当然它也会告诉你这件事发生的置信度是怎样的,置信度这个词你先记住就可以了,后面我们来学习它具体代表什么。
<img src="https://static001.geekbang.org/resource/image/12/a3/1267e0d928f16f4a33b62478e909e9a3.jpg" alt="">
## 数据可视化
第三个就是数据可视化,这是一个非常重要的步骤,也是我们特别感兴趣的一个步骤。数据往往是隐性的,尤其是当数据量大的时候很难感知,可视化可以帮我们很好地理解这些数据的结构,以及分析结果的呈现。
如何进行数据可视化呢?有两种方法。
**第一种就是使用Python**。在Python对数据进行清洗、挖掘的过程中我们可以使用Matplotlib、Seaborn等第三方库进行呈现。
**第二种就是使用第三方工具**。如果你已经生成了csv格式文件想要采用所见即所得的方式进行呈现可以采用微图、DataV、Data GIF Maker等第三方工具它们可以很方便地对数据进行处理还可以帮你制作呈现的效果。
数据采集和数据可视化的原理简单,容易理解。这两个部分注重的是工具的掌握,所以我会把重点放在讲解工具以及应用实战上。
<img src="https://static001.geekbang.org/resource/image/c2/af/c2febe187b3c27b1965c765ea50236af.jpg" alt="">
虽然这些理论我会给你一一讲解,但纸上得来终觉浅,绝知此事要躬行。手拿地图,我们知道要去哪里,但是怎么去呢?我认为学习数据分析最好的方法是:**在工具中灵活运用,在项目中加深理解**。
## 修炼指南
刚才我们讲了数据分析全景图,包括数据采集、数据挖掘、数据可视化这三个部分。你可能觉得东西很多,无从下手,或者感觉数据挖掘涉及好多算法,有点“高深莫测”,掌握起来是不是会吃力。其实这些都是不必要的烦恼。
开篇词里我给你介绍了MAS学习法有了这个方法学习数据分析就是从“思维”到“工具”再到“实践”的一个过程。今天我会从更多的角度来和你分享我的学习经验我们可以把今天的内容叫作“修炼指南”。
借用傅盛的话来说,人与人最大的差别在于“认知”,所谓成长就是认知的升级。
很多人存在对“认知“的误解,认为认知不就是概念么?那么你有没有想过,针对同一个概念,为什么不同的人掌握的程度是不一样的呢?
**我们只有把知识转化为自己的语言,它才真正变成了我们自己的东西**。这个转换的过程,就是认知的过程。
<img src="https://static001.geekbang.org/resource/image/13/8c/1395ed64eca6bbd6dc2a413d0f1f7c8c.jpg" alt="">
那么如何提升自己的学习吸收能力呢?简单地说,就是要“知行合一”。
**如果说认知是大脑,那么工具就好比我们的双手**,数据工程师和算法科学家每天打交道最多的就是工具。
如果你开始做数据分析的项目,你脑海中已经思考好了数据挖掘的算法模型,请牢记下面这两点原则。
**1.不重复造轮子**
举个数据采集的例子我见过很多公司都有数据采集的需求他们认为某些工具不能满足他们个性化的需求因此决定招人专门做这项工作。而结果怎样呢做了1年多的实践工资投入几十万结果发现Bug一大堆最后还是选择了第三方工具。耗时耗力还没什么成效。
一个模型是否有相关的类库可以使用——这几乎是每个程序员入行被告知的第一条准则。我也会对新人反复灌输这个概念。大部分情况下你都能找到类库来完成你的想法。
**2.工具决定效率**
“不要重复造轮子”意味着首先需要找到一个可以用的轮子,也就是工具。我们该如何选择呢?
这取决于你要做的工作,工具没有好坏之分,只有适合与否。除去研究型的工作,大部分情况下,**工程师会选择使用者最多的工具。因为Bug少、文档全、案例多。**
比如Python在处理数据挖掘上就有很多第三方库这些库都有大量的用户和帮助文档可以帮助你来上手。
在后面的课程里,我会给你介绍最常用的工具,这些工具会让你的数据挖掘事半功倍。
选择好工具之后,你要做的就是积累 “资产”了。我们很难记住大段的知识点,也背不下来工具的指令,但是我们通常能记住故事、做过的项目、做过的题目。这些题目和项目是你最先行的“资产”。
如何快速积累这些“资产”呢?这里我送你三个字:**熟练度**。
把题目完成只是第一步,关键在于训练我们工具使用的“熟练度”。
高中的时候有一次我做“八皇后”的问题第一次解答花了一个小时的时间。当时老师明确告诉我必须在20分钟内完成我不敢相信从解题、思考、动手最后完成1个小时不算慢。但是后来我调整了思考的结构。最后我6分钟就可以完成那道题。
当熟练度增加的时候,你的思考认知模型也在逐渐提升。所以专栏中,我给你做了一个 “**专属题库**”,在专属题库中你可以进行自我评测,当然我也会对这些练习题进行讲解。在工作篇中,我也会和你一起分享面试技巧、探讨职场上的晋升之路。
## 总结
认知三步曲,从认知到工具,再到实战,是我最想给你分享的学习建议。我看到过很多同学上课的模式,以及很多人工作中的思考模式,我特别认同“人与人最大的区别是在认知”这个观点。
他们很听老师的理论但是这些理论最后又都还给了老师。所以我希望你在后面的15周学习里可以做到以下几点。
<li>
**记录下你每天的认知**。尤其是每次课程后,对知识点的自我理解。
</li>
<li>
**这些认知对应工具的哪些操作**。用工具来表达你对知识点的掌握,并用自己的语言记录下这些操作笔记。
</li>
<li>
**做更多练习来巩固你的认知**。我们学习的内容对于大部分外人来说,就像“开车”一样,很酷。我们学习的内容,对于要掌握的人来说,也像“开车”一样,其实并不难,而且很多人已经上路了。你需要的就是更多的练习。
</li>
不知道这一讲中你有没有不清楚的地方,如果有,一定要提问,而且问题越具体越好,我会在留言区和你讨论。如果你理解了我们讲的内容,也一定要分享给我,让我和你一起体验这种认知升级的喜悦。
最后我想问你个问题,就当做个小调查吧,你平时是怎么学习的呢?会做学习笔记吗?期待在留言区看到你的答案。也欢迎你把今天的内容分享给身边的朋友,和他一起学习。

View File

@@ -0,0 +1,140 @@
<audio id="audio" title="02丨学习数据挖掘的最佳路径是什么" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/10/b5/10da36850ed14fd1845b5ad10a935ab5.mp3"></audio>
上一节中,我给你分享了数据分析的全景图,其中最关键的部分就是数据挖掘,那什么是数据挖掘呢?
想象一下,茫茫的大海上,孤零零地屹立着钻井,想要从大海中开采出宝贵的石油。
对于普通人来说,大海是很难感知的,就更不用说找到宝藏了。但对于熟练的石油开采人员来说,大海是有坐标的。他们对地质做勘探,分析地质构造,从而发现哪些地方更可能有石油。然后用开采工具,进行深度挖掘,直到打到石油为止。
大海、地质信息、石油对开采人员来说就是数据源、地理位置、以及分析得到的结果。
而我们要做的数据挖掘工作,就好像这个钻井一样,通过分析这些数据,从庞大的数据中发现规律,找到宝藏。
## 数据挖掘,从知识清单开始
我们第一天学开车的时候一定不会直接上路,而是要你先学习基本的知识,然后再进行上车模拟。
只有对知识有全面的认知,才能确保在以后的工作中即使遇到了问题,也可以快速定位问题所在,然后找方法去对应和解决。
所以我列了一个数据挖掘的知识清单,分别是数据挖掘的基本流程、十大算法和数学原理,以此来开启我们的学习之旅。
## 数据挖掘的基本流程
在正式讲数据挖掘知识清单之前,我先和你聊聊数据挖掘的基本流程。
数据挖掘的过程可以分成以下6个步骤。
<li>
**商业理解**:数据挖掘不是我们的目的,我们的目的是更好地帮助业务,所以第一步我们要从商业的角度理解项目需求,在这个基础上,再对数据挖掘的目标进行定义。
</li>
<li>
**数据理解**:尝试收集部分数据,然后对数据进行探索,包括数据描述、数据质量验证等。这有助于你对收集的数据有个初步的认知。
</li>
<li>
**数据准备**:开始收集数据,并对数据进行清洗、数据集成等操作,完成数据挖掘前的准备工作。
</li>
<li>
**模型建立**:选择和应用各种数据挖掘模型,并进行优化,以便得到更好的分类结果。
</li>
<li>
**模型评估**:对模型进行评价,并检查构建模型的每个步骤,确认模型是否实现了预定的商业目标。
</li>
<li>
**上线发布**:模型的作用是从数据中找到金矿,也就是我们所说的“知识”,获得的知识需要转化成用户可以使用的方式,呈现的形式可以是一份报告,也可以是实现一个比较复杂的、可重复的数据挖掘过程。数据挖掘结果如果是日常运营的一部分,那么后续的监控和维护就会变得重要。
</li>
## 数据挖掘的十大算法
为了进行数据挖掘任务数据科学家们提出了各种模型在众多的数据挖掘模型中国际权威的学术组织ICDM the IEEE International Conference on Data Mining评选出了十大经典的算法。
按照不同的目的,我可以将这些算法分成四类,以便你更好的理解。
l **分类算法**C4.5朴素贝叶斯Naive BayesSVMKNNAdaboostCART
l **聚类算法**K-MeansEM
l **关联分析**Apriori
l **连接分析**PageRank
**1. C4.5**
C4.5算法是得票最高的算法可以说是十大算法之首。C4.5是决策树的算法,它创造性地在决策树构造过程中就进行了剪枝,并且可以处理连续的属性,也能对不完整的数据进行处理。它可以说是决策树分类中,具有里程碑式意义的算法。
**2. 朴素贝叶斯Naive Bayes**
朴素贝叶斯模型是基于概率论的原理,它的思想是这样的:对于给出的未知物体想要进行分类,就需要求解在这个未知物体出现的条件下各个类别出现的概率,哪个最大,就认为这个未知物体属于哪个分类。
**3. SVM**
SVM的中文叫支持向量机英文是Support Vector Machine简称SVM。SVM在训练中建立了一个超平面的分类模型。如果你对超平面不理解没有关系我在后面的算法篇会给你进行介绍。
**4. KNN**
KNN也叫K最近邻算法英文是 K-Nearest Neighbor。所谓K近邻就是每个样本都可以用它最接近的K个邻居来代表。如果一个样本它的K个最接近的邻居都属于分类A那么这个样本也属于分类A。
**5. AdaBoost**
Adaboost在训练中建立了一个联合的分类模型。boost在英文中代表提升的意思所以Adaboost是个构建分类器的提升算法。它可以让我们多个弱的分类器组成一个强的分类器所以Adaboost也是一个常用的分类算法。
**6. CART**
CART代表分类和回归树英文是 Classification and Regression Trees。像英文一样它构建了两棵树一棵是分类树另一个是回归树。和C4.5一样,它是一个决策树学习方法。
**7. Apriori**
Apriori是一种挖掘关联规则association rules的算法它通过挖掘频繁项集frequent item sets来揭示物品之间的关联关系被广泛应用到商业挖掘和网络安全等领域中。频繁项集是指经常出现在一起的物品的集合关联规则暗示着两种物品之间可能存在很强的关系。
**8. K-Means**
K-Means 算法是一个聚类算法。你可以这么理解最终我想把物体划分成K类。假设每个类别里面都有个“中心点”即意见领袖它是这个类别的核心。现在我有一个新点要归类这时候就只要计算这个新点与K个中心点的距离距离哪个中心点近就变成了哪个类别。
**9. EM**
EM算法也叫最大期望算法是求参数的最大似然估计的一种方法。原理是这样的假设我们想要评估参数A和参数B在开始状态下二者都是未知的并且知道了A的信息就可以得到B的信息反过来知道了B也就得到了A。可以考虑首先赋予A某个初值以此得到B的估值然后从B的估值出发重新估计A的取值这个过程一直持续到收敛为止。
EM算法经常用于聚类和机器学习领域中。
**10. PageRank**
PageRank起源于论文影响力的计算方式如果一篇文论被引入的次数越多就代表这篇论文的影响力越强。同样PageRank被Google创造性地应用到了网页权重的计算中当一个页面链出的页面越多说明这个页面的“参考文献”越多当这个页面被链入的频率越高说明这个页面被引用的次数越高。基于这个原理我们可以得到网站的权重划分。
算法可以说是数据挖掘的灵魂也是最精华的部分。这10个经典算法在整个数据挖掘领域中的得票最高的后面的一些其他算法也基本上都是在这个基础上进行改进和创新。今天你先对十大算法有一个初步的了解你只需要做到心中有数就可以了具体内容不理解没有关系后面我会详细给你进行讲解。
## 数据挖掘的数学原理
我说了这么多数据挖掘中的经典算法,但是如果你不了解概率论和数理统计,还是很难掌握算法的本质;如果你不懂线性代数,就很难理解矩阵和向量运作在数据挖掘中的价值;如果你没有最优化方法的概念,就对迭代收敛理解不深。所以说,想要更深刻地理解数据挖掘的方法,就非常有必要了解它后背的数学原理。
**1. 概率论与数理统计**
概率论在我们上大学的时候,基本上都学过,不过大学里老师教的内容,偏概率的多一些,统计部分讲得比较少。在数据挖掘里使用到概率论的地方就比较多了。比如条件概率、独立性的概念,以及随机变量、多维随机变量的概念。
很多算法的本质都与概率论相关,所以说概率论与数理统计是数据挖掘的重要数学基础。
**2. 线性代数**
向量和矩阵是线性代数中的重要知识点,它被广泛应用到数据挖掘中,比如我们经常会把对象抽象为矩阵的表示,一幅图像就可以抽象出来是一个矩阵,我们也经常计算特征值和特征向量,用特征向量来近似代表物体的特征。这个是大数据降维的基本思路。
基于矩阵的各种运算以及基于矩阵的理论成熟可以帮我们解决很多实际问题比如PCA方法、SVD方法以及MF、NMF方法等在数据挖掘中都有广泛的应用。
**3. 图论**
社交网络的兴起让图论的应用也越来越广。人与人的关系可以用图论上的两个节点来进行连接节点的度可以理解为一个人的朋友数。我们都听说过人脉的六度理论在Facebook上被证明平均一个人与另一个人的连接只需要3.57个人。当然图论对于网络结构的分析非常有效,同时图论也在关系挖掘和图像分割中有重要的作用。
**4. 最优化方法**
最优化方法相当于机器学习中自我学习的过程,当机器知道了目标,训练后与结果存在偏差就需要迭代调整,那么最优化就是这个调整的过程。一般来说,这个学习和迭代的过程是漫长、随机的。最优化方法的提出就是用更短的时间得到收敛,取得更好的效果。
## 总结
今天我列了下学习数据挖掘你要掌握的知识清单,只有你对数据挖掘的流程、算法、原理有更深的理解,你才能在实际工作中更好地运用,我将在后面的章节中对它们进行一一介绍。
<img src="https://static001.geekbang.org/resource/image/11/d7/1130af6d29d029c470144dfc8610b6d7.jpg" alt="">
最后给你留道思考题吧。
今天我给你讲了如何学习数据挖掘,你从中有什么样的体会呢?如果某电商网站想挖掘商品之间的关联关系,从而提升销售额,你觉得可以采用上面的哪个算法?为什么?
欢迎在留言区和我讨论,也欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事,一起来交流,一起来进步。

View File

@@ -0,0 +1,356 @@
<audio id="audio" title="03丨Python基础语法开始你的Python之旅" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/f7/2e/f75db127bdfcef18a0ed7583d361952e.mp3"></audio>
上一节课我跟你分享了数据挖掘的最佳学习路径相信你对接下来的学习已经心中有数了。今天我们继续预习课我会用三篇文章分别对Python的基础语法、NumPy和Pandas进行讲解带你快速入门Python语言。如果你已经有Python基础了那先恭喜你已经掌握了这门简洁而高效的语言这几节课你可以跳过或者也可以当作复习自己查漏补缺你还可以在留言区分享自己的Python学习和使用心得。
好了你现在心中是不是有个问题要学好数据分析一定要掌握Python吗
我的答案是想学好数据分析你最好掌握Python语言。为什么这么说呢
首先在一份关于开发语言的调查中使用过Python的开发者80%都会把Python作为自己的主要语言。Python已经成为发展最快的主流编程语言从众多开发语言中脱颖而出深受开发者喜爱。其次在数据分析领域中使用Python的开发者是最多的远超其他语言之和。最后Python语言简洁有大量的第三方库功能强大能解决数据分析的大部分问题这一点我下面具体来说。
Python语言最大的优点是简洁它虽然是C语言写的但是摒弃了C语言的指针这就让代码非常简洁明了。同样的一行Python代码甚至相当于5行Java代码。我们读Python代码就像是读英文一样直观这就能让程序员更好地专注在问题解决上而不是在语言本身。
当然除了Python自身的特点Python还有强大的开发者工具。在数据科学领域Python有许多非常著名的工具库比如科学计算工具NumPy和Pandas库深度学习工具Keras和TensorFlow以及机器学习工具Scikit-learn使用率都非常高。
总之如果你想在数据分析、机器学习等数据科学领域有所作为那么掌握一项语言尤其是Python语言的使用是非常有必要的尤其是我们刚提到的这些工具熟练掌握它们会让你事半功倍。
## 安装及IDE环境
了解了为什么要学Python接下来就带你快速开始你的第一个Python程序所以我们先来了解下如何安装和搭建IDE环境。
**Python的版本选择**
Python主要有两个版本 2.7.x和3.x。两个版本之间存在一些差异但并不大它们语法不一样的地方不到10%。
另一个事实就是大部分Python库都同时支持Python 2.7.x和3.x版本。虽然官方称Python2.7只维护到2020年但是我想告诉你的是千万不要忽视Python2.7它的寿命远不止到2020年而且这两年Python2.7还是占据着Python版本的统治地位。一份调查显示在2017年的商业项目中2.7版本依然是主流占到了63.7%即使这两年Python3.x版本使用的增速较快但实际上Python3.x在2008年就已经有了。
那么你可能会问:这两个版本该如何选择呢?
版本选择的标准就是看你的项目是否会依赖于Python2.7的包如果有依赖的就只能使用Python2.7否则你可以用Python 3.x开始全新的项目。
**Python IDE推荐**
确定了版本问题后怎么选择Python IDE呢有众多优秀的选择这里推荐几款。
**1. PyCharm**
这是一个跨平台的Python开发工具可以帮助用户在使用Python时提升效率比如调试、语法高亮、代码跳转、自动完成、智能提示等。
**2. Sublime Text**
SublimeText是个著名的编辑器Sublime Text3基本上可以1秒即启动反应速度很快。同时它对Python的支持也很到位具有代码高亮、语法提示、自动完成等功能。
**3. Vim**
Vim是一个简洁、高效的工具速度很快可以做任何事从来不崩溃。不过Vim相比于Sublime Text上手有一定难度配置起来有些麻烦。
**4. Eclipse+PyDev**
习惯使用Java的人一定对Eclipse这个IDE不陌生那么使用Eclipse+PyDev插件会是一个很好的选择这样熟悉Eclipse的开发者可以轻易上手。
如果上面这些IDE你之前都没有怎么用过那么推荐你使用Sublime Text上手简单反应速度快。
## Python基础语法
环境配置好后我们就来快速学习几个Python必会的基础语法。我假设你是Python零基础但已经有一些其他编程语言的基础。下面我们一一来看。
**输入与输出**
```
name = raw_input(&quot;What's your name?&quot;)
sum = 100+100
print ('hello,%s' %name)
print ('sum = %d' %sum)
```
raw_input是Python2.7的输入函数在python3.x里可以直接使用input赋值给变量nameprint 是输出函数,%name代表变量的数值因为是字符串类型所以在前面用的 %s作为代替。
这是运行结果:
```
What's your name?cy
hello,cy
sum = 200
```
**判断语句if … else …**
```
if score&gt;= 90:
print 'Excellent'
else:
if score &lt; 60:
print 'Fail'
else:
print 'Good Job'
```
if … else … 是经典的判断语句需要注意的是在if expression后面有个冒号同样在else后面也存在冒号。
另外需要注意的是Python不像其他语言一样使用{}或者begin…end来分隔代码块而是采用代码缩进和冒号的方式来区分代码之间的层次关系。所以**代码缩进在Python中是一种语法**如果代码缩进不统一比如有的是tab有的是空格会怎样呢会产生错误或者异常。相同层次的代码一定要采用相同层次的缩进。
**循环语句for … in**
```
sum = 0
for number in range(11):
sum = sum + number
print sum
```
运行结果:
```
55
```
for循环是一种迭代循环机制迭代即重复相同的逻辑操作。如果规定循环的次数我们可以使用range函数它在for循环中比较常用。range(11)代表从0到10不包括11也相当于range(0,11)range里面还可以增加步长比如range(1,11,2)代表的是[1,3,5,7,9]。
**循环语句: while**
```
sum = 0
number = 1
while number &lt; 11:
sum = sum + number
number = number + 1
print sum
```
运行结果:
```
55
```
1到10的求和也可以用while循环来写这里while控制了循环的次数。while循环是条件循环在while循环中对于变量的计算方式更加灵活。因此while循环适合循环次数不确定的循环而for循环的条件相对确定适合固定次数的循环。
**数据类型:列表、元组、字典、集合**
**列表:[]**
```
lists = ['a','b','c']
lists.append('d')
print lists
print len(lists)
lists.insert(0,'mm')
lists.pop()
print lists
```
运行结果:
```
['a', 'b', 'c', 'd']
4
['mm', 'a', 'b', 'c']
```
列表是Python中常用的数据结构相当于数组具有增删改查的功能我们可以使用len()函数获得lists中元素的个数使用append()在尾部添加元素使用insert()在列表中插入元素使用pop()删除尾部的元素。
**元组 (tuple)**
```
tuples = ('tupleA','tupleB')
print tuples[0]
```
运行结果:
```
tupleA
```
元组tuple和list非常类似但是tuple一旦初始化就不能修改。因为不能修改所以没有append(), insert() 这样的方法可以像访问数组一样进行访问比如tuples[0],但不能赋值。
**字典 {dictionary}**
```
# -*- coding: utf-8 -*
#定义一个dictionary
score = {'guanyu':95,'zhangfei':96}
#添加一个元素
score['zhaoyun'] = 98
print score
#删除一个元素
score.pop('zhangfei')
#查看key是否存在
print 'guanyu' in score
#查看一个key对应的值
print score.get('guanyu')
print score.get('yase',99)
```
运行结果:
```
{'guanyu': 95, 'zhaoyun': 98, 'zhangfei': 96}
True
95
99
```
字典其实就是{key, value}多次对同一个key放入value后面的值会把前面的值冲掉同样字典也有增删改查。增加字典的元素相当于赋值比如score[zhaoyun] = 98删除一个元素使用pop查询使用get如果查询的值不存在我们也可以给一个默认值比如score.get(yase,99)。
**集合set**
```
s = set(['a', 'b', 'c'])
s.add('d')
s.remove('b')
print s
print 'c' in s
```
运行结果:
```
set(['a', 'c', 'd'])
True
```
集合set和字典dictory类似不过它只是key的集合不存储value。同样可以增删查增加使用add删除使用remove查询看某个元素是否在这个集合里使用in。
**注释:#**
注释在python中使用#,如果注释中有中文,一般会在代码前添加# -**- coding: utf-8 -**。
如果是多行注释,使用三个单引号,或者三个双引号,比如:
```
# -*- coding: utf-8 -*
'''
这是多行注释,用三个单引号
这是多行注释,用三个单引号
这是多行注释,用三个单引号
'''
```
**引用模块/包import**
```
# 导入一个模块
import model_name
# 导入多个模块
import module_name1,module_name2
# 导入包中指定模块
from package_name import moudule_name
# 导入包中所有模块
from package_name import *
```
Python语言中import的使用很简单直接使用import module_name语句导入即可。这里import的本质是什么呢import的本质是路径搜索。import引用可以是模块module或者包package。
针对module实际上是引用一个.py文件。而针对package可以采用from … import …的方式这里实际上是从一个目录中引用模块这时目录结构中必须带有一个__init__.py文件。
**函数def**
```
def addone(score):
return score + 1
print addone(99)
```
运行结果:
```
100
```
函数代码块以def关键词开头后接函数标识符名称和圆括号在圆括号里是传进来的参数然后通过return进行函数结果得反馈。
**A+B Problem**
上面的讲的这些基础语法我们可以用sumlime text编辑器运行Python代码。另外告诉你一个相当高效的方法你可以充分利用一个刷题进阶的网址 [http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1](http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1) 这是浙江大学ACM的OnlineJudge。
什么是OnlineJudge呢它实际上是一个在线答题系统做题后你可以在后台提交代码然后OnlineJudge会告诉你运行的结果如果结果正确就反馈Accepted如果错误就反馈Wrong Answer。
不要小看这样的题目也会存在编译错误、内存溢出、运行超时等等情况。所以题目对编码的质量要求还是挺高的。下面我就给你讲讲这道A+B的题目你可以自己做练习然后在后台提交答案。
**题目A+B**
输入格式有一系列的整数对A和B以空格分开。
输出格式对于每个整数对A和B需要给出A和B的和。
输入输出样例:
```
INPUT
1 5
OUTPUT
6
```
针对这道题,我给出了下面的答案:
```
while True:
try:
line = raw_input()
a = line.split()
print int(a[0]) + int(a[1])
except:
break
```
当然每个人可以有不同的解法官方也有Python的答案这里给你介绍这个OnlineJudge是因为
<li>
可以在线得到反馈,提交代码后,系统会告诉你对错。而且你能看到每道题的正确率,和大家提交后反馈的状态;
</li>
<li>
有社区论坛可以进行交流学习;
</li>
<li>
对算法和数据结构的提升大有好处,当然对数据挖掘算法的灵活运用和整个编程基础的提升都会有很大的帮助。
</li>
## 总结
现在我们知道Python毫无疑问是数据分析中最主流的语言。今天我们学习了这么多Python的基础语法你是不是体会到了它的简洁。如果你有其他编程语言基础相信你会非常容易地转换成Python语法的。那到此Python我们也就算入门了。有没有什么方法可以在此基础上快速提升Python编程水平呢给你分享下我的想法。
在日常工作中,我们解决的问题都不属于高难度的问题,大部分人做的都是开发工作而非科研项目。所以我们要提升的主要是**熟练度**,而通往熟练度的唯一路径就是练习、练习、再练习!
如果你是第一次使用Python不用担心最好的方式就是直接做题。把我上面的例子都跑一遍自己在做题中体会。
如果你想提升自己的编程基础尤其是算法和数据结构相关的能力因为这个在后面的开发中都会用到。那么ACM Online Judge是非常好的选择勇敢地打开这扇大门把它当作你进阶的好工具。
你可以从Accepted比率高的题目入手你做对的题目数越多你的排名也会越来越往前这意味着你的编程能力包括算法和数据结构的能力都有了提升。另外这种在社区中跟大家一起学习还能排名就像游戏一样让学习更有趣味从此不再孤独。
<img src="https://static001.geekbang.org/resource/image/b9/9c/b93956302991443d440684d86d16199c.jpg" alt="">
我在文章中多次强调练习的作用,这样可以增加你对数据分析相关内容的熟练度。所以我给你出了两道练习题,你可以思考下如何来做,欢迎把答案放到评论下面,我也会和你一起在评论区进行讨论。
<li>
如果我想在Python中引用scikit-learn库该如何引用
</li>
<li>
求1+3+5+7+…+99的求和用Python该如何写
</li>
欢迎你把今天的内容分享给身边的朋友和他一起掌握Python这门功能强大的语言。

View File

@@ -0,0 +1,340 @@
<audio id="audio" title="04丨Python科学计算用NumPy快速处理数据" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/35/dd/35c6026b38ce55c29f5cf56ffe680cdd.mp3"></audio>
上一节我讲了Python的基本语法今天我来给你讲下Python中一个非常重要的第三方库NumPy。
它不仅是Python中使用最多的第三方库而且还是SciPy、Pandas等数据科学的基础库。它所提供的数据结构比Python自身的“更高级、更高效”可以这么说NumPy所提供的数据结构是Python数据分析的基础。
我上次讲到了Python数组结构中的列表list它实际上相当于一个数组的结构。而NumPy中一个关键数据类型就是关于数组的那为什么还存在这样一个第三方的数组结构呢
实际上标准的Python中用列表list保存数组的数值。由于列表中的元素可以是任意的对象所以列表中list保存的是对象的指针。虽然在Python编程中隐去了指针的概念但是数组有指针Python的列表list其实就是数组。这样如果我要保存一个简单的数组[0,1,2]就需要有3个指针和3个整数的对象这样对于Python来说是非常不经济的浪费了内存和计算时间。
## 使用NumPy让你的Python科学计算更高效
为什么要用NumPy数组结构而不是Python本身的列表list这是因为列表list的元素在系统内存中是分散存储的而NumPy数组存储在一个均匀连续的内存块中。这样数组计算遍历所有的元素不像列表list还需要对内存地址进行查找从而节省了计算资源。
另外在内存访问模式中缓存会直接把字节块从RAM加载到CPU寄存器中。因为数据连续的存储在内存中NumPy直接利用现代CPU的矢量化指令计算加载寄存器中的多个连续浮点数。另外NumPy中的矩阵计算可以采用多线程的方式充分利用多核CPU计算资源大大提升了计算效率。
当然除了使用NumPy外你还需要一些技巧来提升内存和提高计算资源的利用率。一个重要的规则就是**避免采用隐式拷贝,而是采用就地操作的方式**。举个例子如果我想让一个数值x是原来的两倍可以直接写成x*=2而不要写成y=x*2。
这样速度能快到2倍甚至更多。
既然NumPy这么厉害你该从哪儿入手学习呢在NumPy里有两个重要的对象ndarrayN-dimensional array object解决了多维数组问题而ufuncuniversal function object则是解决对数组进行处理的函数。下面我就带你一一来看。
**ndarray对象**
ndarray实际上是多维数组的含义。在NumPy数组中维数称为秩rank一维数组的秩为1二维数组的秩为2以此类推。在NumPy中每一个线性的数组称为一个轴axes其实秩就是描述轴的数量。
下面你来看ndarray对象是如何创建数组的又是如何处理结构数组的呢
**创建数组**
```
import numpy as np
a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
b[1,1]=10
print a.shape
print b.shape
print a.dtype
print b
```
运行结果:
```
(3L,)
(3L, 3L)
int32
[[ 1 2 3]
[ 4 10 6]
[ 7 8 9]]
```
创建数组前你需要引用NumPy库可以直接通过array函数创建数组如果是多重数组比如示例里的b那么该怎么做呢你可以先把一个数组作为一个元素然后嵌套起来比如示例b中的[1,2,3]就是一个元素,然后[4,5,6][7,8,9]也是作为元素,然后把三个元素再放到[]数组里赋值给变量b。
当然数组也是有属性的比如你可以通过函数shape属性获得数组的大小通过dtype获得元素的属性。如果你想对数组里的数值进行修改的话直接赋值即可注意下标是从0开始计的所以如果你想对b数组九宫格里的中间元素进行修改的话下标应该是[1,1]。
**结构数组**
如果你想统计一个班级里面学生的姓名、年龄以及语文、英语、数学成绩该怎么办当然你可以用数组的下标来代表不同的字段比如下标为0的是姓名、下标为1的是年龄等但是这样不显性。
实际上在C语言里可以定义结构数组也就是通过struct定义结构类型结构中的字段占据连续的内存空间每个结构体占用的内存大小都相同那在NumPy中是怎样操作的呢
```
import numpy as np
persontype = np.dtype({
'names':['name', 'age', 'chinese', 'math', 'english'],
'formats':['S32','i', 'i', 'i', 'f']})
peoples = np.array([(&quot;ZhangFei&quot;,32,75,100, 90),(&quot;GuanYu&quot;,24,85,96,88.5),
(&quot;ZhaoYun&quot;,28,85,92,96.5),(&quot;HuangZhong&quot;,29,65,85,100)],
dtype=persontype)
ages = peoples[:]['age']
chineses = peoples[:]['chinese']
maths = peoples[:]['math']
englishs = peoples[:]['english']
print np.mean(ages)
print np.mean(chineses)
print np.mean(maths)
print np.mean(englishs)
```
运行结果:
```
28.25
77.5
93.25
93.75
```
你看下这个例子首先在NumPy中是用dtype定义的结构类型然后在定义数组的时候用array中指定了结构数组的类型dtype=persontype这样你就可以自由地使用自定义的persontype了。比如想知道每个人的语文成绩就可以用chineses = peoples[:][chinese]当然NumPy中还有一些自带的数学运算比如计算平均值使用np.mean。
**ufunc运算**
ufunc是universal function的缩写是不是听起来就感觉功能非常强大确如其名它能对数组中每个元素进行函数操作。NumPy中很多ufunc函数计算速度非常快因为都是采用C语言实现的。
**连续数组的创建**
NumPy可以很方便地创建连续数组比如我使用arange或linspace函数进行创建
```
x1 = np.arange(1,11,2)
x2 = np.linspace(1,9,5)
```
np.arange和np.linspace起到的作用是一样的都是创建等差数组。这两个数组的结果x1,x2都是[1 3 5 7 9]。结果相同,但是你能看出来创建的方式是不同的。
arange()类似内置函数range(),通过指定**初始值、终值、步长**来创建等差数列的一维数组,默认是不包括终值的。
linspace是linear space的缩写代表线性等分向量的含义。linspace()通过指定**初始值、终值、元素个数**来创建等差数列的一维数组,默认是包括终值的。
**算数运算**
通过NumPy可以自由地创建等差数组同时也可以进行加、减、乘、除、求n次方和取余数。
```
x1 = np.arange(1,11,2)
x2 = np.linspace(1,9,5)
print np.add(x1, x2)
print np.subtract(x1, x2)
print np.multiply(x1, x2)
print np.divide(x1, x2)
print np.power(x1, x2)
print np.remainder(x1, x2)
```
运行结果:
```
[ 2. 6. 10. 14. 18.]
[0. 0. 0. 0. 0.]
[ 1. 9. 25. 49. 81.]
[1. 1. 1. 1. 1.]
[1.00000000e+00 2.70000000e+01 3.12500000e+03 8.23543000e+05
3.87420489e+08]
[0. 0. 0. 0. 0.]
```
我还以x1, x2数组为例求这两个数组之间的加、减、乘、除、求n次方和取余数。在n次方中x2数组中的元素实际上是次方的次数x1数组的元素为基数。
在取余函数里你既可以用np.remainder(x1, x2)也可以用np.mod(x1, x2),结果是一样的。
**统计函数**
如果你想要对一堆数据有更清晰的认识,就需要对这些数据进行描述性的统计分析,比如了解这些数据中的最大值、最小值、平均值,是否符合正态分布,方差、标准差多少等等。它们可以让你更清楚地对这组数据有认知。
下面我来介绍下在NumPy中如何使用这些统计函数。
**计数组/矩阵中的最大值函数amax()最小值函数amin()**
```
import numpy as np
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print np.amin(a)
print np.amin(a,0)
print np.amin(a,1)
print np.amax(a)
print np.amax(a,0)
print np.amax(a,1)
```
运行结果:
```
1
[1 2 3]
[1 4 7]
9
[7 8 9]
[3 6 9]
```
amin() 用于计算数组中的元素沿指定轴的最小值。对于一个二维数组aamin(a)指的是数组中全部元素的最小值amin(a,0)是延着axis=0轴的最小值axis=0轴是把元素看成了[1,4,7], [2,5,8], [3,6,9]三个元素,所以最小值为[1,2,3]amin(a,1)是延着axis=1轴的最小值axis=1轴是把元素看成了[1,2,3], [4,5,6], [7,8,9]三个元素,所以最小值为[1,4,7]。同理amax()是计算数组中元素沿指定轴的最大值。
**统计最大值与最小值之差 ptp()**
```
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print np.ptp(a)
print np.ptp(a,0)
print np.ptp(a,1)
```
运行结果:
```
8
[6 6 6]
[2 2 2]
```
对于相同的数组anp.ptp(a)可以统计数组中最大值与最小值的差即9-1=8。同样ptp(a,0)统计的是沿着axis=0轴的最大值与最小值之差即7-1=6当然8-2=6,9-3=6第三行减去第一行的ptp差均为6ptp(a,1)统计的是沿着axis=1轴的最大值与最小值之差即3-1=2当然6-4=2, 9-7=2即第三列与第一列的ptp差均为2
**统计数组的百分位数 percentile()**
```
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print np.percentile(a, 50)
print np.percentile(a, 50, axis=0)
print np.percentile(a, 50, axis=1)
```
运行结果:
```
5.0
[4. 5. 6.]
[2. 5. 8.]
```
同样percentile()代表着第 p 个百分位数这里p的取值范围是0-100如果p=0那么就是求最小值如果p=50就是求平均值如果p=100就是求最大值。同样你也可以求得在axis=0 和 axis=1两个轴上的p%的百分位数。
**统计数组中的中位数median()、平均数mean()**
```
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
#求中位数
print np.median(a)
print np.median(a, axis=0)
print np.median(a, axis=1)
#求平均数
print np.mean(a)
print np.mean(a, axis=0)
print np.mean(a, axis=1)
```
运行结果:
```
5.0
[4. 5. 6.]
[2. 5. 8.]
5.0
[4. 5. 6.]
[2. 5. 8.]
```
你可以用median()和mean()求数组的中位数、平均值同样也可以求得在axis=0和1两个轴上的中位数、平均值。你可以自己练习下看看运行结果。
**统计数组中的加权平均值average()**
```
a = np.array([1,2,3,4])
wts = np.array([1,2,3,4])
print np.average(a)
print np.average(a,weights=wts)
```
运行结果:
```
2.5
3.0
```
average()函数可以求加权平均加权平均的意思就是每个元素可以设置个权重默认情况下每个元素的权重是相同的所以np.average(a)=(1+2+3+4)/4=2.5你也可以指定权重数组wts=[1,2,3,4]这样加权平均np.average(a,weights=wts)=(1*1+2*2+3*3+4*4)/(1+2+3+4)=3.0。
**统计数组中的标准差std()、方差var()**
```
a = np.array([1,2,3,4])
print np.std(a)
print np.var(a)
```
运行结果:
```
1.118033988749895
1.25
```
方差的计算是指每个数值与平均值之差的平方求和的平均值即mean((x - x.mean())** 2)。标准差是方差的算术平方根。在数学意义上代表的是一组数据离平均值的分散程度。所以np.var(a)=1.25, np.std(a)=1.118033988749895。
**NumPy排序**
排序是算法中使用频率最高的一种,也是在数据分析工作中常用的方法,计算机专业的同学会在大学期间的算法课中学习。
那么这些排序算法在NumPy中实现起来其实非常简单一条语句就可以搞定。这里你可以使用sort函数sort(a, axis=-1, kind=quicksort, order=None)默认情况下使用的是快速排序在kind里可以指定quicksort、mergesort、heapsort分别表示快速排序、合并排序、堆排序。同样axis默认是-1即沿着数组的最后一个轴进行排序也可以取不同的axis轴或者axis=None代表采用扁平化的方式作为一个向量进行排序。另外order字段对于结构化的数组可以指定按照某个字段进行排序。
```
a = np.array([[4,3,2],[2,4,1]])
print np.sort(a)
print np.sort(a, axis=None)
print np.sort(a, axis=0)
print np.sort(a, axis=1)
```
运行结果:
```
[[2 3 4]
[1 2 4]]
[1 2 2 3 4 4]
[[2 3 1]
[4 4 2]]
[[2 3 4]
[1 2 4]]
```
你可以自己计算下这个运行结果,然后再跑一遍比对下。
## 总结
在NumPy学习中你重点要掌握的就是对数组的使用因为这是NumPy和标准Python最大的区别。在NumPy中重新对数组进行了定义同时提供了算术和统计运算你也可以使用NumPy自带的排序功能一句话就搞定各种排序算法。
当然要理解NumPy提供的数据结构为什么比Python自身的“更高级、更高效”要从对数据指针的引用角度进行理解。
<img src="https://static001.geekbang.org/resource/image/7b/66/7ba74ca7776ac29a5dc94c272d72ff66.jpg" alt=""><br>
我今天重点讲了NumPy的数据结构你能用自己的话说明一下为什么要用NumPy而不是Python的列表list吗除此之外你还知道那些数据结构类型
**练习题:统计全班的成绩**
假设一个团队里有5名学员成绩如下表所示。你可以用NumPy统计下这些人在语文、英语、数学中的平均成绩、最小成绩、最大成绩、方差、标准差。然后把这些人的总成绩排序得出名次进行成绩输出。
<img src="https://static001.geekbang.org/resource/image/44/5c/442a89eed30c13b543e5f717c538325c.jpg" alt="">
期待你的答案,也欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事。

View File

@@ -0,0 +1,409 @@
<audio id="audio" title="05丨Python科学计算Pandas" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a5/7b/a57cce18f0bf45f73b440a355ea9a37b.mp3"></audio>
上一章中我们讲了Python的一个重要的第三方库NumPy今天我来给你介绍Python的另一个工具Pandas。
在数据分析工作中Pandas的使用频率是很高的一方面是因为Pandas提供的基础数据结构DataFrame与json的契合度很高转换起来就很方便。另一方面如果我们日常的数据清理工作不是很复杂的话你通常用几句Pandas代码就可以对数据进行规整。
Pandas可以说是基于 NumPy 构建的含有更高级数据结构和分析能力的工具包。在NumPy中数据结构是围绕ndarray展开的那么在Pandas中的核心数据结构是什么呢
下面主要给你讲下**Series和 DataFrame这两个核心数据结构**他们分别代表着一维的序列和二维的表结构。基于这两种数据结构Pandas可以对数据进行导入、清洗、处理、统计和输出。
## 数据结构Series和DataFrame
**Series是个定长的字典序列**。说是定长是因为在存储的时候相当于两个ndarray这也是和字典结构最大的不同。因为在字典的结构里元素的个数是不固定的。
**Series**有两个基本属性index 和 values。在Series结构中index默认是0,1,2,……递增的整数序列当然我们也可以自己来指定索引比如index=[a, b, c, d]。
```
import pandas as pd
from pandas import Series, DataFrame
x1 = Series([1,2,3,4])
x2 = Series(data=[1,2,3,4], index=['a', 'b', 'c', 'd'])
print x1
print x2
```
运行结果:
```
0 1
1 2
2 3
3 4
dtype: int64
a 1
b 2
c 3
d 4
dtype: int64
```
这个例子中x1中的index采用的是默认值x2中index进行了指定。我们也可以采用字典的方式来创建Series比如
```
d = {'a':1, 'b':2, 'c':3, 'd':4}
x3 = Series(d)
print x3
```
运行结果:
```
a 1
b 2
c 3
d 4
dtype: int64
```
**DataFrame类型数据结构类似数据库表。**
它包括了行索引和列索引我们可以将DataFrame 看成是由相同索引的Series组成的字典类型。
我们虚构一个王者荣耀考试的场景,想要输出几位英雄的考试成绩:
```
import pandas as pd
from pandas import Series, DataFrame
data = {'Chinese': [66, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98, 96, 77, 90]}
df1= DataFrame(data)
df2 = DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei'], columns=['English', 'Math', 'Chinese'])
print df1
print df2
```
在后面的案例中我一般会用df, df1, df2这些作为DataFrame数据类型的变量名我们以例子中的df2为例列索引是[English, Math, Chinese],行索引是[ZhangFei, GuanYu, ZhaoYun, HuangZhong, DianWei]所以df2的输出是
```
English Math Chinese
ZhangFei 65 30 66
GuanYu 85 98 95
ZhaoYun 92 96 93
HuangZhong 88 77 90
DianWei 90 90 80
```
在了解了Series和 DataFrame这两个数据结构后我们就从数据处理的流程角度来看下他们的使用方法。
## 数据导入和输出
Pandas允许直接从xlsxcsv等文件中导入数据也可以输出到xlsx, csv等文件非常方便。
```
import pandas as pd
from pandas import Series, DataFrame
score = DataFrame(pd.read_excel('data.xlsx'))
score.to_excel('data1.xlsx')
print score
```
需要说明的是在运行的过程可能会存在缺少xlrd和openpyxl包的情况到时候如果缺少了可以在命令行模式下使用“pip install”命令来进行安装。
## 数据清洗
数据清洗是数据准备过程中必不可少的环节Pandas也为我们提供了数据清洗的工具在后面数据清洗的章节中会给你做详细的介绍这里简单介绍下Pandas在数据清洗中的使用方法。
我还是以上面这个王者荣耀的数据为例。
```
data = {'Chinese': [66, 95, 93, 90,80],'English': [65, 85, 92, 88, 90],'Math': [30, 98, 96, 77, 90]}
df2 = DataFrame(data, index=['ZhangFei', 'GuanYu', 'ZhaoYun', 'HuangZhong', 'DianWei'], columns=['English', 'Math', 'Chinese'])
```
**在数据清洗过程中,一般都会遇到以下这几种情况,下面我来简单介绍一下。**
**1. 删除 DataFrame 中的不必要的列或行**
Pandas提供了一个便捷的方法 drop() 函数来删除我们不想要的列或行。比如我们想把“语文”这列删掉。
```
df2 = df2.drop(columns=['Chinese'])
```
想把“张飞”这行删掉。
```
df2 = df2.drop(index=['ZhangFei'])
```
**2. 重命名列名columns让列表名更容易识别**
如果你想对DataFrame中的columns进行重命名可以直接使用rename(columns=new_names, inplace=True) 函数比如我把列名Chinese改成YuWenEnglish改成YingYu。
```
df2.rename(columns={'Chinese': 'YuWen', 'English': 'Yingyu'}, inplace = True)
```
**3. 去重复的值**
数据采集可能存在重复的行这时只要使用drop_duplicates()就会自动把重复的行去掉。
```
df = df.drop_duplicates() #去除重复行
```
**4. 格式问题**
**更改数据格式**
这是个比较常用的操作因为很多时候数据格式不规范我们可以使用astype函数来规范数据格式比如我们把Chinese字段的值改成str类型或者int64可以这么写
```
df2['Chinese'].astype('str')
df2['Chinese'].astype(np.int64)
```
**数据间的空格**
有时候我们先把格式转成了str类型是为了方便对数据进行操作这时想要删除数据间的空格我们就可以使用strip函数
```
#删除左右两边空格
df2['Chinese']=df2['Chinese'].map(str.strip)
#删除左边空格
df2['Chinese']=df2['Chinese'].map(str.lstrip)
#删除右边空格
df2['Chinese']=df2['Chinese'].map(str.rstrip)
```
如果数据里有某个特殊的符号我们想要删除怎么办同样可以使用strip函数比如Chinese字段里有美元符号我们想把这个删掉可以这么写
```
df2['Chinese']=df2['Chinese'].str.strip('$')
```
**大小写转换**
大小写是个比较常见的操作比如人名、城市名等的统一都可能用到大小写的转换在Python里直接使用upper(), lower(), title()函数,方法如下:
```
#全部大写
df2.columns = df2.columns.str.upper()
#全部小写
df2.columns = df2.columns.str.lower()
#首字母大写
df2.columns = df2.columns.str.title()
```
**查找空值**
数据量大的情况下有些字段存在空值NaN的可能这时就需要使用Pandas中的isnull函数进行查找。比如我们输入一个数据表如下
<img src="https://static001.geekbang.org/resource/image/34/ab/3440abb73e91e9f7a41dc2fbfeea44ab.png" alt=""><br>
如果我们想看下哪个地方存在空值NaN可以针对数据表df进行df.isnull(),结果如下:
<img src="https://static001.geekbang.org/resource/image/5b/fe/5b52bca4eb6f00d51f72dcc5c6ce2afe.png" alt="">
如果我想知道哪列存在空值可以使用df.isnull().any(),结果如下:
<img src="https://static001.geekbang.org/resource/image/89/03/89cb71afc4f54a11ce1d4d05cd46bb03.png" alt="">
## 使用apply函数对数据进行清洗
apply函数是Pandas中**自由度非常高的函数**,使用频率也非常高。
比如我们想对name列的数值都进行大写转化可以用
```
df['name'] = df['name'].apply(str.upper)
```
我们也可以定义个函数在apply中进行使用。比如定义double_df函数是将原来的数值*2进行返回。然后对df1中的“语文”列的数值进行*2处理可以写成
```
def double_df(x):
return 2*x
df1[u'语文'] = df1[u'语文'].apply(double_df)
```
我们也可以定义更复杂的函数比如对于DataFrame我们新增两列其中new1列是“语文”和“英语”成绩之和的m倍'new2列是“语文”和“英语”成绩之和的n倍我们可以这样写
```
def plus(df,n,m):
df['new1'] = (df[u'语文']+df[u'英语']) * m
df['new2'] = (df[u'语文']+df[u'英语']) * n
return df
df1 = df1.apply(plus,axis=1,args=(2,3,))
```
其中axis=1代表按照列为轴进行操作axis=0代表按照行为轴进行操作args是传递的两个参数即n=2, m=3在plus函数中使用到了n和m从而生成新的df。
## 数据统计
在数据清洗后,我们就要对数据进行统计了。
Pandas和NumPy一样都有常用的统计函数如果遇到空值NaN会自动排除。
常用的统计函数包括:
<img src="https://static001.geekbang.org/resource/image/34/00/343ba98c1322dc0c013e07c87b157a00.jpg" alt="">
表格中有一个describe()函数统计函数千千万describe()函数最简便。它是个统计大礼包可以快速让我们对数据有个全面的了解。下面我直接使用df1.descirbe()输出结果为:
```
df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)})
print df1.describe()
```
<img src="https://static001.geekbang.org/resource/image/e4/83/e4a7a208a11d60dbcda6f3dbaff9a583.png" alt="">
## 数据表合并
有时候我们需要将多个渠道源的多个数据表进行合并一个DataFrame相当于一个数据库的数据表那么多个DataFrame数据表的合并就相当于多个数据库的表合并。
比如我要创建两个DataFrame
```
df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)})
df2 = DataFrame({'name':['ZhangFei', 'GuanYu', 'A', 'B', 'C'], 'data2':range(5)})
```
两个DataFrame数据表的合并使用的是merge()函数有下面5种形式
**1. 基于指定列进行连接**
比如我们可以基于name这列进行连接。
```
df3 = pd.merge(df1, df2, on='name')
```
<img src="https://static001.geekbang.org/resource/image/22/2f/220ce1ea19c8f6f2668d3a8122989c2f.png" alt="">
**2. inner内连接**
inner内链接是merge合并的默认情况inner内连接其实也就是键的交集在这里df1, df2相同的键是name所以是基于name字段做的连接
```
df3 = pd.merge(df1, df2, how='inner')
```
<img src="https://static001.geekbang.org/resource/image/22/2f/220ce1ea19c8f6f2668d3a8122989c2f.png" alt="">
**3. left左连接**
左连接是以第一个DataFrame为主进行的连接第二个DataFrame作为补充。
```
df3 = pd.merge(df1, df2, how='left')
```
<img src="https://static001.geekbang.org/resource/image/90/ac/9091a7406d5aa7a2980328d587fb42ac.png" alt="">
**4. right右连接**
右连接是以第二个DataFrame为主进行的连接第一个DataFrame作为补充。
```
df3 = pd.merge(df1, df2, how='right')
```
<img src="https://static001.geekbang.org/resource/image/10/af/10f9f22f66f3745381d85d760f857baf.png" alt="">
**5. outer外连接**
外连接相当于求两个DataFrame的并集。
```
df3 = pd.merge(df1, df2, how='outer')
```
<img src="https://static001.geekbang.org/resource/image/67/8c/6737f6d4d66af0d75734cd140b5d198c.png" alt="">
## 如何用SQL方式打开Pandas
Pandas的DataFrame数据类型可以让我们像处理数据表一样进行操作比如数据表的增删改查都可以用Pandas工具来完成。不过也会有很多人记不住这些Pandas的命令相比之下还是用SQL语句更熟练用SQL对数据表进行操作是最方便的它的语句描述形式更接近我们的自然语言。
事实上在Python里可以直接使用SQL语句来操作Pandas。
这里给你介绍个工具pandasql。
pandasql 中的主要函数是 sqldf它接收两个参数一个SQL 查询语句还有一组环境变量globals()或locals()。这样我们就可以在Python里直接用SQL语句中对DataFrame进行操作举个例子
```
import pandas as pd
from pandas import DataFrame
from pandasql import sqldf, load_meat, load_births
df1 = DataFrame({'name':['ZhangFei', 'GuanYu', 'a', 'b', 'c'], 'data1':range(5)})
pysqldf = lambda sql: sqldf(sql, globals())
sql = &quot;select * from df1 where name ='ZhangFei'&quot;
print pysqldf(sql)
```
运行结果:
```
data1 name
0 0 ZhangFei
```
上面这个例子中我们是对“name='ZhangFei”“的行进行了输出。当然你会看到我们用到了lambdalambda在python中算是使用频率很高的那lambda是用来做什么的呢它实际上是用来定义一个匿名函数的具体的使用形式为
```
lambda argument_list: expression
```
这里argument_list是参数列表expression是关于参数的表达式会根据expression表达式计算结果进行输出返回。
在上面的代码中,我们定义了:
```
pysqldf = lambda sql: sqldf(sql, globals())
```
在这个例子里输入的参数是sql返回的结果是sqldf对sql的运行结果当然sqldf中也输入了globals全局参数因为在sql中有对全局参数df1的使用。
## 总结
和NumPy一样Pandas有两个非常重要的数据结构Series和DataFrame。使用Pandas可以直接从csv或xlsx等文件中导入数据以及最终输出到excel表中。
我重点介绍了数据清洗中的操作当然Pandas中同样提供了多种数据统计的函数。
最后我们介绍了如何将数据表进行合并以及在Pandas中使用SQL对数据表更方便地进行操作。
Pandas包与NumPy工具库配合使用可以发挥巨大的威力正是有了Pandas工具Python做数据挖掘才具有优势。
<img src="https://static001.geekbang.org/resource/image/74/cd/74884960677548b08acdc919c13460cd.jpg" alt="">
我们来回顾一下今天的内容在Pandas中最主要的数据结构是什么它都提供了哪些函数可以帮我们做数据清洗你可以自己描述一下吗
## 练习题
对于下表的数据请使用Pandas中的DataFrame进行创建并对数据进行清洗。同时新增一列“总和”计算每个人的三科成绩之和。
<img src="https://static001.geekbang.org/resource/image/25/80/25b34b3f6227a945500074e05ea49e80.png" alt=""><br>
欢迎在评论区与我分享你的答案。
如果你觉着这篇文章有价值,欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事。

View File

@@ -0,0 +1,151 @@
<audio id="audio" title="06 | 学数据分析要掌握哪些基本概念?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/26/be/26d6c9ad279962ee4e66398f6cf049be.mp3"></audio>
美国明尼苏达州一家Target百货被客户投诉这名客户指控Target将婴儿产品优惠券寄给他的女儿而他女儿还是一名高中生。但没多久这名客户就来电道歉因为女儿经他逼问后坦承自己真的怀孕了。
Target百货寄送婴儿产品优惠券绝非偶然之举他们发现妇女在怀孕的情况下购买的物品会发生变化比如护手霜会从有香味的改成无味的此外还会购买大量维生素等保健品。通过类似的关联分析Target构建了一个“怀孕预测指数”通过这个指数预测到了顾客已经怀孕的情况并把优惠券寄送给她。
那么顾客怀孕与商品之间的关联关系是如何被发现的呢?
实际上他们都是用的**Apriori算法**该算法是由美国学者Agrawal在1994年提出的。他通过分析购物篮中的商品集合找出商品之间的关联关系。利用这种隐性关联关系商家就可以强化这类购买行为从而提升销售额。
这就是数据分析的力量,人们总是从数据分析中得到有价值的信息,啤酒和尿布的故事也是个经典的案例。如今在超市中,我们还能看到不少组合的套装打包在一起卖,比如宝洁的产品:飘柔洗发水+玉兰油沐浴露、海飞丝洗发水+舒肤佳沐浴露等等。
商品的捆绑销售是个很有用的营销方式,背后都是数据分析在发挥作用。
## 商业智能BI、数据仓库DW、数据挖掘DM三者之间的关系
开头中的百货商店利用数据预测用户购物行为属于**商业智能**,他们积累的顾客的消费行为习惯会存储在**数据仓库**中,通过对个体进行消费行为分析总结出来的规律属于**数据挖掘**。
所以我们能在这个场景里看到三个重要的概念:商业智能、数据仓库和数据挖掘。
**商业智能**的英文是Business Intelligence缩写是BI。相比于数据仓库、数据挖掘它是一个更大的概念。商业智能可以说是基于数据仓库经过了数据挖掘后得到了商业价值的过程。所以说数据仓库是个金矿数据挖掘是炼金术而商业报告则是黄金。
**数据仓库**的英文是Data Warehouse缩写是DW。它可以说是BI这个房子的地基搭建好DW这个地基之后才能进行分析使用最后产生价值。
数据仓库可以说是数据库的升级概念。从逻辑上理解,数据库和数据仓库没有什么区别,都是通过数据库技术来存储数据的。不过从数量上来讲,数据仓库的量更庞大,适用于数据挖掘和数据分析。数据库可以理解是一项技术。
数据仓库将原有的多个数据来源中的数据进行汇总、整理而得。数据进入数据仓库前,必须消除数据中的不一致性,方便后续进行数据分析和挖掘。
**数据挖掘**的英文是Data Mining缩写是DM。在商业智能BI中经常会使用到数据挖掘技术。数据挖掘的核心包括分类、聚类、预测、关联分析等任务通过这些炼金术我们可以从数据仓库中得到宝藏比如商业报告。
很多时候企业老板总是以结果为导向他们认为商业报告才是他们想要的但是这也是需要经过地基DW、搬运工ETL、科学家DM等共同的努力才得到的。
## 元数据 VS 数据元
我们前面提到了数据仓库,在数据仓库中,还有一类重要的数据是元数据,那么它和数据元有什么区别呢?
**元数据**MetaData描述其它数据的数据也称为“中介数据”。
**数据元**Data Element就是最小数据单元。
在生活中只要有一类事物就可以定义一套元数据。举个例子比如一本图书的信息包括了书名、作者、出版社、ISBN、出版时间、页数和定价等多个属性的信息我们就可以把这些属性定义成一套图书的元数据。
在图书这个元数据中,书名、作者、出版社就是数据元。你可以理解是最小的数据单元。元数据最大的好处是使信息的描述和分类实现了结构化,让机器处理起来很方便。
元数据可以很方便地应用于数据仓库。比如数据仓库中有数据和数据之间的各种复杂关系,为了描述这些关系,元数据可以对数据仓库的数据进行定义,刻画数据的抽取和转换规则,存储与数据仓库主题有关的各种信息。而且整个数据仓库的运行都是基于元数据的,比如抽取调度数据、获取历史数据等。
通过元数据,可以很方便地帮助我们管理数据仓库。
## 数据挖掘的流程
聊完了数据仓库我们再来谈谈数据挖掘。数据挖掘不是凭空产生的它与数据库技术的发展分不开。数据挖掘的一个英文解释叫Knowledge Discovery in Database简称KDD也就是数据库中的知识发现。
在数据挖掘中,有几个非常重要的任务,就是**分类、聚类、预测和关联分析**。我来解释下这些概念。
**1. 分类**
就是通过训练集得到一个分类模型,然后用这个模型可以对其他数据进行分类。
这里需要说明下训练集和测试集的概念。一般来说数据可以划分为训练集和测试集。训练集是用来给机器做训练的,通常是人们整理好训练数据,以及这些数据对应的分类标识。通过训练,机器就产生了自我分类的模型,然后机器就可以拿着这个分类模型,对测试集中的数据进行分类预测。同样如果测试集中,人们已经给出了测试结果,我们就可以用测试结果来做验证,从而了解分类器在测试环境下的表现。
**2. 聚类**
人以群分,物以类聚。聚类就是将数据自动聚类成几个类别,聚到一起的相似度大,不在一起的差异性大。我们往往利用聚类来做数据划分。
**3. 预测**
顾名思义,就是通过当前和历史数据来预测未来趋势,它可以更好地帮助我们识别机遇和风险。
**4. 关联分析**
就是发现数据中的关联规则,它被广泛应用在购物篮分析,或事务数据分析中。比如我们开头提到的那个案例。
数据挖掘要怎么完成这些任务呢?它需要将数据库中的数据经过一系列的加工计算,最终得出有用的信息。
这个过程可以用以下步骤来描述。
<img src="https://static001.geekbang.org/resource/image/bb/5e/bb63e82e50de89776abf7681a5b8785e.jpg" alt="">
首先,输入我们收集到的数据,然后对数据进行预处理。预处理通常是将数据转化成我们想要的格式,然后我们再对数据进行挖掘,最后通过后处理得到我们想要的信息。
那你可能想问,为什么不直接进行数据挖掘,还要进行数据预处理呢?
因为在这个过程中,输入的数据通常是从不同渠道采集而来的,所以数据的格式以及质量是参差不齐的,所以我们需要对数据进行预处理。
**数据预处理**中,我们会对数据进行几个处理步骤:数据清洗,数据集成,以及数据变换。
**1. 数据清洗**
主要是为了去除重复数据,去噪声(即干扰数据)以及填充缺失值。
**2. 数据集成**
是将多个数据源中的数据存放在一个统一的数据存储中。
**3. 数据变换**
就是将数据转换成适合数据挖掘的形式。比如通过归一化将属性数据按照比例缩放这样就可以将数值落入一个特定的区间内比如0~1之间。
我会在后面的几节课给你讲解如何对数据进行预处理。
**数据后处理**是将模型预测的结果进一步处理后再导出。比如在二分类问题中一般能得到的是0~1之间的概率值此时把数据以0.5为界限进行四舍五入就可以实现后处理。
## 白话数据概念
说了这么多概念,可能你还是觉得很抽象,我来打个比喻。比如你认识了两个漂亮的女孩。
**商业智能**会告诉你要追哪个?成功概率有多大?
**数据仓库**会说,我这里存储了这两个女孩的相关信息,你要吗?
其中每个女孩的数据都有单独的文件夹,里面有她们各自的姓名、生日、喜好和联系方式等,这些具体的信息就是**数据元,<strong>加起来叫作**元数据。</strong>
**数据挖掘**会帮助你确定追哪个女孩,并且整理好数据仓库,这里就可以使用到各种算法,帮你做决策了。
你可能会用到**分类算法**。御姐、萝莉、女王,她到底属于哪个分类?
如果认识的女孩太多了多到你已经数不过来了比如说5万人你就可以使用**聚类算法**了它帮你把这些女孩分成多个群组比如5个组。然后再对每个群组的特性进行了解进行决策。这样就把5万人的决策转化成了5个组的决策。成功实现降维大大提升了效率。如果你想知道这个女孩的闺蜜是谁那么**关联分析算法**可以告诉你。
如果你的数据来源比较多,比如有很多朋友给你介绍女朋友,很多人都推荐了同一个,你就需要去重,这叫**数据清洗**;为了方便记忆,你把不同朋友推荐的女孩信息合成一个,这叫**数据集成**;有些数据渠道统计的体重的单位是公斤,有些是斤,你就需要将它们转换成同一个单位,这叫**数据变换。**
最后你可以进行数据可视化了,它会直观地把你想要的结果呈现出来。
## 上帝不会告诉我们规律,而是展示给我们数据
还记得高中物理课上我们计算自由落体运动加速度的实验吗?
我们将重物连上纸带,通过电火花打点计时器,在纸带上会出现多个打点。然后我们通过纸带上打点的个数,以及点之间的间距,来计算自由落体运动的加速度。通过多组实验,取平均值的方式将误差降到最小。
在我们的高中时代,许多定律都是通过实验得出的。参加工作以后,很多数据是业务数据,比如电商的客户购物数据等,这些数据依然有着某些规律。这就需要我们通过数据挖掘的力量来帮我们揭示规律,通过利用这些规律,可以帮我们创造更大的价值。
今天的内容到这里就结束了,我出几道题让你回顾下今天的内容吧。
1.什么是KDD
A. 数据挖掘与知识发现<br>
B. 领域知识发现<br>
C. 文档知识发现<br>
D. 动态知识发现
2.某超市将火锅产品和骨汤进行并列陈列后这两种商品相比以往提升了50%的销售额,这种属于数据挖掘的哪类问题?
A. 关联规则发现<br>
B. 聚类<br>
C. 分类<br>
D. 自然语言处理
最后,说一下你是如何理解数据挖掘的价值的?可以谈谈你的体会或者项目经历。
如果你觉得今天的内容有所启迪,欢迎点击“请朋友读”,分享给你的朋友或者同事,一起来学习。

View File

@@ -0,0 +1,158 @@
<audio id="audio" title="07 | 用户画像:标签化就是数据的抽象能力" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ae/91/aee6e3c6f3c97f4e2506594c58713591.mp3"></audio>
王兴说过我们已经进入到互联网的下半场。在上半场也就是早期的互联网时代你永远不知道在对面坐的是什么样的人。那个年代大部分人还是QQ的早期用户。在下半场互联网公司已经不新鲜了大部分公司已经互联网化。他们已经在用网络进行产品宣传使用电商销售自己的商品。
这两年引领下半场发展的是那些在讲 “大数据”“赋能”的企业,他们有数据,有用户。
通过大数据告诉政府该如何智慧地管理交通,做城市规划。
通过消费数据分析,告诉企业该在什么时间生产什么产品,以最大化地满足用户的需求。
通过生活大数据告诉我们餐饮企业,甚至房地产企业该如何选址。
如果说互联网的上半场是粗狂运营,因为有流量红利不需要考虑细节。那么在下半场,**精细化运营将是长久的主题**。有数据,有数据分析能力才能让用户得到更好的体验。
所以,用户是根本,也是数据分析的出发点。
假如你进入到一家卖羊肉串的餐饮公司,老板说现在竞争越来越激烈,要想做得好就要明白顾客喜欢什么。于是上班第一天,老板问你:“你能不能分析下用户数据,给咱们公司的业务做个赋能啊?”
听到这,你会怎么想?
你说:“老板啊,咱们是卖羊肉串的,做数据挖掘没用啊。”估计老板听后,晚上就把你给开了。
那该怎么办呢?如果你感觉一头懵,没关系,我们今天就来讲讲怎么一步步分析用户数据。
## 用户画像的准则
首先就是将自己企业的用户画像做个白描,告诉他这些用户“都是谁”“从哪来”“要去哪”。
你可以这么和老板说“老板啊用户画像建模是个系统的工程我们要解决三个问题。第一呢就是用户从哪里来这里我们需要统一标识用户ID方便我们对用户后续行为进行跟踪。我们要了解这些羊肉串的用户从哪里来他们是为了聚餐还是自己吃宵夜这些场景我们都要做统计分析。第二呢这些用户是谁我们需要对这些用户进行标签化方便我们对用户行为进行理解。第三呢就是用户要到哪里去我们要将这些用户画像与我们的业务相关联提升我们的转化率或者降低我们的流失率。”
听到这,老板给你竖起了大拇指,说:“不错,都需要什么资源,随时找我就行。”
<img src="https://static001.geekbang.org/resource/image/0f/f4/0ff019f3f87f627dd5522411f67a45f4.jpg" alt=""><br>
刚才说的这三个步骤,下面我一一给你做个梳理。
**首先,为什么要设计唯一标识?**
**用户唯一标识是整个用户画像的核心**。我们以一个App为例它把“从用户开始使用APP到下单到售后整个所有的用户行为”进行串联这样就可以更好地去跟踪和分析一个用户的特征。
设计唯一标识可以从这些项中选择用户名、注册手机号、联系人手机号、邮箱、设备号、CookieID等。
**其次,给用户打标签。**
你可能会想,标签有很多,且不同的产品,标签的选择范围也不同,这么多的标签,怎样划分才能既方便记忆,又能保证用户画像的全面性呢?
这里我总结了八个字,叫“**用户消费行为分析**”。我们可以从这4个维度来进行标签划分。
<li>
用户标签:它包括了性别、年龄、地域、收入、学历、职业等。这些包括了用户的基础属性。
</li>
<li>
消费标签:消费习惯、购买意向、是否对促销敏感。这些统计分析用户的消费习惯。
</li>
<li>
行为标签时间段、频次、时长、访问路径。这些是通过分析用户行为来得到他们使用App的习惯。
</li>
<li>
内容分析:对用户平时浏览的内容,尤其是停留时间长、浏览次数多的内容进行分析,分析出用户对哪些内容感兴趣,比如,金融、娱乐、教育、体育、时尚、科技等。
</li>
可以说,用户画像是现实世界中的**用户的数学建模**,我们正是将海量数据进行**标签化**,来得到精准的用户画像,从而为企业更精准地解决问题。
最后,当你有了用户画像,可以为企业带来什么业务价值呢?
我们可以从用户生命周期的三个阶段来划分业务价值,包括:**获客、粘客和留客**。
<li>
获客:如何进行拉新,通过更精准的营销获取客户。
</li>
<li>
粘客:个性化推荐,搜索排序,场景运营等。
</li>
<li>
留客:流失率预测,分析关键节点降低流失率。
</li>
如果按照数据流处理的阶段来划分用户画像建模的过程,可以分为数据层、算法层和业务层。你会发现在不同的层,都需要打上不同的标签。
**数据层**指的是用户消费行为里的标签。我们可以打上“事实标签”,作为数据客观的记录。
**算法层**指的是透过这些行为算出的用户建模。我们可以打上“模型标签”,作为用户画像的分类标识。
**业务层**指的是获客、粘客、留客的手段。我们可以打上“预测标签”,作为业务关联的结果。
所以这个标签化的流程,就是通过数据层的“事实标签”,在算法层进行计算,打上“模型标签”的分类结果,最后指导业务层,得出“预测标签”。
<img src="https://static001.geekbang.org/resource/image/f0/2f/f0e94ab9319dc561df3cdd781526c22f.jpg" alt="">
## 美团外卖的用户画像该如何设计?
刚才讲的是用户画像的三个阶段,以及每个阶段的准则。下面,我们来使用这些准则做个练习。
如果你是美团外卖的数据分析师你该如何制定用户标识ID制定用户画像以及基于用户画像可以做哪些业务关联
首先我们先回顾下美团外卖的产品背景。美团已经和大众点评进行了合并因此在大众点评和美团外卖上都可以进行外卖下单。另外美团外卖针对的是高频O2O的场景美团外卖是美团的核心产品基本上有一半的市值都是由外卖撑起来的。
基于用户画像实施的三个阶段,我们首先需要统一用户的唯一标识,那么究竟哪个字段可以作为用户标识呢?
我们先看下美团和大众点评都是通过哪些方式登录的。
我们看到美团采用的是手机号、微信、微博、美团账号的登录方式。大众点评采用的是手机号、微信、QQ、微博的登录方式。这里面两个APP共同的登录方式都是手机号、微信和微博。
那么究竟哪个可以作为用户的唯一标识呢?当然主要是以用户的注册手机号为标准。这样美团和大众点评的账号体系就可以相通。
当然,大家知道在集团内部,各部门之间的协作,尤其是用户数据打通是非常困难的,所以这里建议,如果希望大数据对各个部门都能赋能,一定要在集团的战略高度上,尽早就在最开始的顶层架构上,将用户标识进行统一,这样在后续过程中才能实现用户数据的打通。
然后我们思考下,有了用户,用户画像都可以统计到哪些标签。我们按照“**用户消费行为分析**”的准则来进行设计。
<li>
用户标签:性别、年龄、家乡、居住地、收货地址、婚姻、宝宝信息、通过何种渠道进行的注册。
</li>
<li>
消费标签:餐饮口味、消费均价、团购等级、预定使用等级、排队使用等级、外卖等级。
</li>
<li>
行为标签:点外卖时间段、使用频次、平均点餐用时、访问路径。
</li>
<li>
内容分析:基于用户平时浏览的内容进行统计,包括餐饮口味、优惠敏感度等。
</li>
**当你有了“用户消费行为分析”的标签之后,你就可以更好地理解业务了。**
比如一个经常买沙拉的人,一般很少吃夜宵。同样,一个经常吃夜宵的人,吃小龙虾的概率可能远高于其他人。这些结果都是通过数据挖掘中的关联分析得出的。
有了这些数据,我们就可以预测用户的行为。
比如一个用户购买了“月子餐”后,更有可能购买婴儿水,同样婴儿相关的产品比如婴儿湿巾等的购买概率也会增大。
具体在业务层上,我们都可以基于标签产生哪些业务价值呢?
<li>
**在获客上**,我们可以找到优势的宣传渠道,如何通过个性化的宣传手段,吸引有潜在需求的用户,并刺激其转化。
</li>
<li>
**在粘客上**,如何提升用户的单价和消费频次,方法可以包括购买后的个性化推荐、针对优质用户进行优质高价商品的推荐、以及重复购买,比如通过红包、优惠等方式激励对优惠敏感的人群,提升购买频次。
</li>
<li>
**在留客上**预测用户是否可能会从平台上流失。在营销领域关于用户留存有一个观点——如果将顾客流失率降低5%公司利润将提升25%~85%。可以看出留存率是多么的重要。用户流失可能会包括多种情况,比如用户体验、竞争对手、需求变化等,通过预测用户的流失率可以大幅降低用户留存的运营成本。
</li>
## 锻炼自己的抽象能力,将繁杂的事务简单化
上面我们讲到的“用户消费行为标签”都是基于一般情况考虑的,除此之外,用户的行为也会随着营销的节奏产生异常值,比如双十一的时候,如果商家都在促销就会产生突发的大量订单。因此在做用户画像的时候,还要考虑到异常值的处理。
总之数据量是庞大的会存在各种各样的使用情况。光是分析EB级别的大数据我们就要花很长的时间。
但**我们的最终目的不是处理这些数据,而是理解、使用这些数据挖掘的结果**。对数据的标签化能让我们快速理解一个用户,一个商品,乃至一个视频内容的特征,从而方便我们去理解和使用数据。
对数据的标签化其实考验的是我们的抽象能力,在日常工作中,我们也要锻炼自己的抽象能力,它可以让我们很快地将一个繁杂的事物简单化,不仅方便理解,还有益后续的使用。
我们今天讲了用户画像的流程,其中很重要的一个步骤就是给用户打标签,那么你不妨想想,如果给羊肉串连锁店进行用户画像分析,都可以从哪些角度进行标签化?
最后,我们从现实生活中出发,打开你的手机,翻翻看你的微信通讯录,分析下你的朋友圈,都有哪些用户画像?如果你来给它设计标签,都有哪些种类需要统计呢。为了方便后续使用,你是如何将他们归类分组的?
欢迎在评论区与我分享你的答案,我会和你一起探讨。也欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事,我们一起交流,一起进步。

View File

@@ -0,0 +1,124 @@
<audio id="audio" title="08 | 数据采集:如何自动化采集数据?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/b3/15/b3cc6a80fed3a57570fce015688d9715.mp3"></audio>
上一节中我们讲了如何对用户画像建模,而建模之前我们都要进行数据采集。数据采集是数据挖掘的基础,没有数据,挖掘也没有意义。很多时候,我们拥有多少数据源,多少数据量,以及数据质量如何,将决定我们挖掘产出的成果会怎样。
举个例子,你做量化投资,基于大数据预测未来股票的波动,根据这个预测结果进行买卖。你当前能够拿到以往股票的所有历史数据,是否可以根据这些数据做出一个预测率高的数据分析系统呢?
实际上如果你只有股票历史数据你仍然无法理解股票为什么会产生大幅的波动。比如当时可能是爆发了SARS疫情或者某地区发生了战争等。这些重大的社会事件对股票的影响也是巨大的。
因此我们需要考虑到,一个数据的走势,是由多个维度影响的。我们需要通过**多源的数据采集**,收集到尽可能多的**数据维度**,同时保证数据的质量,这样才能得到高质量的数据挖掘结果。
那么,从数据采集角度来说,都有哪些数据源呢?我将数据源分成了以下的四类。
<img src="https://static001.geekbang.org/resource/image/2e/7e/2e26981a785f7a6e2523f052cd38277e.jpg" alt="">
这四类数据源包括了:开放数据源、爬虫抓取、传感器和日志采集。它们各有特点。
开放数据源一般是针对行业的数据库。比如美国人口调查局开放了美国的人口信息、地区分布和教育情况数据。除了政府外,企业和高校也会开放相应的大数据,这方面北美相对来说做得好一些。国内,贵州做了不少大胆尝试,搭建了云平台,逐年开放了旅游、交通、商务等领域的数据量。
要知道很多研究都是基于开放数据源进行的,否则每年不会有那么多论文发表,大家需要相同的数据集才能对比出算法的好坏。
爬虫抓取一般是针对特定的网站或App。如果我们想要抓取指定的网站数据比如购物网站上的购物评价等就需要我们做特定的爬虫抓取。
第三类数据源是传感器,它基本上采集的是物理信息。比如图像、视频、或者某个物体的速度、热度、压强等。
最后是日志采集,这个是统计用户的操作。我们可以在前端进行埋点,在后端进行脚本收集、统计,来分析网站的访问情况,以及使用瓶颈等。
知道了有四类数据源,那如何采集到这些数据呢?
## 如何使用开放数据源
我们先来看下开放数据源,教你个方法,开放数据源可以从两个维度来考虑,一个是单位的维度,比如政府、企业、高校;一个就是行业维度,比如交通、金融、能源等领域。这方面,国外的开放数据源比国内做得好一些,当然近些年国内的政府和高校做开放数据源的也越来越多。一方面服务社会,另一方面自己的影响力也会越来越大。
比如,下面这张表格列举的就是单位维度的数据源。
<img src="https://static001.geekbang.org/resource/image/da/03/da6c227cf944dcd740e23ad833c85203.jpg" alt="">
所以如果你想找某个领域的数据源,比如金融领域,你基本上可以看下政府、高校、企业是否有开放的数据源。当然你也可以直接搜索金融开放数据源。
## 如何使用爬虫做抓取
爬虫抓取应该属于最常见的需求,比如你想要餐厅的评价数据。当然这里要注重版权问题,而且很多网站也是有反爬机制的。
最直接的方法就是使用Python编写爬虫代码当然前提是你需要会Python的基本语法。除此之外PHP也可以做爬虫只是功能不如Python完善尤其是涉及到多线程的操作。
在Python爬虫中基本上会经历三个过程。
<li>
使用 Requests 爬取内容。我们可以使用 Requests库来抓取网页信息。Requests 库可以说是 Python 爬虫的利器也就是Python的HTTP 库,通过这个库爬取网页中的数据,非常方便,可以帮我们节约大量的时间。
</li>
<li>
使用 XPath 解析内容。XPath 是XML Path的缩写也就是XML 路径语言。它是一种用来确定 XML 文档中某部分位置的语言在开发中经常用来当作小型查询语言。XPath可以通过元素和属性进行位置索引。
</li>
<li>
使用 Pandas 保存数据。Pandas 是让数据分析工作变得更加简单的高级数据结构,我们可以用 Pandas 保存爬取的数据。最后通过Pandas再写入到XLS或者MySQL等数据库中。
</li>
Requests、XPath、Pandas是Python的三个利器。当然做Python爬虫还有很多利器比如SeleniumPhantomJS或者用Puppeteer这种无头模式。
另外我们也可以不编程就抓取到网页信息,这里介绍三款常用的抓取工具。
**[火车采集器](http://www.locoy.com/)**
火车采集器已经有13年历史了是老牌的采集工具。它不仅可以做抓取工具也可以做数据清洗、数据分析、数据挖掘和可视化等工作。数据源适用于绝大部分的网页网页中能看到的内容都可以通过采集规则进行抓取。
**[八爪鱼](http://www.bazhuayu.com/)**
八爪鱼也是知名的采集工具,它有两个版本,一个就是免费的采集模板,还有一个就是云采集(付费)。
免费的采集模板实际上就是内容采集规则,包括了电商类、生活服务类、社交媒体类和论坛类的网站都可以采集,用起来非常方便。当然你也可以自己来自定义任务。
那什么是云采集呢就是当你配置好采集任务就可以交给八爪鱼的云端进行采集。八爪鱼一共有5000台服务器通过云端多节点并发采集采集速度远远超过本地采集。此外还可以自动切换多个 IP避免IP被封影响采集。
做过工程项目的同学应该能体会到,云采集这个功能太方便了,**很多时候自动切换IP以及云采集才是自动化采集的关键**。
下一篇文章我会给你详细介绍八爪鱼的使用。
**[集搜客](http://www.gooseeker.com/)**
这个工具的特点是完全可视化操作,无需编程。整个采集过程也是所见即所得,抓取结果信息、错误信息等都反应在软件中。相比于八爪鱼来说,集搜客没有流程的概念,用户只需要关注抓取什么数据,而流程细节完全交给集搜客来处理。
但是集搜客的缺点是没有云采集功能,所有爬虫都是在用户自己电脑上跑的。
## 如何使用日志采集工具
传感器采集基本上是基于特定的设备,将设备采集的信息进行收集即可,这里我们就不重点讲解了。
下面我们来看日志采集。
为什么要做日志采集呢?日志采集最大的作用,就是通过分析用户访问情况,提升系统的性能,从而提高系统承载量。及时发现系统承载瓶颈,也可以方便技术人员基于用户实际的访问情况进行优化。
日志采集也是运维人员的重要工作之一,那么日志都包括哪些呢,又该如何对日志进行采集呢?
日志就是日记的意思它记录了用户访问网站的全过程哪些人在什么时间通过什么渠道比如搜索引擎、网址输入来过都执行了哪些操作系统是否产生了错误甚至包括用户的IP、HTTP请求的时间用户代理等。这些日志数据可以被写在一个日志文件中也可以分成不同的日志文件比如访问日志、错误日志等。
日志采集可以分两种形式。
<li>
通过Web服务器采集例如 httpd、Nginx、Tomcat 都自带日志记录功能。同时很多互联网企业都有自己的海量数据采集工具多用于系统日志采集如Hadoop的Chukwa、Cloudera的Flume、Facebook的Scribe等这些工具均采用分布式架构能够满足每秒数百MB的日志数据采集和传输需求。
</li>
<li>
自定义采集用户行为例如用JavaScript代码监听用户的行为、AJAX异步请求后台记录日志等。
</li>
**埋点是什么**
埋点是日志采集的关键步骤,那什么是埋点呢?
**埋点就是在有需要的位置采集相应的信息,进行上报**。比如某页面的访问情况,包括用户信息、设备信息;或者用户在页面上的操作行为,包括时间长短等。这就是埋点,每一个埋点就像一台摄像头,采集用户行为数据,将数据进行多维度的交叉分析,可真实还原出用户使用场景,和用户使用需求。
那我们要如何进行埋点呢?
埋点就是在你需要统计数据的地方植入统计代码当然植入代码可以自己写也可以使用第三方统计工具。我之前讲到“不重复造轮子”的原则一般来说需要自己写的代码一般是主营核心业务对于埋点这类监测性的工具市场上已经比较成熟这里推荐你使用第三方的工具比如友盟、Google Analysis、Talkingdata等。他们都是采用前端埋点的方式然后在第三方工具里就可以看到用户的行为数据。但如果我们想要看到更深层的用户操作行为就需要进行自定义埋点。
总结一下日志采集有助于我们了解用户的操作数据适用于运维监控、安全审计、业务数据分析等场景。一般Web服务器会自带日志功能也可以使用Flume从不同的服务器集群中采集、汇总和传输大容量的日志数据。当然我们也可以使用第三方的统计工具或自定义埋点得到自己想要的统计内容。
## 总结
数据采集是数据分析的关键很多时候我们会想到Python网络爬虫实际上数据采集的方法、渠道很广有些可以直接使用开放的数据源比如想获取比特币历史的价格及交易数据可以直接从Kaggle上下载不需要自己爬取。
另一方面根据我们的需求,需要采集的数据也不同,比如交通行业,数据采集会和摄像头或者测速仪有关。对于运维人员,日志采集和分析则是关键。所以我们需要针对特定的业务场景,选择适合的采集工具。
今天我讲了数据采集的不同渠道以及相关的工具。给你留一个思考题,假如你想预测比特币的未来走势,都需要哪些维度的数据源呢?怎样收集到它们呢?欢迎在留言区与我分享你的想法,我也会和你一起探讨。
也欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事。

View File

@@ -0,0 +1,167 @@
<audio id="audio" title="09丨数据采集如何用八爪鱼采集微博上的“D&G”评论" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a8/ad/a801c9f352bf11dbb99d5967ff49ddad.mp3"></audio>
上一讲我给你讲了数据采集的来源,其中有一个很关键的工具叫做八爪鱼,今天我们就用八爪鱼实战模拟一下如何进行数据采集。
在文末你可以看到我操作的流程视频。
## 八爪鱼的基本操作
在开始操作前我先来介绍下今天要讲的主角“八爪鱼”工具。相比使用Python进行爬虫八爪鱼的使用更加简便因为是所见即所得的方式基本上不需要编写代码除了在正则表达式匹配的时候会用到XPath。
这里简单介绍下XPathXPath的英文是XML Path Language也就是XML的路径语言用来在XML文件中寻找我们想要的元素。所以八爪鱼可以使用XPath帮我们更灵活地定位我们想要找的元素。
**自定义任务 VS 简易采集**
如果你想要采集数据就需要新建一个任务,在建任务的时候,八爪鱼会给你一个提示,是使用八爪鱼自带的“简易采集”,还是自定义一个任务。
简易采集集成了一些热门的模板,也就是我们经常访问的一些网站。它可以帮助我们轻松地实现采集,只需要我们告诉工具两个信息即可,一个是需要采集的网址,另一个是登录网站的账号和密码。
虽然简易采集比较方便快捷但通常还是推荐使用自定义任务的方式这样可以更灵活地帮我们提取想要的信息比如你只想采集关于“D&amp;G”的微博评论。
## 流程步骤
<img src="https://static001.geekbang.org/resource/image/8f/f6/8f64431836e79d7773aed420d34cddf6.jpg" alt=""><br>
八爪鱼的采集共分三步:
<li>
**输入网页:**每个采集需要输入你想要采集的网页。在新建任务的时候,这里是必填项。
</li>
<li>
**设计流程:**这个步骤最为关键,你需要告诉八爪鱼,你是如何操作页面的、想要提取页面上的哪些信息等。因为数据条数比较多,通常你还需要翻页,所以要进行循环翻页的设置。在设计流程中,你可以使用简易采集方式,也就是八爪鱼自带的模板,也可以采用自定义的方式。
</li>
<li>
**启动采集:**当你设计好采集流程后就可以启动采集任务了任务结束后八爪鱼会提示你保存采集好的数据通常是xlsx或csv格式。
</li>
如果你使用的是自定义采集,就需要自己来设计采集流程,也就是采集流程中的第二步。八爪鱼的流程步骤有两类,可以划分为基本步骤和高级步骤。
<img src="https://static001.geekbang.org/resource/image/68/d5/68687ec44b128c3b19df823c0d2e13d5.jpg" alt="">
基本步骤就是最常用的步骤每次采集都会用到一共分为4步分别是打开网页、点击元素、循环翻页、提取数据。
高级步骤是辅助步骤,可以帮我们更好地对数据进行提取,比如我们想要某个关键词的数据,就需要在网页输入框中输入对应的文字。有时候源网页的系统会提示需要输入验证码,我们就可以采用验证码识别的模块帮我们解决。有时候我们需要用下拉选项帮我们筛选想要的数据,或者某些判断条件下(比如存在某个关键词)才触发的采集等。这些操作可以更精细化地提取想要的数据。
下面我来介绍下基本步骤:
**1. 打开网页**
所有的采集默认第一项都是打开网页。所以在新建任务之后,系统会提示你输入网址。当你输入之后,八爪鱼就会自动建立一个“打开网页”的流程。
**2. 点击元素**
这里元素的定义比较广泛,它可以是某个按钮,或者某个链接,也或者是某个图片或文字。使用这个步骤是你在搜索或者提交某个请求。当你点击元素后,八爪鱼会提示你想要达到的目的:点击该按钮、采集该元素文本、还是鼠标移到该链接上。然后再选择“点击该按钮”进行确认即可。
如果我们点击某个元素的目的是循环翻页,或者提取数据,那么在点击之后,八爪鱼会确认你的目的,你只要点击相关的按钮即可。
**3. 循环翻页**
很多数据都存在翻页的情况,通常你需要找到翻页的位置,比如网页底部的“下一页”按钮,点击它,会提示你“循环点击下一页”、“采集该链接文本”还是“点击该链接”。你需要确认这里是进行的“循环点击下一页”。
**4. 提取数据**
在网页上选择你想要提取的页面范围,鼠标移动到页面上会呈现蓝色的阴影面积,它表明了你想提取的数据范围。然后点击鼠标后,在右侧选择“采集数据”即可。
这4个基本操作就像它们的名称一样简单直接这里我给你一些使用的建议
<li>
尽量使用用户操作视角进行模拟的方式进行操作,而不是在“流程视图”中手动创建相应的步骤。因为八爪鱼最大的特点就是所见即所得,所以一切就按照用户使用的流程进行操作即可。
</li>
<li>
使用“流程视图”方便管理和调整。右侧有“流程视图”的按钮,点击之后进入到流程视图,会把你之前的操作以流程图的方式展示出来。我会在文章下面详细介绍一下。
</li>
为什么要这么做呢?这样的话每个步骤流程清晰可见,而且你还可以调整每个步骤的参数,比如你之前的网址写错了想要修改,或者之前输入的文字需要调整等。
另外很多时候需要账号登录后才能采集数据,我们可以提前在八爪鱼工具里登录,这样再进行抓取的时候就是登录的状态,直接进行采集就可以了。
## 采集微博上的“Dolce&amp;Gabbana”评论
在了解基本步骤之后我们就可以自己动手采集内容了。比如说我想要采集微博上关于“D&amp;G”的评论那么我可以先在浏览器上人工操作下整个流程梳理出来以下的步骤。
<img src="https://static001.geekbang.org/resource/image/ac/07/ac0c2a85f4240e5277fc2ba4853c1307.jpg" alt="">
这几个流程具体是怎么做的呢?我来给你一一梳理一下。
**1. 输入网页**
对应基本步骤“打开网页”,我们输入[微博搜索的地址](https://s.weibo.com/)。
**2. 输入关键词**
对应“输入文本”我把鼠标移动到输入框中点击后会在右侧进行操作目的的确认选择“输入文本”即可然后输入我们想要搜索的内容“D&amp;G”。
**3. 点击搜索**
对应“点击元素”,我们点击“搜索按钮”,然后确认操作目的是“点击元素”。
**4. 设置翻页**
因为我们想要采集全量数据因此需要先设置翻页。这里特别注意下翻页的操作要在数据提取之前因为翻页是个循环的命令就像我们平时写for语句一样一定是先设置for循环然后在循环中进行数据提取。
**5. 提取数据**
提取数据的时候我们需要提取多个字段比如用户、微博内容、发表时间、该微博网址。而且一个页面上会有多个微博都需要进行采集。所以你需要先选择单条内容的最大的目标区域在确认目的时会发现里面有子元素这里目的选择为“选中子元素”。因为我们要对子元素内容进行采集方便把内容按照字段进行划分。这时会提示页面中还有20个相同元素时选择“选中全部”即可。
**6. 启动采集**
都选择好之后,系统会给出三个提示,分别是“启动本地采集”、“启动云采集”和“设置定时采集”。数据量不大的时候,我们选择“启动本地采集”即可。
你可以看出,这整个过程比较简便,但中间有一些细节你可能会出错,比如说你忘记了先翻页,再选取你想提取的元素。这样如果遇到了问题,有**两个重要的工具一定要用好流程视图和XPath。**
**流程视图**
流程视图我在上面提到过,这里详细介绍一下。流程视图应该是在可视化中应用最多的场景,我们可以**使用流程视图查看创建流程**,调整顺序,或者删掉不想要的步骤。
另外我们还能**在视图中查看数据提取的字段。**选中“提取数据”步骤可以看到该步骤提取的字段都有哪些。一般都会出现很多冗余的字段因为HTML代码段中有很多隐藏的内容也会被提取到这里你可以删掉没用的字段把保留的字段名称进行备注修改。
这里有张图,是我通过八爪鱼可视化操作采集微博评论时,自动生成的流程视图。
<img src="https://static001.geekbang.org/resource/image/37/e8/376983d3823c8734cee79a0672f329e8.png" alt=""><br>
**XPath**
介绍完流程视图之后我们再来说一下XPath。在八爪鱼工具中内置了XPath引擎所以在我们用可视化方式选择元素的时候会自动生成相应的XPath路径。当然我们也可以查看这些元素的XPath方便对它们进行精细地控制。
为什么有了可视化操作还需要自己来定义XPath呢
这是因为有时候我们采集的网站页面是不规律的比如你可以看到微博搜索结果页中第一页和第二页的HTML排版是不同的这样的话可视化操作得到的XPath可能不具备通用性。这种情况下如果你用搜索结果第一页提取数据得到的XPath就无法匹配搜索结果页第二页的数据。
在八爪鱼工具中很多控件都有XPath最常用的还是循环和提取数据中的XPath下面我来一一简单介绍下。
**循环中的XPath**
在微博采集这个例子中,我们用到了两种循环方式,一种是“循环翻页”,一种是“循环列表”。
在“循环翻页”中你可以在“流程视图”中点击“循环翻页”的控件看到右侧的“高级选项”中的XPath。在微博采集这个例子中循环翻页的XPath是//A[@class=next]。
在“循环列表”中我在提取数据的时候出现了页面提示“还有20个相同元素”这时我选择“选中全部”。相当于出现了20个元素的循环列表。所以你在流程视图中可以会看到提取数据外层嵌套了个循环列表。同样我们可以看到循环列表的XPath是//DIV[@class=card-feed]。
**提取数据的XPath**
当我们点击流程中的“提取数据”可以看到有很多字段名称XPath实际上定位到了这些要采集的字段。所以你需要选中一个字段才能看到它的XPath。
现在你知道了八爪鱼的匹配是基于XPath的那么你也可以自己来调整XPath参数。这样当匹配不到想要的数据的时候可以检查下是不是XPath参数设置的问题可以手动调整从而抓取到正确的元素。
## 总结
今天我给你讲了八爪鱼的使用,然后带你实现了一个微博采集的例子。你可能会想问,我为什么要讲一个八爪鱼这样的第三方工具呢?
这里讲下我的一些心得体会。
我们的工作流程通常很长所以更应该专注工作的核心比如说数据分析这块所有的辅助都可以采用第三方工具来做。如果老板让你统计微博上的评论实际上老板最想知道的不是采集的过程而是整体的概况比如说影响了多少人评论如何是否有KOL关注等等。
如果你之前没有数据采集的经验,那么第三方工具,以及采用可视化的方式来进行采集应该是你的首选。可视化的方式可以让你迅速上手,了解到整个数据采集的过程。
我们应该从基础步骤开始遇到特定需求的时候再学习了解高级步骤。这篇文章只介绍了基本的流程但你可以上手操作了。在实际操作中你可能会遇到各种问题这个时候再对高级步骤进行学习如果要进阶的话还需要你掌握XPath的使用。
好了,我来总结一下今天的内容。今天我讲了八爪鱼的任务建立、流程设计,还有一个实操的案例。具体的内容概要可以看我整理的下面这张图。
虽然八爪鱼工具提供了各种简易采集的方式,我更建议你把它作为参考模板,可以看下别人是如何建立的,这样多做案例,你上手会更快。
<img src="https://static001.geekbang.org/resource/image/61/f0/61c274c9fe85b1610518154e5df32af0.jpg" alt=""><br>
下面是我操作八爪鱼的流程,你可以看一下这个视频,更直观一些。
<video poster="https://media001.geekbang.org/e3e56a181b0b4dffaecdf03412f6b522/snapshots/13f5c1d49e854a6a91d62f939160b827-00005.jpg" preload="none" controls=""><source src="https://media001.geekbang.org/customerTrans/6f475a24b1498919eb0a38bef256c23a/d1107b2-1683072ce69-0000-0000-01d-dbacd.mp4" type="video/mp4"><source src="https://media001.geekbang.org/e3e56a181b0b4dffaecdf03412f6b522/2df74269b15c4501be27e91055f0ce3d-aa7773bbe881719e6171cebaadb35cd3-sd.m3u8" type="application/x-mpegURL"><source src="https://media001.geekbang.org/e3e56a181b0b4dffaecdf03412f6b522/2df74269b15c4501be27e91055f0ce3d-ce65ac2a5053c9160869176661fb7ff5-hd.m3u8" type="application/x-mpegURL"></video>
**最后给你留个练习题**吧。如何通过八爪鱼抓取豆瓣网站中关于《海王》的电影评论呢?你不妨上手练习一下,这样会有更深的体会。
如果你觉得今天的内容对你有帮助,欢迎你把这篇文章分享给你的朋友或者同事,一起来学习进步。

View File

@@ -0,0 +1,285 @@
<audio id="audio" title="10丨Python爬虫如何自动化下载王祖贤海报" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/1f/b2/1f06d71d84ddc724459ec700d207afb2.mp3"></audio>
上一讲中我给你讲了如何使用八爪鱼采集数据,对于数据采集刚刚入门的人来说,像八爪鱼这种可视化的采集是一种非常好的方式。它最大的优点就是上手速度快,当然也存在一些问题,比如运行速度慢、可控性差等。
相比之下,爬虫可以很好地避免这些问题,今天我来分享下如何通过编写爬虫抓取数据。
## 爬虫的流程
相信你对“爬虫”这个词已经非常熟悉了,爬虫实际上是用浏览器访问的方式模拟了访问网站的过程,整个过程包括三个阶段:打开网页、提取数据和保存数据。
在Python中这三个阶段都有对应的工具可以使用。
在“打开网页”这一步骤中,可以使用 Requests 访问页面得到服务器返回给我们的数据这里包括HTML页面以及JSON数据。
在“提取数据”这一步骤中主要用到了两个工具。针对HTML页面可以使用 XPath 进行元素定位提取数据针对JSON数据可以使用JSON进行解析。
在最后一步“保存数据”中,我们可以使用 Pandas 保存数据最后导出CSV文件。
下面我来分别介绍下这些工具的使用。
**Requests访问页面**
Requests是Python HTTP的客户端库编写爬虫的时候都会用到编写起来也很简单。它有两种访问方式Get和Post。这两者最直观的区别就是Get把参数包含在url中而Post通过request body来传递参数。
假设我们想访问豆瓣那么用Get访问的话代码可以写成下面这样的
```
r = requests.get('http://www.douban.com')
```
代码里的“r”就是Get请求后的访问结果然后我们可以使用r.text或r.content来获取HTML的正文。
如果我们想要使用Post进行表单传递代码就可以这样写
```
r = requests.post('http://xxx.com', data = {'key':'value'})
```
这里data就是传递的表单参数data的数据类型是个字典的结构采用key和value的方式进行存储。
**XPath定位**
XPath是XML的路径语言实际上是通过元素和属性进行导航帮我们定位位置。它有几种常用的路径表达方式。
<img src="https://static001.geekbang.org/resource/image/3b/ea/3bcb311361c76bfbeb90d360b21195ea.jpg" alt="">
我来给你简单举一些例子:
<li>
xpath(node) 选取了node节点的所有子节点
</li>
<li>
xpath(/div) 从根节点上选取div节点
</li>
<li>
xpath(//div) 选取所有的div节点
</li>
<li>
xpath(./div) 选取当前节点下的div节点
</li>
<li>
xpath(’…’) 回到上一个节点;
</li>
<li>
xpath(//@id) 选取所有的id属性
</li>
<li>
xpath(//book[@id]) 选取所有拥有名为id的属性的book元素
</li>
<li>
xpath(//book[@id=“abc”]) 选取所有book元素且这些book元素拥有id= "abc"的属性;
</li>
<li>
xpath(//book/title | //book/price) 选取book元素的所有title和price元素。
</li>
上面我只是列举了XPath的部分应用XPath的选择功能非常强大它可以提供超过100个内建函数来做匹配。我们想要定位的节点几乎都可以使用XPath来选择。
使用XPath定位你会用到Python的一个解析库lxml。这个库的解析效率非常高使用起来也很简便只需要调用HTML解析命令即可然后再对HTML进行XPath函数的调用。
比如我们想要定位到HTML中的所有列表项目可以采用下面这段代码。
```
from lxml import etree
html = etree.HTML(html)
result = html.xpath('//li')
```
**JSON对象**
JSON是一种轻量级的交互方式在Python中有JSON库可以让我们将Python对象和JSON对象进行转换。为什么要转换呢原因也很简单。将JSON对象转换成为Python对象我们对数据进行解析就更方便了。
<img src="https://static001.geekbang.org/resource/image/9a/43/9a6d6564a64cf2b1c256265eea78c543.png" alt="">
这是一段将JSON格式转换成Python对象的代码你可以自己运行下这个程序的结果。
```
import json
jsonData = '{&quot;a&quot;:1,&quot;b&quot;:2,&quot;c&quot;:3,&quot;d&quot;:4,&quot;e&quot;:5}';
input = json.loads(jsonData)
print input
```
接下来我们就要进行实战了我会从两个角度给你讲解如何使用Python爬取海报一个是通过JSON数据爬取一个是通过XPath定位爬取。
## 如何使用JSON数据自动下载王祖贤的海报
我在上面讲了Python爬虫的基本原理和实现的工具下面我们来实战一下。如果想要从豆瓣图片中下载王祖贤的海报你应该先把我们日常的操作步骤整理下来
<li>
打开网页;
</li>
<li>
输入关键词“王祖贤”;
</li>
<li>
在搜索结果页中选择“图片”;
</li>
<li>
下载图片页中的所有海报。
</li>
这里你需要注意的是如果爬取的页面是动态页面就需要关注XHR数据。因为动态页面的原理就是通过原生的XHR数据对象发出HTTP请求得到服务器返回的数据后再进行处理。XHR会用于在后台与服务器交换数据。
你需要使用浏览器的插件查看XHR数据比如在Chrome浏览器中使用开发者工具。
在豆瓣搜索中我们对“王祖贤”进行了模拟发现XHR数据中有一个请求是这样的
[https://www.douban.com/j/search_photo?q=%E7%8E%8B%E7%A5%96%E8%B4%A4&amp;limit=20&amp;start=0](https://www.douban.com/j/search_photo?q=%E7%8E%8B%E7%A5%96%E8%B4%A4&amp;limit=20&amp;start=0)
url中的乱码正是中文的url编码打开后我们看到了很清爽的JSON格式对象展示的形式是这样的
```
{&quot;images&quot;:
[{&quot;src&quot;: …, &quot;author&quot;: …, &quot;url&quot;:…, &quot;id&quot;: …, &quot;title&quot;: …, &quot;width&quot;:…, &quot;height&quot;:…},
{&quot;src&quot;: …, &quot;author&quot;: …, &quot;url&quot;:…, &quot;id&quot;: …, &quot;title&quot;: …, &quot;width&quot;:…, &quot;height&quot;:…}],
&quot;total&quot;:22471,&quot;limit&quot;:20,&quot;more&quot;:true}
```
从这个JSON对象中我们能看到王祖贤的图片一共有22471张其中一次只返回了20张还有更多的数据可以请求。数据被放到了images对象里它是个数组的结构每个数组的元素是个字典的类型分别告诉了src、author、url、id、title、width和height字段这些字段代表的含义分别是原图片的地址、作者、发布地址、图片ID、标题、图片宽度、图片高度等信息。
有了这个JSON信息你很容易就可以把图片下载下来。当然你还需要寻找XHR请求的url规律。
如何查看呢,我们再来重新看下这个网址本身。
[https://www.douban.com/j/search_photo?q=王祖贤&amp;limit=20&amp;start=0](https://www.douban.com/j/search_photo?q=%E7%8E%8B%E7%A5%96%E8%B4%A4&amp;limit=20&amp;start=0)
你会发现网址中有三个参数q、limit和start。start实际上是请求的起始ID这里我们注意到它对图片的顺序标识是从0开始计算的。所以如果你想要从第21个图片进行下载你可以将start设置为20。
王祖贤的图片一共有22471张你可以写个for循环来跑完所有的请求具体的代码如下
```
# coding:utf-8
import requests
import json
query = '王祖贤'
''' 下载图片 '''
def download(src, id):
dir = './' + str(id) + '.jpg'
try:
pic = requests.get(src, timeout=10)
fp = open(dir, 'wb')
fp.write(pic.content)
fp.close()
except requests.exceptions.ConnectionError:
print('图片无法下载')
''' for 循环 请求全部的 url '''
for i in range(0, 22471, 20):
url = 'https://www.douban.com/j/search_photo?q='+query+'&amp;limit=20&amp;start='+str(i)
html = requests.get(url).text # 得到返回结果
response = json.loads(html,encoding='utf-8') # 将 JSON 格式转换成 Python 对象
for image in response['images']:
print(image['src']) # 查看当前下载的图片网址
download(image['src'], image['id']) # 下载一张图片
```
## 如何使用XPath自动下载王祖贤的电影海报封面
如果你遇到JSON的数据格式那么恭喜你数据结构很清爽通过Python的JSON库就可以解析。
但有时候网页会用JS请求数据那么只有JS都加载完之后我们才能获取完整的HTML文件。XPath可以不受加载的限制帮我们定位想要的元素。
比如,我们想要从豆瓣电影上下载王祖贤的电影封面,需要先梳理下人工的操作流程:
<li>
[打开网页movie.douban.com](http://xn--movie-hr2j95qrv1e8j7b.douban.com)
</li>
<li>
输入关键词“王祖贤”;
</li>
<li>
下载图片页中的所有电影封面。
</li>
这里你需要用XPath定位图片的网址以及电影的名称。
一个快速定位XPath的方法就是采用浏览器的XPath Helper插件使用Ctrl+Shift+X快捷键的时候用鼠标选中你想要定位的元素就会得到类似下面的结果。
<img src="https://static001.geekbang.org/resource/image/0e/c7/0e0fef601ee043f4bea8dd2874e788c7.png" alt="">
XPath Helper插件中有两个参数一个是Query另一个是Results。Query其实就是让你来输入XPath语法然后在Results里看到匹配的元素的结果。
我们看到这里选中的是一个元素我们要匹配上所有的电影海报就需要缩减XPath表达式。你可以在Query中进行XPath表达式的缩减尝试去掉XPath表达式中的一些内容在Results中会自动出现匹配的结果。
经过缩减之后你可以得到电影海报的XPath假设为变量src_xpath
```
//div[@class='item-root']/a[@class='cover-link']/img[@class='cover']/@src
```
以及电影名称的XPath假设为变量title_xpath
```
//div[@class='item-root']/div[@class='detail']/div[@class='title']/a[@class='title-text']
```
但有时候当我们直接用Requests获取HTML的时候发现想要的XPath并不存在。这是因为HTML还没有加载完因此你需要一个工具来进行网页加载的模拟直到完成加载后再给你完整的HTML。
在Python中这个工具就是Selenium库使用方法如下
```
from selenium import webdriver
driver = webdriver.Chrome()
driver.get(request_url)
```
Selenium是Web应用的测试工具可以直接运行在浏览器中它的原理是模拟用户在进行操作支持当前多种主流的浏览器。
这里我们模拟Chrome浏览器的页面访问。
你需要先引用Selenium中的WebDriver库。WebDriver实际上就是Selenium 2是一种用于Web应用程序的自动测试工具提供了一套友好的API方便我们进行操作。
然后通过WebDriver创建一个Chrome浏览器的drive再通过drive获取访问页面的完整HTML。
当你获取到完整的HTML时就可以对HTML中的XPath进行提取在这里我们需要找到图片地址srcs和电影名称titles。这里通过XPath语法匹配到了多个元素因为是多个元素所以我们需要用for循环来对每个元素进行提取。
```
srcs = html.xpath(src_xpath)
titles = html.xpath(title_path)
for src, title in zip(srcs, titles):
download(src, title.text)
```
然后使用上面我编写好的download函数进行图片下载。
## 总结
好了,这样就大功告成了,程序可以源源不断地采集你想要的内容。这节课,我想让你掌握的是:
<li>
Python爬虫的流程
</li>
<li>
了解XPath定位JSON对象解析
</li>
<li>
如何使用lxml库进行XPath的提取
</li>
<li>
如何在Python中使用Selenium库来帮助你模拟浏览器获取完整的HTML。
</li>
其中Python + Selenium + 第三方浏览器可以让我们处理多种复杂场景包括网页动态加载、JS响应、Post表单等。因为Selenium模拟的就是一个真实的用户的操作行为就不用担心cookie追踪和隐藏字段的干扰了。
当然Python还给我们提供了数据处理工具比如lxml库和JSON库这样就可以提取想要的内容了。
<img src="https://static001.geekbang.org/resource/image/eb/ab/eb3e48f714ca857a79948d831de521ab.jpg" alt="">
最后,你不妨来实践一下,你最喜欢哪个明星?如果想要自动下载这个明星的图片,该如何操作呢?欢迎和我在评论区进行探讨。
你也可以把这篇文章分享给你的朋友或者同事,一起动手练习一下。

View File

@@ -0,0 +1,185 @@
<audio id="audio" title="11 | 数据科学家80%时间都花费在了这些清洗任务上?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d7/32/d70e8b468eb331693b6e4e904472cf32.mp3"></audio>
我们在上一节中讲了数据采集,以及相关的工具使用,但做完数据采集就可以直接进行挖掘了吗?肯定不是的。
就拿做饭打个比方吧对于很多人来说热油下锅、掌勺翻炒一定是做饭中最过瘾的环节但实际上炒菜这个过程只占做饭时间的20%剩下80%的时间都是在做准备,比如买菜、择菜、洗菜等等。
在数据挖掘中,数据清洗就是这样的前期准备工作。对于数据科学家来说,我们会遇到各种各样的数据,在分析前,要投入大量的时间和精力把数据“**整理裁剪**”成自己想要或需要的样子。
为什么呢?因为我们采集到的数据往往有很多问题。
我们先看一个例子,假设老板给你以下的数据,让你做数据分析,你看到这个数据后有什么感觉呢?
<img src="https://static001.geekbang.org/resource/image/5e/23/5e69b73b96c0d824240ac8035fe69723.png" alt="">
你刚看到这些数据可能会比较懵,因为这些数据缺少标注。
我们在收集整理数据的时候,一定要对数据做标注,数据表头很重要。比如这份数据表,就缺少列名的标注,这样一来我们就不知道每列数据所代表的含义,无法从业务中理解这些数值的作用,以及这些数值是否正确。但在实际工作中,也可能像这个案例一样,数据是缺少标注的。
我简单解释下这些数据代表的含义。
这是一家服装店统计的会员数据。最上面的一行是列坐标,最左侧一列是行坐标。
列坐标中第0列代表的是序号第1列代表的会员的姓名第2列代表年龄第3列代表体重第4~6列代表男性会员的三围尺寸第7~9列代表女性会员的三围尺寸。
了解含义以后我们再看下中间部分具体的数据你可能会想这些数据怎么这么“脏乱差”啊有很多值是空的NaN还有空行的情况。
是的这还仅仅是一家商店的部分会员数据我们一眼看过去就能发现一些问题。日常工作中的数据业务会复杂很多通常我们要统计更多的数据维度比如100个指标数据量通常都是超过TB、EB级别的所以整个数据分析的处理难度是呈指数级增加的。这个时候仅仅通过肉眼就很难找到问题所在了。
我举了这样一个简单的例子,带你理解在数据分析之前为什么要有数据清洗这个重要的准备工作。有经验的数据分析师都知道,**好的数据分析师必定是一名数据清洗高手要知道在整个数据分析过程中不论是在时间还是功夫上数据清洗大概都占到了80%**。
## 数据质量的准则
在上面这个服装店会员数据的案例中,一看到这些数据,你肯定能发现几个问题。你是不是想知道,有没有一些准则来规范这些数据的质量呢?
准则肯定是有的。不过如果数据存在七八种甚至更多的问题我们很难将这些规则都记住。有研究说一个人的短期记忆最多可以记住7条内容或信息超过7条就记不住了。而数据清洗要解决的问题远不止7条我们万一漏掉一项该怎么办呢有没有一种方法我们既可以很方便地记住又能保证我们的数据得到很好的清洗提升数据质量呢
在这里我将数据清洗规则总结为以下4个关键点统一起来叫“**完全合一**”,下面我来解释下。
<li>
**完**整性:单条数据是否存在空值,统计的字段是否完善。
</li>
<li>
**全**面性观察某一列的全部数值比如在Excel表中我们选中一列可以看到该列的平均值、最大值、最小值。我们可以通过常识来判断该列是否有问题比如数据定义、单位标识、数值本身。
</li>
<li>
**合**法性数据的类型、内容、大小的合法性。比如数据中存在非ASCII字符性别存在了未知年龄超过了150岁等。
</li>
<li>
唯**一**性:数据是否存在重复记录,因为数据通常来自不同渠道的汇总,重复的情况是常见的。行数据、列数据都需要是唯一的,比如一个人不能重复记录多次,且一个人的体重也不能在列指标中重复记录多次。
</li>
在很多数据挖掘的教学中数据准则通常会列出来7~8项在这里我们归类成了“完全合一”4项准则按照以上的原则我们能解决数据清理中遇到的大部分问题使得**数据标准、干净、连续**,为后续数据统计、数据挖掘做好准备。如果想要进一步优化数据质量,还需要在实际案例中灵活使用。
## 清洗数据,一一击破
了解了数据质量准则之后,我们针对上面服装店会员数据案例中的问题进行一一击破。
这里你就需要Python的Pandas工具了。这个工具我们之前介绍过。它是基于NumPy的工具专门为解决数据分析任务而创建。Pandas 纳入了大量库,我们可以利用这些库高效地进行数据清理工作。
这里我补充说明一下如果你对Python还不是很熟悉但是很想从事数据挖掘、数据分析相关的工作那么花一些时间和精力来学习一下Python是很有必要的。Python拥有丰富的库堪称数据挖掘利器。当然了数据清洗的工具也还有很多这里我们只是以Pandas为例帮你应用数据清洗准则带你更加直观地了解数据清洗到底是怎么回事儿。
下面我们就依照“完全合一”的准则使用Pandas来进行清洗。
**1. 完整性**
**问题1缺失值**
在数据中有些年龄、体重数值是缺失的,这往往是因为数据量较大,在过程中,有些数值没有采集到。通常我们可以采用以下三种方法:
<li>
删除:删除数据缺失的记录;
</li>
<li>
均值:使用当前列的均值;
</li>
<li>
高频:使用当前列出现频率最高的数据。
</li>
比如我们想对df[Age]中缺失的数值用平均年龄进行填充,可以这样写:
```
df['Age'].fillna(df['Age'].mean(), inplace=True)
```
如果我们用最高频的数据进行填充可以先通过value_counts获取Age字段最高频次age_maxf然后再对Age字段中缺失的数据用age_maxf进行填充
```
age_maxf = train_features['Age'].value_counts().index[0]
train_features['Age'].fillna(age_maxf, inplace=True)
```
**问题2空行**
我们发现数据中有一个空行,除了 index 之外,全部的值都是 NaN。Pandas 的 read_csv() 并没有可选参数来忽略空行,这样,我们就需要在数据被读入之后再使用 dropna() 进行处理,删除空行。
```
# 删除全空的行
df.dropna(how='all',inplace=True)
```
**2. 全面性**
**问题:列数据的单位不统一**
观察weight列的数值我们能发现weight 列的单位不统一。有的单位是千克kgs有的单位是磅lbs
这里我使用千克作为统一的度量单位将磅lbs转化为千克kgs
```
# 获取 weight 数据列中单位为 lbs 的数据
rows_with_lbs = df['weight'].str.contains('lbs').fillna(False)
print df[rows_with_lbs]
# 将 lbs转换为 kgs, 2.2lbs=1kgs
for i,lbs_row in df[rows_with_lbs].iterrows():
# 截取从头开始到倒数第三个字符之前即去掉lbs。
weight = int(float(lbs_row['weight'][:-3])/2.2)
df.at[i,'weight'] = '{}kgs'.format(weight)
```
**3. 合理性**
**问题非ASCII字符**
我们可以看到在数据集中 Firstname 和 Lastname 有一些非 ASCII 的字符。我们可以采用删除或者替换的方式来解决非ASCII问题这里我们使用删除方法
```
# 删除非 ASCII 字符
df['first_name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
df['last_name'].replace({r'[^\x00-\x7F]+':''}, regex=True, inplace=True)
```
**4. 唯一性**
**问题1一列有多个参数**
在数据中不难发现姓名列Name包含了两个参数 Firstname 和 Lastname。为了达到数据整洁目的我们将 Name 列拆分成 Firstname 和 Lastname两个字段。我们使用Python的split方法str.split(expand=True),将列表拆成新的列,再将原来的 Name 列删除。
```
# 切分名字,删除源数据列
df[['first_name','last_name']] = df['name'].str.split(expand=True)
df.drop('name', axis=1, inplace=True)
```
**问题2重复数据**
我们校验一下数据中是否存在重复记录。如果存在重复记录,就使用 Pandas 提供的 drop_duplicates() 来删除重复数据。
```
# 删除重复数据行
df.drop_duplicates(['first_name','last_name'],inplace=True)
```
这样,我们就将上面案例中的会员数据进行了清理,来看看清理之后的数据结果。怎么样?是不是又干净又标准?
<img src="https://static001.geekbang.org/resource/image/71/fe/71001f8efb2692e77fa1285bcf7f91fe.png" alt="">
## 养成数据审核的习惯
现在你是不是能感受到数据问题不是小事上面这个简单的例子里都有6处错误。所以我们常说现实世界的数据是“肮脏的”需要清洗。
第三方的数据要清洗,自有产品的数据,也需要数据清洗。比如美团自身做数据挖掘的时候,也需要去除爬虫抓取,作弊数据等。可以说**没有高质量的数据,就没有高质量的数据挖掘,而数据清洗是高质量数据的一道保障。**
当你从事这方面工作的时候,你会发现养成数据审核的习惯非常重要。而且越是优秀的数据挖掘人员,越会有“数据审核”的“职业病”。这就好比编辑非常在意文章中的错别字、语法一样。
数据的规范性就像是你的作品一样通过清洗之后会变得非常干净、标准。当然了这也是一门需要不断修炼的功夫。终有一天你会进入这样一种境界看一眼数据差不多7秒钟的时间就能知道这个数据是否存在问题。为了这一眼的功力我们要做很多练习。
刚开始接触数据科学工作的时候,一定会觉得数据挖掘是件很酷、很有价值的事。确实如此,不过今天我还要告诉你,再酷炫的事也离不开基础性的工作,就像我们今天讲的数据清洗工作。对于这些基础性的工作,我们需要耐下性子,一个坑一个坑地去解决。
好了,最后我们来总结下今天的内容,你都收获了什么?
<img src="https://static001.geekbang.org/resource/image/87/dd/87c0f81b493e99e715e9129cd3134bdd.jpg" alt="">
学习完今天的内容后,给你留个小作业吧。下面是一个美食数据,如果你拿到下面的数据,按照我们今天讲的准则,你能找到几点问题?如果你来清洗这些数据,你打算怎样清洗呢?
<img src="https://static001.geekbang.org/resource/image/34/fd/347fcfd86d83ff92923cbd01707a35fd.png" alt="">
欢迎在留言区写下你的思考,如果你对今天“数据清洗”的内容还有疑问,也欢迎留言和我讨论。也欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事。

View File

@@ -0,0 +1,197 @@
<audio id="audio" title="12 | 数据集成这些大号一共20亿粉丝" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/28/14/28d44de979dfee9e9b300e580e1c5714.mp3"></audio>
我们采集的数据经常会有冗余重复的情况。举个简单的例子假设你是一个网络综艺节目的制片人一共有12期节目你一共打算邀请30位明星作为节目的嘉宾。你知道这些明星影响力都很大具体在微博上的粉丝数都有标记。于是你想统计下这些明星一共能直接影响到微博上的多少粉丝能产生多大的影响力。
然后你突然发现这些明星的粉丝数总和超过了20亿。那么他们一共会影响到中国20亿人口么显然不是的我们都知道中国人口一共是14亿这30位明星的影响力总和不会覆盖中国所有人口。
那么如何统计这30位明星真实的影响力总和呢这里就需要用到数据集成的概念了。
数据集成就是将多个数据源合并存放在一个数据存储中(如数据仓库),从而方便后续的数据挖掘工作。
据统计大数据项目中80%的工作都和数据集成有关,这里的数据集成有更广泛的意义,包括了数据清洗、数据抽取、数据集成和数据变换等操作。这是因为数据挖掘前,我们需要的数据往往分布在不同的数据源中,需要考虑字段表达是否一样,以及属性是否冗余。
## 数据集成的两种架构ELT和ETL
数据集成是数据工程师要做的工作之一。一般来说数据工程师的工作包括了数据的ETL和数据挖掘算法的实现。算法实现可以理解就是通过数据挖掘算法从数据仓库中找到“金子“。
什么是ETL呢ETL是英文Extract、Transform和Load的缩写顾名思义它包括了数据抽取、转换、加载三个过程。ETL可以说是进行数据挖掘这项工作前的“备菜”过程。
我来解释一下数据抽取、转换、加载这三个过程。
抽取是将数据从已有的数据源中提取出来。
转换是对原始数据进行处理例如将表输入1和 表输入2 进行连接形成一张新的表。
<img src="https://static001.geekbang.org/resource/image/31/68/31a88246298e317c90412bc9c03eee68.png" alt="">
如果是三张表连接的话可以怎么操作呢先将表输入1和表输入2进行连接形成表输入1-2然后将表输入1-2和表输入3进行连接形成新的表。然后再将生成的新表写入目的地。
<img src="https://static001.geekbang.org/resource/image/bd/f7/bd39e4f480f92a1794ccc43f51acf9f7.png" alt="">
根据转换发生的顺序和位置,数据集成可以分为 ETL 和 ELT 两种架构。
ETL 的过程为提取(Extract)——转换(Transform)——加载(Load),在数据源抽取后首先进行转换,然后将转换的结果写入目的地。
ELT 的过程则是提取(Extract)——加载(Load)——变换(Transform)在抽取后将结果先写入目的地然后利用数据库的聚合分析能力或者外部计算框架如Spark来完成转换的步骤。
<img src="https://static001.geekbang.org/resource/image/90/c2/90df6593871fa5974e744907bb145bc2.jpg" alt="">
目前数据集成的主流架构是ETL但未来使用ELT作为数据集成架构的将越来越多。这样做会带来多种好处
<li>
ELT 和 ETL 相比,最大的区别是“重抽取和加载,轻转换”,从而可以用更轻量的方案搭建起一个数据集成平台。使用 ELT 方法在提取完成之后数据加载会立即开始。一方面更省时另一方面ELT允许 BI 分析人员无限制地访问整个原始数据,为分析师提供了更大的灵活性,使之能更好地支持业务。
</li>
<li>
在ELT架构中数据变换这个过程根据后续使用的情况需要在 SQL 中进行,而不是在加载阶段进行。这样做的好处是你可以从数据源中提取数据,经过少量预处理后进行加载。这样的架构更简单,使分析人员更好地了解原始数据的变换过程。
</li>
**ETL工具有哪些**
介绍完了这两种架构你肯定想要知道ETL工具都有哪些
典型的ETL工具有:
<li>
商业软件Informatica PowerCenter、IBM InfoSphere DataStage、Oracle Data Integrator、Microsoft SQL Server Integration Services等
</li>
<li>
开源软件Kettle、Talend、Apatar、Scriptella、DataX、Sqoop等
</li>
相对于传统的商业软件Kettle是一个易于使用的低成本的解决方案。国内很多公司都在使用Kettle用来做数据集成。所以我重点给你讲解下Kettle工具的使用。
## Kettle工具的使用
Kettle是一款国外开源的ETL工具纯Java编写可以在Window和Linux上运行不需要安装就可以使用。Kettle 中文名称叫水壶,该项目的目标是将各种数据放到一个壶里,然后以一种指定的格式流出。
Kettle在2006年并入了开源的商业智能公司Pentaho, 正式命名为Pentaho Data Integeration简称“PDI”。因此Kettle现在是Pentaho的一个组件下载地址[https://community.hitachivantara.com/docs/DOC-1009855](https://community.hitachivantara.com/docs/DOC-1009855)
在使用Kettle之前还需要安装数据库软件和Java运行环境JRE
Kettle采用可视化的方式进行操作来对数据库间的数据进行迁移。它包括了两种脚本Transformation转换和Job作业。
<li>
Transformation转换相当于一个容器对数据操作进行了定义。数据操作就是数据从输入到输出的一个过程。你可以把转换理解成为是比作业粒度更小的容器。在通常的工作中我们会把任务分解成为不同的作业然后再把作业分解成多个转换。
</li>
<li>
Job作业相比于转换是个更大的容器它负责将转换组织起来完成某项作业。
</li>
接下来,我分别讲下这两个脚本的创建过程。
**如何创建Transformation转换**
Transformation可以分成三个步骤它包括了输入、中间转换以及输出。
<img src="https://static001.geekbang.org/resource/image/de/ea/de0b5c9d489a591fa1f478cfd09585ea.png" alt="">
在Transformation中包括两个主要概念Step和Hop。Step的意思就是步骤Hop就是跳跃线的意思。
<li>
Step步骤Step是转换的最小单元每一个Step完成一个特定的功能。在上面这个转换中就包括了表输入、值映射、去除重复记录、表输出这4个步骤
</li>
<li>
Hop跳跃线用来在转换中连接Step。它代表了数据的流向。
</li>
<img src="https://static001.geekbang.org/resource/image/ba/f7/bab04c4d05f3a5dbd02d8abd147630f7.jpg" alt="">
**如何创建Job作业**
完整的任务实际上是将创建好的转换和作业串联起来。在这里Job包括两个概念Job Entry、Hop。
如何理解这两个概念呢?
<li>
Job Entry工作实体Job Entry是Job内部的执行单元每一个Job Entry都是用来执行具体的任务比如调用转换发送邮件等。
</li>
<li>
Hop指连接Job Entry的线。并且它可以指定是否有条件地执行。
</li>
在Kettle中你可以使用Spoon它是一种一种图形化的方式来让你设计Job和Transformation并且可以保存为文件或者保存在数据库中。下面我来带你做一个简单的例子。
**案例1如何将文本文件的内容转化到MySQL数据库中**
这里我给你准备了文本文件这个文件我上传到了GitHub上你可以自行下载[http://t.cn/E4SzvOf](http://t.cn/E4SzvOf),数据描述如下:
<img src="https://static001.geekbang.org/resource/image/3b/97/3b6ad903051b066bfba1a4cf3a0d3197.png" alt="">
下面我来教你如何将文本文件的内容转化到MySQL数据库中。
Step1创建转换右键“转换→新建”
Step2在左侧“核心对象”栏目中选择“文本文件输入”控件拖拽到右侧的工作区中
Step3从左侧选择“表输出”控件拖拽到右侧工作区
Step4鼠标在“文本文件输入”控件上停留在弹窗中选择图标鼠标拖拽到“表输出”控件将一条连线连接到两个控件上
这时我们已经将转换的流程设计好了,现在是要对输入和输出两个控件进行设置。
Step5双击“文本文件输入”控件导入已经准备好的文本文件
Step6双击“表输出”控件这里你需要配置下MySQL数据库的连接同时数据库中需要有一个数据表字段的设置与文本文件的字段设置一致这里我设置了一个wucai数据库以及score数据表。字段包括了name、create_time、Chinese、English、Math与文本文件的字段一致
具体操作可以看下面的演示:
<img src="https://static001.geekbang.org/resource/image/6f/c9/6fb632fe0f3a2cce4169b9633a86c0c9.gif" alt="">
Step7创建数据库字段的对应关系这个需要双击“表输出”找到数据库字段进行字段映射的编辑
<img src="https://static001.geekbang.org/resource/image/8f/04/8fee5a90cab86200102a7006efe88104.png" alt=""><br>
Step8点击左上角的执行图标如下图
<img src="https://static001.geekbang.org/resource/image/f9/6d/f9678df2fa2d1684a03d43f90cce716d.png" alt="">
这样我们就完成了从文本文件到MySQL数据库的转换。
Kettle的控件比较多内容无法在一节课内容中完整呈现我只给你做个入门了解。
另外给你推荐一个Kettle的开源社区[http://www.ukettle.org](http://www.ukettle.org) 。
在社区里你可以和大家进行交流。因为Kettle相比其他工具上手简单而且是开源工具有问题可以在社群里咨询。因此我推荐你使用Kettle作为你的第一个ETL工具。
当然除了Kettle工具实际工作中你可能也会接触到其他的ETL工具这里我给你简单介绍下阿里巴巴的开源工具DataX和Apache的Sqoop。
**阿里开源软件DataX**
在以往的数据库中,数据库都是两两之间进行的转换,没有统一的标准,转换形式是这样的:
<img src="https://static001.geekbang.org/resource/image/cf/50/cf2a017d2055afb1f8236bd6518e1c50.jpg" alt="">
但DataX 可以实现跨平台、跨数据库、不同系统之间的数据同步及交互,它将自己作为标准,连接了不同的数据源,以完成它们之间的转换。
<img src="https://static001.geekbang.org/resource/image/ad/ac/ad35fb37962b548f6bf7a00b291ec9ac.jpg" alt="">
DataX的模式是基于框架+插件完成的DataX的框架如下图
<img src="https://static001.geekbang.org/resource/image/8c/67/8cac4b4298187dcd4621c9a1f9551a67.jpg" alt="">
在这个框架里Job作业被Splitter分割器分成了许多小作业Sub-Job。在DataX里通过两个线程缓冲池来完成读和写的操作读和写都是通过Storage完成数据的交换。比如在“读”模块切分后的小作业将数据从源头装载到DataXStorage然后在“写”模块数据从DataXStorage导入到目的地。
这样的好处就是在整体的框架下我们可以对Reader和Writer进行插件扩充比如我想从MySQL导入到Oracle就可以使用MySQLReader和OracleWriter插件装在框架上使用即可。
**Apache开源软件:Sqoop**
Sqoop是一款开源的工具是由Apache基金会所开发的分布式系统基础架构。Sqoop在Hadoop生态系统中是占据一席之地的它主要用来在Hadoop和关系型数据库中传递数据。通过Sqoop我们可以方便地将数据从关系型数据库导入到HDFS中或者将数据从HDFS导出到关系型数据库中。
Hadoop实现了一个分布式文件系统即HDFS。Hadoop的框架最核心的设计就是HDFS和MapReduce。HDFS为海量的数据提供了存储而MapReduce则为海量的数据提供了计算。
## 总结
今天我介绍了数据集成的两种架构方式以及Kettle工具的基本操作。不要小看了ETL虽然它不直接交付数据挖掘的结果但是却是数据挖掘前重要的工作它包括了抽取各种数据、完成转化和加载这三个步骤。
因此除了数据科学家外还有个工作职位叫ETL工程师这份工作正是我们今天介绍的从事ETL这种架构工作的人。如果你以后有机会从事这份工作你不仅要对今天介绍的数据集成概念有所了解还要掌握至少一种ETL开发工具如Kettle、DataX、 Sqoop等此外还需要熟悉主流数据库技术比如SQL Server、PostgeSQL、Oracle等。
<img src="https://static001.geekbang.org/resource/image/07/a0/0767b2fa01ea526d19857e9b95bc1ba0.jpg" alt="">
这是我操作kettle的流程视频你可以看一下。
<video poster="https://media001.geekbang.org/fbf6c6f0ef2f42c5bf9f198130b9c277/snapshots/5acd5761081a42a7be87ad1a8928ed54-00005.jpg" preload="none" controls=""><source src="https://media001.geekbang.org/customerTrans/6f475a24b1498919eb0a38bef256c23a/15b8fc74-16830ca5b16-0000-0000-01d-dbacd.mp4" type="video/mp4"><source src="https://media001.geekbang.org/fbf6c6f0ef2f42c5bf9f198130b9c277/6f95e4f2689b45f4b4878296ce87a0b3-5d490a3237a5a3067be4a6521f2da2b9-sd.m3u8" type="application/x-mpegURL"><source src="https://media001.geekbang.org/fbf6c6f0ef2f42c5bf9f198130b9c277/6f95e4f2689b45f4b4878296ce87a0b3-88d3b20c5e3c1533960f8165340c3aad-hd.m3u8" type="application/x-mpegURL"></video>
今天我给你讲了数据集成的两种架构以及帮助我们实现ETL的工具Kettle。纸上得来终觉浅绝知此事要躬行。你不妨尝试下如何使用Kettle将MySQL数据库内容转化到文本文件
另我想让你来谈谈你对数据集成的理解如果你之前做过ETL的工具也请你来谈一谈你对ETL的工具选择和使用经历。
欢迎在评论区与我分享你的想法。如果你觉得这篇文章对你有帮助,欢迎点击“请朋友读”,分享给你的朋友和同事。

View File

@@ -0,0 +1,202 @@
<audio id="audio" title="13 | 数据变换:考试成绩要求正态分布合理么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/d1/aa/d1b2ccd5d623553c4df34e4993a71aaa.mp3"></audio>
上一讲中我给你讲了数据集成,今天我来讲下数据变换。
如果一个人在百分制的考试中得了95分你肯定会认为他学习成绩很好如果得了65分就会觉得他成绩不好。如果得了80分呢你会觉得他成绩中等因为在班级里这属于大部分人的情况。
为什么会有这样的认知呢?这是因为我们从小到大的考试成绩基本上都会满足正态分布的情况。什么是正态分布呢?正态分布也叫作常态分布,就是正常的状态下,呈现的分布情况。
比如你可能会问班里的考试成绩是怎样的?这里其实指的是大部分同学的成绩如何。以下图为例,在正态分布中,大部分人的成绩会集中在中间的区域,少部分人处于两头的位置。正态分布的另一个好处就是,如果你知道了自己的成绩,和整体的正态分布情况,就可以知道自己的成绩在全班中的位置。
<img src="https://static001.geekbang.org/resource/image/e7/f5/e77a79d3c483c93e74933becd92b5af5.jpg" alt="">
另一个典型的例子就是美国SAT考试成绩也符合正态分布。而且美国本科的申请需要中国高中生的GPA在80分以上百分制的成绩背后的理由也是默认考试成绩属于正态分布的情况。
为了让成绩符合正态分布,出题老师是怎么做的呢?他们通常可以把考题分成三类:
第一类基础题占总分70%,基本上属于送分题;
第二类:灵活题,基础范围内+一定的灵活性占20%
第三类难题涉及知识面较广的难题占10%
那么你想下如果一个出题老师没有按照上面的标准来出题而是将第三类难题比重占到了70%,也就是我们说的“超纲”,结果会是怎样呢?
你会发现,大部分人成绩都“不及格”,最后在大家激烈的讨论声中,老师会将考试成绩做规范化处理,从而让成绩满足正态分布的情况。因为只有这样,成绩才更具有比较性。所以正态分布的成绩,不仅可以让你了解全班整体的情况,还能了解每个人的成绩在全班中的位置。
## 数据变换在数据分析中的角色
我们再来举个例子假设A考了80分B也考了80分但前者是百分制后者500分是满分如果我们把从这两个渠道收集上来的数据进行集成、挖掘就算使用效率再高的算法结果也不是正确的。因为这两个渠道的分数代表的含义完全不同。
所以说有时候数据变换比算法选择更重要数据错了算法再正确也是错的。你现在可以理解为什么80%的工作时间会花在前期的数据准备上了吧。
那么如何让不同渠道的数据统一到一个目标数据库里呢?这样就用到了数据变换。
在数据变换前,我们需要先对字段进行筛选,然后对数据进行探索和相关性分析,接着是选择算法模型(这里暂时不需要进行模型计算),然后针对算法模型对数据的需求进行数据变换,从而完成数据挖掘前的准备工作。
<img src="https://static001.geekbang.org/resource/image/90/e9/9081a928916973723e66d70c771162e9.jpg" alt=""><br>
所以你从整个流程中可以看出,数据变换是数据准备的重要环节,它**通过数据平滑、数据聚集、数据概化和规范化等方式**将数据转换成适用于数据挖掘的形式。
我来介绍下这些常见的变换方法:
<li>
**数据平滑**:去除数据中的噪声,将连续数据离散化。这里可以采用分箱、聚类和回归的方式进行数据平滑,我会在后面给你讲解聚类和回归这两个算法;
</li>
<li>
**数据聚集**对数据进行汇总在SQL中有一些聚集函数可以供我们操作比如Max()反馈某个字段的数值最大值Sum()返回某个字段的数值总和;
</li>
<li>
**数据概化**:将数据由较低的概念抽象成为较高的概念,减少数据复杂度,即用更高的概念替代更低的概念。比如说上海、杭州、深圳、北京可以概化为中国。
</li>
<li>
**数据规范化**使属性数据按比例缩放这样就将原来的数值映射到一个新的特定区域中。常用的方法有最小—最大规范化、Z—score 规范化、按小数定标规范化等,我会在后面给你讲到这些方法的使用;
</li>
<li>
**属性构造**:构造出新的属性并添加到属性集中。这里会用到特征工程的知识,因为通过属性与属性的连接构造新的属性,其实就是特征工程。比如说,数据表中统计每个人的英语、语文和数学成绩,你可以构造一个“总和”这个属性,来作为新属性。这样“总和”这个属性就可以用到后续的数据挖掘计算中。
</li>
在这些变换方法中,最简单易用的就是对数据进行规范化处理。下面我来给你讲下如何对数据进行规范化处理。
## 数据规范化的几种方法
**1. Min-max 规范化**
Min-max规范化方法是将原始数据变换到[0,1]的空间中。用公式表示就是:
新数值=(原数值-极小值)/(极大值-极小值)。
**2. Z-Score 规范化**
假设A与B的考试成绩都为80分A的考卷满分是100分及格60分B的考卷满分是500分及格300分。虽然两个人都考了80分但是A的80分与B的80分代表完全不同的含义。
那么如何用相同的标准来比较A与B的成绩呢Z-Score就是用来可以解决这一问题的。
我们定义:新数值=(原数值-均值)/ 标准差。
假设A所在的班级平均分为80标准差为10。B所在的班级平均分为400标准差为100。那么A的新数值=(80-80)/10=0B的新数值=(80-400)/100=-3.2。
那么在Z-Score标准下A的成绩会比B的成绩好。
我们能看到Z-Score的优点是算法简单不受数据量级影响结果易于比较。不足在于它需要数据整体的平均值和方差而且结果没有实际意义只是用于比较。
**3.小数定标规范化**
小数定标规范化就是通过移动小数点的位置来进行规范化。小数点移动多少位取决于属性A的取值中的最大绝对值。
举个例子比如属性A的取值范围是-999到88那么最大绝对值为999小数点就会移动3位即新数值=原数值/1000。那么A的取值范围就被规范化为-0.999到0.088。
上面这三种是数值规范化中常用的几种方式。
## Python的SciKit-Learn库使用
SciKit-Learn是Python的重要机器学习库它帮我们封装了大量的机器学习算法比如分类、聚类、回归、降维等。此外它还包括了数据变换模块。
我现在来讲下如何使用SciKit-Learn进行数据规范化。
**1. Min-max 规范化**
我们可以让原始数据投射到指定的空间[min, max]在SciKit-Learn里有个函数MinMaxScaler是专门做这个的它允许我们给定一个最大值与最小值然后将原数据投射到[min, max]中。默认情况下[min,max]是[0,1],也就是把原始数据投放到[0,1]范围内。
我们来看下下面这个例子:
```
# coding:utf-8
from sklearn import preprocessing
import numpy as np
# 初始化数据,每一行表示一个样本,每一列表示一个特征
x = np.array([[ 0., -3., 1.],
[ 3., 1., 2.],
[ 0., 1., -1.]])
# 将数据进行[0,1]规范化
min_max_scaler = preprocessing.MinMaxScaler()
minmax_x = min_max_scaler.fit_transform(x)
print minmax_x
```
运行结果:
```
[[0. 0. 0.66666667]
[1. 1. 1. ]
[0. 1. 0. ]]
```
**2. Z-Score规范化**
在SciKit-Learn库中使用preprocessing.scale()函数可以直接将给定数据进行Z-Score规范化。
```
from sklearn import preprocessing
import numpy as np
# 初始化数据
x = np.array([[ 0., -3., 1.],
[ 3., 1., 2.],
[ 0., 1., -1.]])
# 将数据进行Z-Score规范化
scaled_x = preprocessing.scale(x)
print scaled_x
```
运行结果:
```
[[-0.70710678 -1.41421356 0.26726124]
[ 1.41421356 0.70710678 1.06904497]
[-0.70710678 0.70710678 -1.33630621]]
```
这个结果实际上就是将每行每列的值减去了平均值,再除以方差的结果。
我们看到Z-Score规范化将数据集进行了规范化数值都符合均值为0方差为1的正态分布。
**3. 小数定标规范化**
我们需要用NumPy库来计算小数点的位数。NumPy库我们之前提到过。
这里我们看下运行代码:
```
# coding:utf-8
from sklearn import preprocessing
import numpy as np
# 初始化数据
x = np.array([[ 0., -3., 1.],
[ 3., 1., 2.],
[ 0., 1., -1.]])
# 小数定标规范化
j = np.ceil(np.log10(np.max(abs(x))))
scaled_x = x/(10**j)
print scaled_x
```
运行结果:
```
[[ 0. -0.3 0.1]
[ 0.3 0.1 0.2]
[ 0. 0.1 -0.1]]
```
## 数据挖掘中数据变换比算法选择更重要
在考试成绩中,我们都需要让数据满足一定的规律,达到规范性的要求,便于进行挖掘。这就是数据变换的作用。
如果不进行变换的话,要不就是维数过多,增加了计算的成本,要不就是数据过于集中,很难找到数据之间的特征。
在数据变换中重点是如何将数值进行规范化有三种常用的规范方法分别是Min-Max规范化、Z-Score规范化、小数定标规范化。其中Z-Score规范化可以直接将数据转化为正态分布的情况当然不是所有自然界的数据都需要正态分布我们也可以根据实际的情况进行设计比如取对数log或者神经网络里采用的激励函数等。
<img src="https://static001.geekbang.org/resource/image/e7/e9/e764dc178b5dffd919907fdd0d175ae9.jpg" alt="">
在最后我给大家推荐了Python的sklearn库它和NumPy, Pandas都是非常有名的Python库在数据统计工作中起了很大的作用。SciKit-Learn不仅可以用于数据变换它还提供了分类、聚类、预测等数据挖掘算法的API封装。后面我会详细给你讲解这些算法也会教你如何使用SciKit-Learn工具来完成数据挖掘算法的工作。
最后给你留道思考题吧假设属性income的最小值和最大值分别是5000元和58000元。利用Min-Max规范化的方法将属性的值映射到0至1的范围内那么属性income的16000元将被转化为多少
另外数据规范化都有哪些方式,他们是如何进行规范化的?欢迎在评论区与我分享你的答案,也欢迎你把这篇文章分享给你的朋友或者同事,一起讨论一下。

View File

@@ -0,0 +1,129 @@
<audio id="audio" title="14丨数据可视化掌握数据领域的万金油技能" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/48/8c/484bbea09a7e82b9872cbcdb0a466e8c.mp3"></audio>
上一讲中,我给你讲了数据变换,今天讲一下数据可视化。如果你想做一名数据分析师,那么掌握可视化技能是必不可少的,因为在大部分情况下,老板更关心呈现的结果。
另外当这些可视化的结果呈现在你眼前时,你才能直观地体会到“数据之美”。图片在内容表达上,要远胜于文字,它不仅能体现数据真实性,还能给人很大的想象空间。
## 数据可视化的视图都有哪些?
在了解数据可视化的重要性之后,我们来看下,在数据可视化产品中,一般都包括哪些视图?
我们常用的可视化视图超过20种分别包括文本表、热力图、地图、符号地图、饼图、水平条、堆叠条、并排条、树状图、圆视图、并排圆、线、双线、面积图、双组合、散点图、直方图、盒须图、甘特图、靶心图、气泡图等。
你不用记住这些视图名称都是什么,因为在可视化工具中,操作面板上都会有这些图形可供选择。你看一眼就知道它是不是你想要的。
当然你不仅要掌握这些视图的使用更要了解使用它们背后的目的是什么这里我整理了下可以分为以下的9种情况
<img src="https://static001.geekbang.org/resource/image/5b/d3/5bb98485841aa86f1ca18762e9e04ed3.png" alt=""><br>
在上面的这几种情况里,你也许想要看某个数据的分布情况,或者它随着时间的趋势,或者是局部与整体之间的关系等等。所以在设计之前,你需要思考的是,你的用户是谁,想给他们呈现什么,需要突出数据怎样的特点,以及采用哪种视图来进行呈现。
比如说,你想呈现某个变量的分布情况,就可以通过直方图的形式来呈现。如果你想要看两个变量之间的相关性及分布情况,可以采用散点图的形式呈现。
一个视图可能会有多种表达的目的,比如散点图既可以表明两个变量之间的关系,也可以体现它们的分布情况。同样,如果我想看变量的分布情况,既可以采用散点图的形式,也可以采用直方图的形式。
所以说,具体要采用哪种视图,取决于你想要数据可视化呈现什么样的目的。
## 数据可视化工具都有哪些?
那么如何把数据弄成上面说的视图呢?我们需要借助数据可视化的工具。
这些工具有很多,我从几个维度来给你介绍下。这几个维度分别是商业智能分析软件、可视化大屏、前端可视化组件和编程语言类。
**商业智能分析**
首先在商业智能分析软件中最著名的当属Tableau和PowerBI了另外中国帆软出品的FineBI也受到国内很多企业的青睐。
Tableau是国外的商业软件收费不低。它适合BI工程师、数据分析分析师。如果可以熟练掌握Tableau那么找到一份数据分析的工作是不难的。
PowerBI是微软出品的可以和Excel搭配使用你可以通过PowerBI来呈现Excel的可视化内容。
在BI行业中Tableau和PowerBI远超其他BI产品处于行业的领导者的位置。
另外FineBI是中国的帆软出品针对国内使用更加友好同时也倾向于企业级应用的BI。
**可视化大屏类**
大屏作为一种视觉效果强、科技感强的技术被企业老板所青睐可以很好地展示公司的数据化能力。这里给你介绍两款可视化大屏的软件DataV和FineReport。
- **DataV**
DataV是一款可视化的工具天猫双十一大屏就是用它呈现的。你要做的就是选择相应的控件配置控件的样式、数据传输和交互效果等。当然DataV本身有一些免费的模板你可以直接通过模板来创建。不过一些特殊的控件和交互效果还是需要购买企业版才行。
- **FineReport**
FineReport是帆软出品的工具你可以看出他家的产品基本上都是Fine开头的包括刚才给你介绍的FineBI。FineReport可以做数据大屏也可以做可视化报表在很多行业都有解决方案操作起来也很方便。可以实时连接业务数据对数据进行展示。
**前端可视化组件**
如果你想要成为一名前端数据可视化工程师的话,至少熟练掌握一种前端可视化组件是必不可少的,不少公司招聘“高级前端工程师”的时候,都要求熟悉几个开源数据可视化组件。
可视化组件都是基于Web渲染的技术的。所以你需要了解一下几个典型的Web渲染技术Canvas、SVG和WebGL。简单来说**Canvas和SVG是HTML5中主要的2D图形技术WebGL是3D框架。**
**Canvas适用于位图**也就是给了你一张白板需要你自己来画点。Canvas技术可以绘制比较复杂的动画。不过它是HTML5自带的所以低版本浏览器不支持Canvas。ECharts这个可视化组件就是基于Canvas实现的。
**SVG** 的中文是可缩放矢量图形它是使用XML格式来定义图形的。相当于用点和线来描绘了图形相比于位图来说文件比较小而且任意缩放都不会失真。SVG经常用于图标和图表上。它最大的特点就是支持大部分浏览器动态交互性实现起来也很方便比如在SVG中插入动画元素等。
**WebGL是一种3D绘图协议**能在网页浏览器中呈现3D画面技术并且可以和用户进行交互。你在网页上看到的很多酷炫的3D效果基本上都是用WebGL来渲染的。下面介绍的Three.js就是基于WebGL框架的。
在了解这些Web渲染协议之后我再来带你看下这些常用的可视化组件 Echarts、D3、Three.js和AntV。
ECharts是基于H5 canvas的Javascript图表库是百度的开源项目一直都有更新使用的人也比较多。它作为一个组件可以和DataV、Python进行组合使用。
你可以在DataV企业版中接入ECharts 图表组件。也可以使用Python的Web框架比如Django、Flask+ECharts的解决方案。这样可以让你的项目更加灵活地使用到ECharts的图表库不论你是用Python语言还是用DataV的工具都可以享受到ECharts丰富的图表库样式。
D3 的全称是Data-Driven Documents简单来说是一个 JavaScript 的函数库,因为文件的后缀名通常为“.js”所以 D3 也常使用 D3.js 来称呼。
它提供了各种简单易用的函数,大大简化了 JavaScript 操作数据的难度。你只需要输入几个简单的数据就能够转换为各种绚丽的图形。由于它本质上是JavaScript所以用 JavaScript 也是可以实现所有功能的。
Three.js顾名思义就是Three+JS的意思。“Three”表示3D的意思“Three.js”就是使用JavaScript来实现3D效果。Three.js是一款WebGL框架封装了大量WebGL接口因为直接用WebGL API写3D程序太麻烦了。
AntV是蚂蚁金服出品的一套数据可视化组件包括了 G2、G6、F2和L7一共4个组件。其中G2应该是最知名的它的意思是The grammar Of Graphics也就是一套图形语法。它集成了大量的统计工具而且可以让用户通过简单的语法搭建出多种图表。G6是一套流程图和关系分析的图表库。F2适用于移动端的可视化方案。L7提供了地理空间的数据可视化框架。
**编程语言**
使用数据分析工具你一定离不开Python语言当然也有人使用R语言。在用Python和R做数据分析的时候一定少不了用到可视化的部分。
下面我简单介绍下如何使用Python和R进行数据可视化。
在Python里包括了众多可视化库比如Matplotlib、Seaborn、Bokeh、Plotly、Pyecharts、Mapbox和Geoplotlib。其中使用频率最高最需要掌握的就是Matplotlib和Seaborn。
Matplotlib是Python的可视化基础库作图风格和MATLAB类似所以称为Matplotlib。一般学习Python数据可视化都会从Matplotlib入手然后再学习其他的Python可视化库。
下面这张图就是我拿Matplotlib做的蜘蛛图。
<img src="https://static001.geekbang.org/resource/image/a0/4a/a0c012ecf3831d9657faf744c8cbf74a.jpg" alt=""><br>
Seaborn是一个基于Matplotlib的高级可视化效果库针对Matplotlib做了更高级的封装让作图变得更加容易。你可以用短小的代码绘制更多维度数据的可视化效果图比如下面这个例子
<img src="https://static001.geekbang.org/resource/image/8c/f3/8c9372266b616109fbe3847d9c6ef0f3.jpg" alt=""><br>
在R中也有很多可视化库可供选择。其中包括了R自带的绘图包Graphics以及工具包ggplot2、ggmap、timevis和plotly等。
其中ggplot2是R语言中重要的绘图包这个工具包将数据与绘图操作进行了分离所以使用起来清晰明了画出的图也漂亮。其实在Python里后来也引入了ggplot库这样在Python中也可以很方便地使用到ggplot而且和R语言中的ggplot2代码差别不大稍作修改就能直接在Python中运行了。
## 如何开始数据可视化的学习
其实很多企业都有在用商业分析软件Tableau算是使用率很高的。如果你想做相关的数据分析研究掌握一门语言尤其是Python还是很有必要的。如果你想要全面的学习数据可视化你可以有以下的3个路径
**1. 重点推荐Tableau**
Tableau在可视化灵活分析上功能强大主要目标用户更多是较专业的数据分析师。同时在工作场景中使用率高因此掌握Tableau对于晋升和求职都很有帮助。不过Tableau是个商业软件收费不低。而且上手起来有一些门槛需要一定数据基础。
**2. 使用微图、DataV**
前面我给你讲过八爪鱼的使用,微图和八爪鱼是一家公司的产品,使用起来非常方便,而且免费。当你用八爪鱼采集数据之后,就直接可以用微图进行数据可视化。
DataV是阿里推出的数字大屏技术不过它是收费的产品。它最大的好处就是可以分享链接让别人可以在线浏览不需要像Tableau一样安装客户端才能看到数据可视化的结果。另外DataV有一些模板你直接可以使用。
你可以先使用微图和DataV作为你的数据可视化体验工具因为成本低上手起来快。这样你对数据可视化可以有个直观的了解。如果你想从事数据可视化这份工作你可以花更多的精力去研究和学习Tableau。
**3. Python可视化**
Python是数据分析的首选语言如果你不进行编程可以使用我在上文中提到的数据可视化的工具。如果你的目标是个数据挖掘工程师或者算法工程师那么最重要的就是要了解并且熟练掌握Python的数据可视化。
## 总结
我今天给你介绍了数据可视化的视图然后带你讲解了当前主流的数据可视化工具。Tableau 和 PowerBI 是BI商业智能行业的领导者是很多大公司里商业数据分析工作必备的工具。如果你使用Python作为数据分析的语言那么也需要对Python数据可视化有所掌握。
<img src="https://static001.geekbang.org/resource/image/bd/5b/bd49dbaffdc170ecc4d56d946afd5c5b.jpg" alt=""><br>
最后给你留两道思考题吧。你平时的工作是怎样的,是否需要用到数据可视化技术呢?在数据可视化技术中,你都用过哪些工具,你觉得哪个工具使用起来比较顺手?
欢迎和我在评论区进行讨论,也欢迎你把这篇文章分享给你的朋友或者同事。

View File

@@ -0,0 +1,394 @@
<audio id="audio" title="15丨一次学会Python数据可视化的10种技能" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a9/54/a91eb41bd136885f75bfd4a40fdd7054.mp3"></audio>
今天我来给你讲讲Python的可视化技术。
如果你想要用Python进行数据分析就需要在项目初期开始进行探索性的数据分析这样方便你对数据有一定的了解。其中最直观的就是采用数据可视化技术这样数据不仅一目了然而且更容易被解读。同样在数据分析得到结果之后我们还需要用到可视化技术把最终的结果呈现出来。
## 可视化视图都有哪些?
按照数据之间的关系我们可以把可视化视图划分为4类它们分别是比较、联系、构成和分布。我来简单介绍下这四种关系的特点
<li>
比较:比较数据间各类别的关系,或者是它们随着时间的变化趋势,比如折线图;
</li>
<li>
联系:查看两个或两个以上变量之间的关系,比如散点图;
</li>
<li>
构成:每个部分占整体的百分比,或者是随着时间的百分比变化,比如饼图;
</li>
<li>
分布:关注单个变量,或者多个变量的分布情况,比如直方图。
</li>
同样,按照变量的个数,我们可以把可视化视图划分为单变量分析和多变量分析。
单变量分析指的是一次只关注一个变量。比如我们只关注“身高”这个变量,来看身高的取值分布,而暂时忽略其他变量。
多变量分析可以让你在一张图上可以查看两个以上变量的关系。比如“身高”和“年龄”,你可以理解是同一个人的两个参数,这样在同一张图中可以看到每个人的“身高”和“年龄”的取值,从而分析出来这两个变量之间是否存在某种联系。
可视化的视图可以说是分门别类多种多样今天我主要介绍常用的10种视图这些视图包括了散点图、折线图、直方图、条形图、箱线图、饼图、热力图、蜘蛛图、二元变量分布和成对关系。
<img src="https://static001.geekbang.org/resource/image/46/75/4673a17085302cfe9177f8ee687ac675.png" alt="">
下面我给你一一进行介绍。
**散点图**
散点图的英文叫做scatter plot它将两个变量的值显示在二维坐标中非常适合展示两个变量之间的关系。当然除了二维的散点图我们还有三维的散点图。
我在上一讲中给你简单介绍了下Matplotlib这个工具在Matplotlib中我们经常会用到pyplot这个工具包它包括了很多绘图函数类似Matlab的绘图框架。在使用前你需要进行引用
```
import matplotlib.pyplot as plt
```
在工具包引用后画散点图需要使用plt.scatter(x, y, marker=None)函数。x、y 是坐标marker代表了标记的符号。比如“x”、“&gt;”或者“o”。选择不同的marker呈现出来的符号样式也会不同你可以自己试一下。
下面三张图分别对应“x”“&gt;”和“o”。
<img src="https://static001.geekbang.org/resource/image/7a/f9/7a3e19e006a354eacc230fe87f623cf9.png" alt=""><br>
除了Matplotlib外你也可以使用Seaborn进行散点图的绘制。在使用Seaborn前也需要进行包引用
```
import seaborn as sns
```
在引用seaborn工具包之后就可以使用seaborn工具包的函数了。如果想要做散点图可以直接使用sns.jointplot(x, y, data=None, kind='scatter')函数。其中x、y是data中的下标。data就是我们要传入的数据一般是DataFrame类型。kind这类我们取scatter代表散点的意思。当然kind还可以取其他值这个我在后面的视图中会讲到不同的kind代表不同的视图绘制方式。
好了让我们来模拟下假设我们的数据是随机的1000个点。
```
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
N = 1000
x = np.random.randn(N)
y = np.random.randn(N)
# 用Matplotlib画散点图
plt.scatter(x, y,marker='x')
plt.show()
# 用Seaborn画散点图
df = pd.DataFrame({'x': x, 'y': y})
sns.jointplot(x=&quot;x&quot;, y=&quot;y&quot;, data=df, kind='scatter');
plt.show()
```
我们运行一下这个代码就可以看到下面的视图第一张图为Matplotlib绘制的第二张图为Seaborn绘制的。其实你能看到Matplotlib和Seaborn的视图呈现还是有差别的。Matplotlib默认情况下呈现出来的是个长方形。而Seaborn呈现的是个正方形而且不仅显示出了散点图还给了这两个变量的分布情况。
Matplotlib绘制
<img src="https://static001.geekbang.org/resource/image/28/03/2823ea9c7c2d988c1fdb3e7c8fb1e603.png" alt="">
Seaborn绘制
<img src="https://static001.geekbang.org/resource/image/5f/b9/5f06e23188cb31bc549cfd60696e75b9.png" alt="">
**折线图**
折线图可以用来表示数据随着时间变化的趋势。
在Matplotlib中我们可以直接使用plt.plot()函数当然需要提前把数据按照x轴的大小进行排序要不画出来的折线图就无法按照x轴递增的顺序展示。
在Seaborn中我们使用sns.lineplot (x, y, data=None)函数。其中x、y是data中的下标。data就是我们要传入的数据一般是DataFrame类型。
这里我们设置了x、y的数组。x数组代表时间y数组我们随便设置几个取值。下面是详细的代码。
```
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
x = [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019]
y = [5, 3, 6, 20, 17, 16, 19, 30, 32, 35]
# 使用Matplotlib画折线图
plt.plot(x, y)
plt.show()
# 使用Seaborn画折线图
df = pd.DataFrame({'x': x, 'y': y})
sns.lineplot(x=&quot;x&quot;, y=&quot;y&quot;, data=df)
plt.show()
```
然后我们分别用Matplotlib和Seaborn进行画图可以得到下面的图示。你可以看出这两个图示的结果是完全一样的只是在seaborn中标记了x和y轴的含义。
<img src="https://static001.geekbang.org/resource/image/25/88/258c6a2fbd7786ed7bd86a5f50c49b88.png" alt="">
<img src="https://static001.geekbang.org/resource/image/77/60/77d619cc2a4131e97478df490cc43d60.png" alt="">
**直方图**
直方图是比较常见的视图它是把横坐标等分成了一定数量的小区间这个小区间也叫作“箱子”然后在每个“箱子”内用矩形条bars展示该箱子的箱子数也就是y值这样就完成了对数据集的直方图分布的可视化。
在Matplotlib中我们使用plt.hist(x, bins=10)函数其中参数x是一维数组bins代表直方图中的箱子数量默认是10。
在Seaborn中我们使用sns.distplot(x, bins=10, kde=True)函数。其中参数x是一维数组bins代表直方图中的箱子数量kde代表显示核密度估计默认是True我们也可以把kde设置为False不进行显示。核密度估计是通过核函数帮我们来估计概率密度的方法。
这是一段绘制直方图的代码。
```
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
a = np.random.randn(100)
s = pd.Series(a)
# 用Matplotlib画直方图
plt.hist(s)
plt.show()
# 用Seaborn画直方图
sns.distplot(s, kde=False)
plt.show()
sns.distplot(s, kde=True)
plt.show()
```
我们创建一个随机的一维数组然后分别用Matplotlib和Seaborn进行直方图的显示结果如下你可以看出没有任何差别其中最后一张图就是kde默认为Ture时的显示情况。
<img src="https://static001.geekbang.org/resource/image/fc/0d/fccd31462e7de6f56b4aca262b46650d.png" alt="">
<img src="https://static001.geekbang.org/resource/image/fb/af/fb7a2db332dcd5c7c18a4961794923af.png" alt="">
<img src="https://static001.geekbang.org/resource/image/9c/19/9cded19e1c877f98f55d4c6726ff2f19.png" alt="">
**条形图**
如果说通过直方图可以看到变量的数值分布,那么条形图可以帮我们查看类别的特征。在条形图中,长条形的长度表示类别的频数,宽度表示类别。
在Matplotlib中我们使用plt.bar(x, height)函数其中参数x代表x轴的位置序列height是y轴的数值序列也就是柱子的高度。
在Seaborn中我们使用sns.barplot(**x=None, y=None, data=None**)函数。其中参数data为DataFrame类型x、y是data中的变量。
```
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
x = ['Cat1', 'Cat2', 'Cat3', 'Cat4', 'Cat5']
y = [5, 4, 8, 12, 7]
# 用Matplotlib画条形图
plt.bar(x, y)
plt.show()
# 用Seaborn画条形图
sns.barplot(x, y)
plt.show()
```
我们创建了x、y两个数组分别代表类别和类别的频数然后用Matplotlib和Seaborn进行条形图的显示结果如下
<img src="https://static001.geekbang.org/resource/image/d9/3a/d9a247a6fbee488cc8eb62f96947173a.png" alt="">
<img src="https://static001.geekbang.org/resource/image/75/31/7553f2fa08e3962ed9902d4cef796c31.png" alt="">
**箱线图**
箱线图又称盒式图它是在1977年提出的由五个数值点组成最大值(max)、最小值(min)、中位数(median)和上下四分位数(Q3, Q1)。它可以帮我们分析出数据的差异性、离散程度和异常值等。
在Matplotlib中我们使用plt.boxplot(x, labels=None)函数其中参数x代表要绘制箱线图的数据labels是缺省值可以为箱线图添加标签。
在Seaborn中我们使用sns.boxplot(**x=None, y=None, data=None**)函数。其中参数data为DataFrame类型x、y是data中的变量。
```
# 数据准备
# 生成10*4维度数据
data=np.random.normal(size=(10,4))
labels = ['A','B','C','D']
# 用Matplotlib画箱线图
plt.boxplot(data,labels=labels)
plt.show()
# 用Seaborn画箱线图
df = pd.DataFrame(data, columns=labels)
sns.boxplot(data=df)
plt.show()
```
这段代码中我生成0-1之间的10*4维度数据然后分别用Matplotlib和Seaborn进行箱线图的展示结果如下。
Matplotlib绘制
<img src="https://static001.geekbang.org/resource/image/60/e0/6083f7fc15028eae5e3f49e60fad90e0.png" alt="">
Seaborn绘制
<img src="https://static001.geekbang.org/resource/image/42/e0/42fe2a9864bbc2bc0034a0973673d1e0.png" alt="">
**饼图**
饼图是常用的统计学模块可以显示每个部分大小与总和之间的比例。在Python数据可视化中它用的不算多。我们主要采用Matplotlib的pie函数实现它。
在Matplotlib中我们使用plt.pie(x, labels=None)函数其中参数x代表要绘制饼图的数据labels是缺省值可以为饼图添加标签。
这里我设置了labels数组分别代表高中、本科、硕士、博士和其他几种学历的分类标签。nums代表这些学历对应的人数。
```
import matplotlib.pyplot as plt
# 数据准备
nums = [25, 37, 33, 37, 6]
labels = ['High-school','Bachelor','Master','Ph.d', 'Others']
# 用Matplotlib画饼图
plt.pie(x = nums, labels=labels)
plt.show()
```
通过Matplotlib的pie函数我们可以得出下面的饼图
<img src="https://static001.geekbang.org/resource/image/45/f7/45c38de6563d528f610bfcef5c8874f7.png" alt="">
**热力图**
热力图英文叫heat map是一种矩阵表示方法其中矩阵中的元素值用颜色来代表不同的颜色代表不同大小的值。通过颜色就能直观地知道某个位置上数值的大小。另外你也可以将这个位置上的颜色与数据集中的其他位置颜色进行比较。
热力图是一种非常直观的多元变量分析方法。
我们一般使用Seaborn中的sns.heatmap(data)函数其中data代表需要绘制的热力图数据。
这里我们使用Seaborn中自带的数据集flights该数据集记录了1949年到1960年期间每个月的航班乘客的数量。
```
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
flights = sns.load_dataset(&quot;flights&quot;)
data=flights.pivot('year','month','passengers')
# 用Seaborn画热力图
sns.heatmap(data)
plt.show()
```
通过seaborn的heatmap函数我们可以观察到不同年份不同月份的乘客数量变化情况其中颜色越浅的代表乘客数量越多如下图所示
<img src="https://static001.geekbang.org/resource/image/57/93/57e1bc17d943620620fb087d6190df93.png" alt="">
**蜘蛛图**
蜘蛛图是一种显示一对多关系的方法。在蜘蛛图中,一个变量相对于另一个变量的显著性是清晰可见的。
假设我们想要给王者荣耀的玩家做一个战力图指标一共包括推进、KDA、生存、团战、发育和输出。那该如何做呢
这里我们需要使用Matplotlib来进行画图首先设置两个数组labels和stats。他们分别保存了这些属性的名称和属性值。
因为蜘蛛图是一个圆形,你需要计算每个坐标的角度,然后对这些数值进行设置。当画完最后一个点后,需要与第一个点进行连线。
因为需要计算角度所以我们要准备angles数组又因为需要设定统计结果的数值所以我们要设定stats数组。并且需要在原有angles和stats数组上增加一位也就是添加数组的第一个元素。
```
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties
# 数据准备
labels=np.array([u&quot;推进&quot;,&quot;KDA&quot;,u&quot;生存&quot;,u&quot;团战&quot;,u&quot;发育&quot;,u&quot;输出&quot;])
stats=[83, 61, 95, 67, 76, 88]
# 画图数据准备,角度、状态值
angles=np.linspace(0, 2*np.pi, len(labels), endpoint=False)
stats=np.concatenate((stats,[stats[0]]))
angles=np.concatenate((angles,[angles[0]]))
# 用Matplotlib画蜘蛛图
fig = plt.figure()
ax = fig.add_subplot(111, polar=True)
ax.plot(angles, stats, 'o-', linewidth=2)
ax.fill(angles, stats, alpha=0.25)
# 设置中文字体
font = FontProperties(fname=r&quot;C:\Windows\Fonts\simhei.ttf&quot;, size=14)
ax.set_thetagrids(angles * 180/np.pi, labels, FontProperties=font)
plt.show()
```
代码中flt.figure是创建一个空白的figure对象这样做的目的相当于画画前先准备一个空白的画板。然后add_subplot(111)可以把画板划分成1行1列。再用ax.plot和ax.fill进行连线以及给图形上色。最后我们在相应的位置上显示出属性名。这里需要用到中文Matplotlib对中文的显示不是很友好因此我设置了中文的字体font这个需要在调用前进行定义。最后我们可以得到下面的蜘蛛图看起来是不是很酷
<img src="https://static001.geekbang.org/resource/image/19/7d/1924d3cbf035053fa3d5043794624c7d.png" alt="">
**二元变量分布**
如果我们想要看两个变量之间的关系,就需要用到二元变量分布。当然二元变量分布有多种呈现方式,开头给你介绍的散点图就是一种二元变量分布。
在Seaborn里使用二元变量分布是非常方便的直接使用sns.jointplot(x, y, data=None, kind)函数即可。其中用kind表示不同的视图类型“kind='scatter'”代表散点图“kind='kde'”代表核密度图“kind='hex' ”代表Hexbin图它代表的是直方图的二维模拟。
这里我们使用Seaborn中自带的数据集tips这个数据集记录了不同顾客在餐厅的消费账单及小费情况。代码中total_bill保存了客户的账单金额tip是该客户给出的小费金额。我们可以用Seaborn中的jointplot来探索这两个变量之间的关系。
```
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
tips = sns.load_dataset(&quot;tips&quot;)
print(tips.head(10))
# 用Seaborn画二元变量分布图散点图核密度图Hexbin图
sns.jointplot(x=&quot;total_bill&quot;, y=&quot;tip&quot;, data=tips, kind='scatter')
sns.jointplot(x=&quot;total_bill&quot;, y=&quot;tip&quot;, data=tips, kind='kde')
sns.jointplot(x=&quot;total_bill&quot;, y=&quot;tip&quot;, data=tips, kind='hex')
plt.show()
```
代码中我用kind分别显示了他们的散点图、核密度图和Hexbin图如下图所示。
散点图:
核密度图:
Hexbin图
###
**成对关系**
如果想要探索数据集中的多个成对双变量的分布可以直接采用sns.pairplot()函数。它会同时展示出DataFrame中每对变量的关系另外在对角线上你能看到每个变量自身作为单变量的分布情况。它可以说是探索性分析中的常用函数可以很快帮我们理解变量对之间的关系。
pairplot函数的使用就像在DataFrame中使用describe()函数一样方便,是数据探索中的常用函数。
这里我们使用Seaborn中自带的iris数据集这个数据集也叫鸢尾花数据集。鸢尾花可以分成Setosa、Versicolour和Virginica三个品种在这个数据集中针对每一个品种都有50个数据每个数据中包括了4个属性分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。通过这些数据需要你来预测鸢尾花卉属于三个品种中的哪一种。
```
import matplotlib.pyplot as plt
import seaborn as sns
# 数据准备
iris = sns.load_dataset('iris')
# 用Seaborn画成对关系
sns.pairplot(iris)
plt.show()
```
这里我们用Seaborn中的pairplot函数来对数据集中的多个双变量的关系进行探索如下图所示。从图上你能看出一共有sepal_length、sepal_width、petal_length和petal_width4个变量它们分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度。
下面这张图相当于这4个变量两两之间的关系。比如矩阵中的第一张图代表的就是花萼长度自身的分布图它右侧的这张图代表的是花萼长度与花萼宽度这两个变量之间的关系。
<img src="https://static001.geekbang.org/resource/image/88/0d/885450d23f468b9cbcabd90ff9a3480d.png" alt="">
## 总结
我今天给你讲了Python可视化工具包Matplotlib和Seaborn工具包的使用。他们两者之间的关系就相当于NumPy和Pandas的关系。Seaborn是基于Matplotlib更加高级的可视化库。
另外针对我讲到的这10种可视化视图可以按照变量之间的关系对它们进行分类这些关系分别是比较、联系、构成和分布。当然我们也可以按照随机变量的个数来进行划分比如单变量分析和多变量分析。在数据探索中成对关系pairplot()的使用相好比Pandas中的describe()使用一样方便,常用于项目初期的数据可视化探索。
在Matplotlib和Seaborn的函数中我只列了最基础的使用也方便你快速上手。当然如果你也可以设置修改颜色、宽度等视图属性。你可以自己查看相关的函数帮助文档。这些留给你来进行探索。
关于本次Python可视化的学习我希望你能掌握
<li>
视图的分类,以及可以从哪些维度对它们进行分类;
</li>
<li>
十种常见视图的概念以及如何在Python中进行使用都需要用到哪些函数
</li>
<li>
需要自己动手跑一遍案例中的代码体验下Python数据可视化的过程。
</li>
<img src="https://static001.geekbang.org/resource/image/8e/d2/8ed2addb00a4329dd63bba669f427fd2.png" alt="">
最后我给你留两道思考题吧Seaborn数据集中自带了car_crashes数据集这是一个国外车祸的数据集你要如何对这个数据集进行成对关系的探索呢第二个问题就是请你用Seaborn画二元变量分布图如果想要画散点图核密度图Hexbin图函数该怎样写
欢迎你在评论区与我分享你的答案,也欢迎点击“请朋友读”,把这篇文章分享给你的朋友或者同事,一起来动手练习一下。

View File

@@ -0,0 +1,243 @@
<audio id="audio" title="16丨数据分析基础篇答疑" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/4d/3c/4dddb2c025ea8fb2d49396dcc8a37c3c.mp3"></audio>
截止到今天我们已经将数据分析基础篇的内容都学习完了。在这个过程中感谢大家积极踊跃地进行留言既给其他同学提供了不少帮助也让专栏增色了不少。在这些留言中有很多同学对某个知识点有所疑惑我总结了NumPy、Pandas、爬虫以及数据变换中同学们遇到的问题精选了几个具有代表性的来作为答疑。
## NumPy相关
**答疑1如何理解NumPy中axis的使用**
这里我引用文稿中的一段代码:
```
a = np.array([[4,3,2],[2,4,1]])
print np.sort(a)
print np.sort(a, axis=None)
print np.sort(a, axis=0)
print np.sort(a, axis=1)
```
同学们最容易混淆的是axis=0 和 axis=1的顺序。你可以记住axis=0代表跨行实际上就是按列axis=1 代表跨列(实际上就是按行)。
如果排序的时候没有指定axis默认axis=-1代表就是按照数组最后一个轴来排序。如果axis=None代表以扁平化的方式作为一个向量进行排序。
所以上面的运行结果为:
```
[[2 3 4]
[1 2 4]]
[1 2 2 3 4 4]
[[2 3 1]
[4 4 2]]
[[2 3 4]
[1 2 4]]
```
我解释下axis=0的排序结果axis=0代表的是跨行跨行就是按照列所以实际上是对[4, 2] [3, 4] [2, 1]来进行排序,排序结果是[2, 4] [3, 4] [1, 2],对应的是每一列的排序结果。还原到矩阵中也就是 [[2 3 1], [4, 4, 2]]。
###
**答疑2定义结构数组中的S32代表什么意思**
我文稿中定义了一个结构数组persontype。
```
import numpy as np
persontype = np.dtype({
'names':['name', 'age', 'chinese', 'math', 'english'],
'formats':['S32','i', 'i', 'i', 'f']})
```
这里实际上用的是numpy中的字符编码来表示数据类型的定义比如i代表整数f代表单精度浮点数S代表字符串S32代表的是32个字符的字符串。
<img src="https://static001.geekbang.org/resource/image/74/3c/74e6c7e0a9b9805f746703fbc55c763c.png" alt="">
如果数据中使用了中文可以把类型设置为U32比如
```
import numpy as np
persontype = np.dtype({
'names':['name', 'age', 'chinese', 'math', 'english'],
'formats':['U32','i', 'i', 'i', 'f']})
peoples = np.array([(&quot;张飞&quot;,32,75,100, 90),(&quot;关羽&quot;,24,85,96,88.5), (&quot;赵云&quot;,28,85,92,96.5),(&quot;黄忠&quot;,29,65,85,100)], dtype=persontype)
```
**答疑3PyCharm中无法import numpy的问题**
有些同学已经安装好了numpy但在PyCharm中依然无法使用numpy。遇到这个问题的主要原因是PyCharm会给每一个新建的项目都是一个全新的虚拟环境。
<img src="https://static001.geekbang.org/resource/image/39/39/39ffb856f0937de79e2d3a1363537639.png" alt="">
在这个环境下默认的包只有pip、setuptools和wheel这三个工具你可以在File-&gt;Settings里面找到这个界面。
<img src="https://static001.geekbang.org/resource/image/7f/d8/7fbc03617a3d14b52ca62651be813cd8.png" alt="">
这说明numpy并没有配置到你创建的这个Project下的环境中需要手动点击右侧的+号对numpy进行添加。
<img src="https://static001.geekbang.org/resource/image/a8/e1/a8d6063d8cdae8bdf90947f9b69f89e1.png" alt=""><br>
添加之后,你就可以正常运行程序,显示出结果了。
**答疑4我不明白为什么打印出来的name会带一个b**
这位同学的代码是这样的:
```
student = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')])
a = np.array([('abc', 21, 50),('xyz', 18, 75)], dtype = student)
print(a)
print(a['name'])
结果:
[(b'abc', 21, 50.) (b'xyz', 18, 75.)]
[b'abc' b'xyz']
```
我来解释一下。Python3 默认str是Unicode类型所以要转成bytestring会在原来的str前加上b。如果你用py2.7就不会有这个问题py3的b只是告诉你这里它转化成了bytestring进行输出。
**答疑5np.ceil代表什么意思**
ceil是numpy中的一个函数代表向上取整。比如np.ceil(2.4)=3。
## 数据分析思维培养及练习相关
**答疑1Online Judge的比赛题目数学不好怎么办**
Vol1~Vol32的难度是逐渐增加吗的怎么可以选出有易到难的题目
Online Judge有一些简单的题目可以选择选择使用人数多且accepted比例高的题目。另外它面向的是一些参加比赛的人员比如高中的NOI比赛或者大学的ACM比赛。你也可以选择leetcode或者pythontip进行训练。
难度不一定是增加的而是出题的先后顺序。难易程度你可以看下提交的人数和Accepted的比例。提交人数和Accepted比例越高说明越简单。
**答疑2加餐中小区宽带使用多台手机等设备不会被检测到吗**
小区宽带和手机飞行是两种解决方案。用手机飞行不需要用到小区宽带。 用小区宽带需要使用到交换机这里可以自己来控制交换机每次自动切换IP。
**答疑3加餐中提到的一万个手机号。。。那怎么更换呢也要一万台设备吗**
1万个手机号主要用于账号注册通常采用的是“卡池”这个设备。简单来说卡池可以帮你做收发短信。一个卡池设备512张卡并发32路。
有了卡池还需要算法。你不能让这512张卡每次操作都是有规律可循的比如都是同步执行某项操作否则微信、Facebook会直接把它们干掉。学过数据挖掘的人应该会知道这512张卡如果是协同操作可以直接被算法识别出来。在微信、Facebook看来这512张卡实际上是同一个人也就是“机器人”。所以卡池可以帮你做短信验证码以便账号登录用。MIFI+SIM帮你做手机流量上网用。这是两套不同的设备。
**答疑4听说企业里用SQL和Excel进行数据分析的很多这块该如何选择**
SQL和Excel做统计的工作多一些涉及到编程的很少。如果你想在这个行业进一步提升或者做一名算法工程师那么你都要和Python打交道。专栏里数据挖掘算法的部分是用Python交付的。Excel和SQL很难做数据挖掘。
如果想对数据概况有个了解做一些基础分析用Excel和SQL是OK的。但是想进一步挖掘数据的价值掌握Python还是挺有必要的。
另外如果你做的是数据可视化工作在企业里会用到tableau或者powerBI这些工具。数据采集你也可以选择第三方工具或者自己用Python来编写。
**答疑5学一些算法的时候比如SVM是不是掌握它们的理论内容即可。不需要自己去实现用的时候调用库即可**
是的这些算法都有封装直接使用即可。在python的sklearn中就是一行语句的事。
**答疑6老师我现在等于从零开始学数据挖掘所谓的数学基础指的是把高数学到哪种境界啊是像考研那样不管极限导数积分每种题型都要会解还是只需要了解这些必备的高数基础的概念**
不需要求解每一道数学题,只需要具备高数基础概念即可!概率论与数理统计、线性代数、最优化方法和图论这些,我在算法中涉及的地方都会讲到,你暂时不用提前学习这些数学知识。我觉得最好的方式就是在案例中灵活运用,这样可以加深你对这些数学知识的理解。
对于大部分从0开始学数据挖掘的人来说可以淡化公式重点理解使用场景和概念。
## 爬虫相关问题
**答疑1关于Python爬虫工具的推荐**
我除了在专栏里讲到了**Requests、XPath解析**以及Selenium、PhantomJS。还有一些工具是值得推荐的。
Scrapy是一个Python的爬虫框架它依赖的工具比较多所以在pip install的时候会安装多个工具包。scrapy本身包括了爬取、处理、存储等工具。在scrapy中有一些组件是提供给你的需要你针对具体任务进行编写。比如在item.py对抓取的内容进行定义在spider.py中编写爬虫在pipeline.py中对抓取的内容进行存储可以保存为csv等格式。这里不具体讲解scrapy的使用。
另外Puppeteer是个很好的选择可以控制Headless Chrome这样就不用Selenium和PhantomJS。与Selenium相比Puppeteer直接调用Chrome的API接口不需要打开浏览器直接在V8引擎中处理同时这个组件是由Google的Chrome团队维护的所以兼容性会很好。
**答疑2driver = webdriver.Chrome(),为什么输入这个代码就会报错了呢?**
报错的原因是没有下载或正确配置ChromeDriver路径正确的方法如下
1.下载ChromeDriver并放到Chrome浏览器目录中
下载地址:[http://npm.taobao.org/mirrors/chromedriver/72.0.3626.7/](http://npm.taobao.org/mirrors/chromedriver/72.0.3626.7/)
2.将Chrome浏览器目录添加到系统的环境变量Path中然后再运行下试试.
另外你也可以在代码中设置ChromeDriver的路径方法如下
```
chrome_driver = &quot;C:\Users\cheny\AppData\Local\Google\Chrome\Application\chromedriver.exe&quot;
driver = webdriver.Chrome(executable_path=chrome_driver)
```
**答疑3如果是需要用户登陆后才能爬取的数据该怎么用python来实现呢**
你可以使用Python+Selenium的方式完成账户的自动登录因为Selenium是个自动化测试的框架使用Selenium的webdriver就可以模拟浏览器的行为。找到输入用户名密码的地方输入相应的值然后模拟点击即可完成登录没有验证码的情况下
另外你也可以使用cookie来登录网站方法是你登录网站时先保存网站的cookie然后在下次访问的时候加载之前保存的cookie放到request headers中这样就不需要再登录网站了。
**答疑4为什么我在豆瓣网查询图片的网址与你不一样[https://www.douban.com/search?cat=1025&amp;q=](https://www.douban.com/search?cat=1025&amp;q=)王祖贤&amp;source=suggest 。**
咱们访问豆瓣查询图片的网址应该是一样的。只是我给出的是json的链接。
方法是这样的用Chrome浏览器的开发者工具可以监测出来网页中是否有json数据的传输所以我给出的链接是json数据传输的链接 [https://www.douban.com/j/search_photo?q=%E7%8E%8B%E7%A5%96%E8%B4%A4&amp;limit=20&amp;start=0](https://www.douban.com/j/search_photo?q=%E7%8E%8B%E7%A5%96%E8%B4%A4&amp;limit=20&amp;start=0)
**答疑5XHR数据这个是如何查出来的我使用chrome的开发者工具查看XHR数据但是查不到这部分麻烦老师帮忙解答。**
你需要使用浏览器的插件查看 XHR 数据,比如在 Chrome的开发者工具。
在豆瓣搜索中,我们对“王祖贤”进行了模拟,发现 XHR 数据中有一个请求是这样的:
[https://www.douban.com/j/search_photo?q=](https://www.douban.com/j/search_photo?q=)王祖贤&amp;limit=20&amp;start=0
你可以看一下操作流程。
<video preload="none" controls=""><source src="https://static001.geekbang.org/customerTrans/6f475a24b1498919eb0a38bef256c23a/1b95ea61-1685a730c41-0000-0000-01d-dbacd.mp4" type="video/mp4"><source src="https://media001.geekbang.org/f875159eb09240e98f80d05a1bfaf2aa/26d1897f4d544e789e7b244111980b4a-8412840b86d68500c43f9db956f7d968-sd.m3u8" type="application/x-mpegURL"><source src="https://media001.geekbang.org/f875159eb09240e98f80d05a1bfaf2aa/26d1897f4d544e789e7b244111980b4a-8068a4641b9e65f1564e6c58db797859-hd.m3u8" type="application/x-mpegURL"></video>
## 数据变换相关
**答疑1数据规范化、归一化、标准化是同一个概念么**
数据规范化是更大的概念,它指的是将不同渠道的数据,都按照同一种尺度来进行度量,这样做有两个好处,一是让数据之间具有可比较性;另一个好处就是方便后续运算,因为数据在同一个数量级上规整了,在机器学习迭代的时候,也会加快收敛效率。
数据归一化和数据标准化都是数据规范化的方式。不同点在于数据归一化会让数据在一个[0,1]或者[-1,1]的区间范围内。而数据标准化会让规范化的数据呈现正态分布的情况,所以你可以这么记:归一化的“一”,是让数据在[0,1]的范围内。而标准化,目标是让数据呈现标准的正态分布。
**答疑2什么时候会用到数据规范化Min-max、Z-Score和小数定标**
刚才提到了,进行数据规范化有两个作用:一是让数据之间具有可比较性,二是加快后续算法的迭代收敛速度。
实际上你能看到Min-max、Z-Score和小数定标规范化都是一种线性映射的关系将原来的数值投射到新的空间中。这样变换的好处就是可以看到在特定空间内的数值分布情况比如通过Min-max可以看到数据在[0,1]之间的分布情况Z-Score可以看到数值的正态分布情况等。
不论是采用哪种数据规范化方法,规范化后的数值都会在同一个数量的级别上,这样方便后续进行运算。
那么回过头来看在数据挖掘算法中是否都需要进行数据规范化呢一般情况下是需要的尤其是针对距离相关的运算比如在K-Means、KNN以及聚类算法中我们需要有对距离的定义所以在做这些算法前需要对数据进行规范化。
另外还有一些算法用到了梯度下降作为优化器这是为了提高迭代收敛的效率也就是提升找到目标函数最优解的效率。我们也需要进行数据规范化比如逻辑回归、SVM和神经网络算法。
在这些算法中都有目标函数,需要对目标函数进行求解。梯度下降的目标是寻找到目标函数的最优解,而梯度的方法则指明了最优解的方向,如下图所示。
<img src="https://static001.geekbang.org/resource/image/55/a0/55fb82ec9ecac8516419edfcc5ecd1a0.jpg" alt="">
当然不是所有的算法都需要进行数据规范化。在构造决策树的时候,可以不用提前做数据规范化,因为我们不需要关心特征值的大小维度,也没有使用到梯度下降来做优化,所以数据规范化对决策树的构造结果和构造效率影响不大。除此之外,还是建议你在做数据挖掘算法前进行数据规范化。
**答疑3如何使用Z-Score规范化将分数变成正态分布**
我在专栏文稿中举了一个Z-Score分数规范化的例子假设A与B的考试成绩都为80分A的考卷满分是100分及格60分B的考卷满分是500分及格300分。这里假设A和B的考试成绩都是成正态分布可以直接采用Z-Score的线性化规范化方法。
在专栏的讨论区中有个同学提出了“Z-Score”的非线性计算方式大家可以一起了解下
<li>
先按公式计算出百分等级。百分等级(年级)=100-(100x年级名次-50)/有效参加考试人数。这里百分等级是每个学生在该批学生中的相对位置,其中百分等级是按照正态分布图的所占面积比例求得的;
</li>
<li>
按照百分等级数去标准正态分布表中查询得出Z-Score值这样最终得出的Z分便是标准的正态分布能够将偏态转化成标准正态。
</li>
因为在很多情况下数值如果不是正态分布而是偏态分布直接使用Z-Score的线性计算方式无法将分数转化成正态分布。采用以上的方法可以解决这一个问题大家可以了解下。这里偏态分布指的是非对称分布的偏斜状态包括了负偏态也就是左偏态分布以及正偏态也就是右偏态分布。
我发现大家对工具的使用和场景比较感兴趣,所以最后留两道思考题。
第一道题假设矩阵a = np.array([[4,3,2],[2,4,1]]),请你编写代码将矩阵中的每一列按照从小到大的方式进行排序。
第二道题你都用过哪些Python爬虫工具抓取过哪些数据觉得哪个工具好用
欢迎你在评论分享你的想法,也欢迎你点击“请朋友读”,把它分享给你的朋友或者同事。