此文是《10周入门资料分析》系列的第13篇
想了解学习路线,可以先阅读 学习计画 | 10周入门资料分析
前面经过十几篇文章,相想必大家对于资料分析是什么,怎么做有了基本的认识。跟着操作的小伙伴基本功应该练的差不多了,可以蛟龙出海了。
有些基础后,理论上的东西我们先放一放,现在开始我们就学习一下很热门,很烫手的python》》入门版六小节,好了,跟着小编学起来吧!
作为当下最热门的程式设计语言之一,Python有两个非常有趣的方向:一个是资料分析,从掌握资料分析的基本方法开始,学习NumPy、Pandas、mapplotlib包;然后再往下就是资料採撷,机器学习、深度学习,甚至人工智慧。另外一个方向则是web开发。有同学说爬虫呢,爬虫其实是获取资料的一个手段,包括资料库的处理等等都是包含在上面两条路线里面。
想学会一门语言不是一朝一夕的事情,本文是按照业务资料分析师/商业分析师的路线来讲Python的学习路径。若大家想成为技术型的分析师,或者未来往资料採撷发展,建议你要比文章内容学得更深,所有的程式码最好都手打一遍,这是最有效的学习方式。
好了,言归正传。按照所有程式设计语言的学习套路,先从基础语法开始,有程式设计基础的同好可能学习起来比较轻鬆,但也建议看一遍,温习一二。
资料分析环境
Python的编写环境,用Anaconda足矣。Anaconda是专业的资料科学计算环境,已经集成绝大部分包和工具,不需要多余的安装和调试。
Python版本建议3.0以上,不要选择2.7的版本,否则你会被无尽的中文编码问题困扰。
Anaconda在官网下载,选择最新版本,约400MB。
完成安装后,Win版本会多出几个程式,Mac版本只有一个Navigator导航。资料分析最常用的程式叫Jupyter,以前被称为IPython Notebook,是一个互动式的笔记本,能快速创建程式,支援即时程式码、视觉化和Markdown语言。
点击Jupyter进入,它会自动创建一个本地环境localhost。
点击介面右上角的new,创建一个python档。
开始你的Python
介面上部是工具列,编辑撤回运行等,下面是快捷操作,大家以后会熟悉的。页面正中便是脚本执行的地方,我们输入自己第一行程式码吧:
(我就不用hello world)灰色框是输入程式的地方,回车是换行,shift+回车执行灰色区域的程式码,它的结果会直接在下面空白处出现。这就是Jupyter互动式的强大地方,将Python脚本分成片段式运行,尤其适合资料分析的摸索调整工作。
这里的print叫函数,和excel的函数同理,是程式执行的主体,负责将输入转化成输出(函数留在下一篇细讲)。这里将hello qinlu这段文字输出。新手可能会奇怪为什么要加引号,这种用引号括起来的文字在程式中叫字串。
Python是一门电脑语言,它的逻辑和自然语言不一样,程式设计语言的目的是执行任务,所以它不能有歧义。为了规避各种歧义,人们创造了语法规则,只有正确的语法,才能被转换成CPU执行的机器码。
先了解Python语法中的资料类型。电脑最开始只被用于数值运算,后来被赋予了各种丰富的资料类型。
上面两个是小学生都会的四则运算,在电脑语言中可没有那么简单。它涉及了两个数值类型,整数int和浮点数float。整数和浮点数在电脑内部存储的方式是不同的,我们不用知道具体原理,明确一点,整数运算是永远精确的,浮点运算则可能有误差。
两种资料类型也可以互换,透过int函数和float函数。
有了数值,必然有文本,程式中叫字串,用英文引号括起来表示。单引号和双引号没有区别,所以”qinlu”和’qinlu’是等价的,引号是边界,输出的时候不会包含它。当字串内本身包含引号时,也不影响使用。
需要注意的是,不论单引号还是双引号,一旦混用很容易出现错误。因为程式并不知道它是字串的边界还是符号。
解决方法有两种,一种是使用三引号,三引号代表整体引用,而且包含换行。第二种是引号前面加\,它是转义字元,表示这个引号就是单纯的字元。
三引号也可以用来注释,通常是大段的文字解释,如果一句话,我们更习惯用#,#后面的内容均不会作为程式执行。
时间是特殊的数数值型别,它将结合datetime模组讲解。
还有两个常见的资料类型,布林值和空值。布林值是逻辑判断值,只有True和False。
布林值在IF语句和资料清洗中经常使用,利用其过滤。布林值能和布林值运算,不过这里是and、not、or作为运算子,Ttue and True = True,False and True = False,False and False = False,not True = False,True or False = True等。
空值是一个特殊的值,表示为None,None不等于0,0具有数学意义而None没有,None更多表示该值缺失。
整数,浮点数,字串,布林值,空值就是Python常见的资料类型。Python3对中文的支持比较友好,所以大家可以用中文作为字串试一下print。
资料类型构成了变数的基础,变数可以是任意的资料类型。想要用变数,必须先赋予变数一个值,这个过程叫赋值。
我首先给a赋予了一个整数值1,然后改变它为字串abc,变数在Python中没有固定的数数值型别,这是Python最大的优点,所以它在资料分析中很灵活。这也是它被称为动态语言的原因,相对应的叫静态语言。
Python是大小写敏感的语言,所以a和A是有区别的,这点请牢记。另外变数名尽可能使用英文,不要拼音,英文的可读性是优于拼音的。
变数有两种拼写风格,一种叫驼峰,一种叫底线,以用户ID为例。驼峰命名法为userId,以一串英文词语user和id组成变数,第一个词语的首字母小写,第二个词语开始的首字母均大写。底线命名法为user_id,全部小写,用_分割单词。
一个变数的值可以被赋予另外一个变数,如果b变数之前有另外一个值,那么会被1覆盖。呈从上而下的执行关係。
初看a = a + 1好像有逻辑问题,其实这涉及到了程式执行的先后顺序,程式是先计算a+1的值得到2,然后将其赋予(覆盖)了a。等号右边的计算先于左边,这是从右到左的逻辑关係。
有变数,自然有常量,常量是固定不变的量,可是在Python中没有真正意义的常量,一切皆可变,它更多是习惯上的叫法,即一旦赋值,就不再改变了。
Python的基础数学运算子号有+,-,*,/,//,%。前面四个就是加减乘除,其中除法的结果一定是浮点数。后面两个符号是除法的特殊形式,//代表除法中取整数,%代表除法中取余数。
到这里,新手部分已经讲解完成。再来讲讲资料结构。
资料结构
Python一共有三大资料结构,它是Python进行资料分析的基础,分别是tuple元组,list阵列以及dict字典。本文透过这三者的学习,打下资料分析的基础。
阵列
阵列是一个有序的集合,他用方括号表示。
num就是一个典型的阵列。阵列不限定其中的资料类型,可以是整数也可以是字串,或者是混合型。
阵列可以直接用特定的函数,函数名和Excel相近。
sum是求和,len则是统计阵列中的元素个数。
上述列举的函数是阵列内整体元素的应用,如果我只想针对单一的元素呢?比如查找,这里就要用到阵列的特性,索引。索引和SQL中的索引差不多,都是用来指示资料所在位置的逻辑指标。阵列的索引便是元素所在的序列位置。
注意,索引位置是从0开始算起,这是程式设计语言的预设特色了。num[0]指数组的第一个元素,num[1]指数组的第二个元素。
我们用len()计算出了阵列元素个数是5,那么它最后一个元素的索引是4。若是阵列内的元素特别多呢?此时查找阵列最后一位元的元素会有点麻烦。Python有一个简易的方法,可以用负数表示,意为从最后一个数位计算索引。
这里的num[4]等价于num[-1],num[-2]则指倒数第二个的元素。
再来一个新问题,如何一次性选择多个元素?例如筛选出阵列前三个元素。在Python中,用:表示範围。
num[0:3]筛选了前三个元素,方括号左边是闭区间,右边是开区间,所以这里是num[0],num[1]和num[2],并不包含num[3]。这个方法叫做切片。
上述是索引的特殊用法,[0:]表示从第0个索引开始,直到最后一个元素。[:3]表示从第一个元素开始,直到第3个索引。
负数当然也有特殊用法。[-1:]表示从最后一个元素开始,因为它已经是最后一个元素了,所以只返回它本身。[:-1]表示从第一个元素开始到最后一个元素。num[-2:-1]和num[-3:-1]大同小异。
阵列的增删查
我们已经了解阵列的基本概念,不过仍旧停留在查找,它不涉及资料的变化。工作中,更多需要操纵阵列,对阵列的元素进行添加,删除,更改。
阵列透过insert函数插入,函数的第一个参数表示插入的索引位置,第二个表示插入的值。
另外一种方式是append,直接在阵列末尾添加上元素。它在之后讲到反覆运算和迴圈时应用较多。
如果要删除特定位置的元素,用pop函数。如果函数没有选择数值,预设删除最后一个元素,如果有,则删除数值对应索引的元素。
更改元素不需要用到函数,直接选取元素重新赋值即可。
到这里,阵列增删改查已经讲完,但这只是一维阵列,一维阵列之上还有多维阵列。如果现在有一份资料是关于学生资讯,一共有三个学生,要求包含学生的姓名,年龄,和性别,应该怎么用阵列表示呢?
有两种思路,一种是用三个一维阵列分别表示学生的姓名,年龄和性别。
学生属性被拆分成多个阵列,利用索引来表示其资讯,这里的索引有些类似SQL的主键,透过索引查找到资讯。但是这种方法并不直观,实际应用会比较麻烦,更好的方法是表示成多维阵列。
所谓多维阵列,是阵
列内再嵌套数组,图中表示的是一个宽度为3,高度为3的二维阵列。此时student[0]返回的是阵列而不是单一值。这种方法将学生资讯合併在一起,比第一个案例更容易使用。
如果想选择第一个学生的性别,应该怎么办呢?很简单,后面再加一个索引即可。
现在尝试快速创建一个多维阵列。
[0]*3将快速生成3个元素值为0的阵列,这是一种快捷操作,而[row]4则将其扩展成二维资料,因为是4,所以是34的结构。
这里有一个注意点,当我们想更改多维阵列中的某一个元素而不是阵列时,这种方式会错误。
按照正常的想法,martix[1][0]将会改变第二个阵列中的第一个值为1,但是结果是所有阵列的第一个值都变成1。这是因为在matrix = [row] * 4操作中,只是创建3个指向row的引用,可以简单理解成四个阵列是一体的。一旦其中一个改变,所有的都会变。
比较稳妥的方式是直接定义多维阵列,或者用迴圈间接定义。多维阵列是一个挺重要的概念,它也能直接表示成矩阵,是后续很多演算法和分析的基础(不过在pandas中,它是另外一种形式了)。
元组
tuple叫做元组,它和阵列非常相似,不过用圆括号表示。但是它最大的特点是不能修改。
当我们想要修改时就会报错。
而选择和阵列没有差异。
元组可以作为简化版的阵列,因为它不可更改的特性,很多时候可以作为常量使用,防止被篡改。这样会更安全。
字典
字典dict全称dictionary,以键值对key-value的形式存储。所谓键值,就是将key作为索引存储。用大括弧表示。
图中的’qinlu’是key,18是value值。key是唯一的,value可以对应各种资料类型。key-value的原理不妨想像成查找字典,拼音是key,对应的文字是value(当然字典的拼音不唯一)。
字典和阵列的差异在于,因为字典以key的形式存储和查找,所以它的查询速度非常快,毕竟翻字典的时候你只要知道拼音就能快速定位了。对dict资料结构,10个key和10万个key在查找对应的value时速度没有太大差别。
这种查找方式的缺点是佔用记忆体大。阵列则相反,查找速度随着元素的增加逐渐下降,这个过程想像成程式在一页页的翻一本没有拼音的字典,直到找到内容。阵列的优点是佔用的记忆体空间小。
所以阵列和字典的优缺点相反,dict是空间换时间,list是时间换空间,这是程式设计中一个比较重要的概念。实际中,资料分析师的工作不太涉及工程化,选用阵列或者字典没有太严苛的限制。
细心的读者可能已经发现,字典定义时我的输入顺序是qinlu,lulu,qinqin,而列印出来是lulu,qinlu,qinqin,顺序变了。这是因为定义时key的顺序和放在记忆体的key顺序没有关係,key-value透过hash演算法互相确定,甚至不同Python版本的杂凑演算法也不同。这一点应用中要避免出错。
既然字典透过key-value对匹配查找,那么它自然不能不用阵列的数值索引,它只能透过key值。
如果key不存在,会报错。透过in方法,可以返回True或False,避免报错。
dict和list一样,直接透过赋值更改value。
能不能更改key的名字?不能,key一旦确定,就无法再修改,好比字典定好后,你能修改字的拼音么?
dict中删除key和list一样,透过pop函数。增加key则是直接赋予一个新的键值对。
dict的keys和values两个函数直接输出所有的key值和value值。如果要转换成阵列,则再外面嵌套一个list函数。
items函数,将key-value对变成tuple形式,以阵列的方式输出
字典可以透过嵌套应用更複杂的资料格式,和NoSQL与JSON差不多。
基础的资料类型差不多了,更多函数应用大家可以网上自行查阅文档,这块掌握了,在资料清洗过程中将会非常高效,尤其是读取Excel资料时。当然不要求滚瓜烂熟,因为后面将学习更加强大的Numpy和Pandas。
我是「数据分析那些事」。常年分享资料分析乾货,不定期分享好用的职场技能工具。