前言
最近拿到了一些Msc in Data Science的offer,想着往Data Scientist方向发展,为了适应全英文授课,故在coursera上看点网课,顺便在这里做点笔记,主要为了供日后自己复习和查阅,记录一点学习的思考,如有问题,欢迎指出。
以下是本篇文章正文内容
一、课程大纲
- week1:Python前置知识
- week2:pandas工具箱
- week3:用pandas进行查询与操作
- week4:用numpy和scipy库对项目进行基本统计分析
二、本周笔记
1.Function
合理利用default可以使得函数更加灵活
def add_numbers(x,y,z=None):
2.python types
python的数据类型主要包含boolean, str, int, float, NoneType还有tuple, list, dict,set
- tuple:可以有多种数据结构,是有序的,不可单独更改内容,不可单独新增内容
- list:可以有多种数据结构,是有序的,可以随时增删和修改
- dict:用key-value的方式存储,key必须是不可变对象,对应的value数据类型可以不一样(在本周学习中利用csv.DictReader()模块时,遇到了OrderedDict,而回根据放入元素的先后顺序进行排序,所以输出的值是排好序的)
- set:无序集合,key不重复,与dict类似,但不储存值,且key不重复,方便查看所有的类型
for key in x:
for value in x.values:
3.unpacking 解包
如果我们有一个序列(sequence)或者list, tuple, dict我们都可以用unpacking的方法快速赋值给我们想要的变量,例如:
x=('Christopher','Brooks','brooksch@umich.edu')
fname,lname,email=x
print('fname:{},lname:{},email:{}'.format(fname,lname,email))
--output:
fname:Christopher,lname:Brooks,email:brooksch@umich.edu
4.csv Module:指导课笔记
- 全局变量:设定小数位数
import csv
%precision 2
- csv.DictReader()与Slicing切片
可以利用DictReader()工具将数据按行创建字典,并可以用list将他们组合起来,得到列表mpg,接下来的操作都将利用mpg上进行,代码如下:
import csv
%precision 2
with open ('mpg.csv') as csvfile:
mpg=list(csv.DictReader(csvfile))
mpg[0:1]
--Output:
[OrderedDict([('', '1'),
('manufacturer', 'audi'),
('model', 'a4'),
('displ', '1.8'),
('year', '1999'),
('cyl', '4'),
('trans', 'auto(l5)'),
('drv', 'f'),
('cty', '18'),
('hwy', '29'),
('fl', 'p'),
('class', 'compact')])]
此处所产生的list是OrderedDict,使用方法与dict类似
- 查看字典的所有key,并计算城市(cty)和高速(hwy)的平均每加仑燃料行驶英里数
mpg[0].keys()
--Output:
odict_keys(['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class'])
sum(float(d['cty']) for d in mpg)/len(mpg)
summpg=0
for d in mpg:
summpg+=float(d['cty'])
summpg/len(mpg)
--Output:
16.86
(注:这里运用到了List comprehension列表推导式的方法,LC表达式本质是带有if statement的压缩的迭代取数列表,只要理解压缩的过程,就可以理解LC表达式,这些都会在稍后有简单的介绍笔记)
- 查看cylinder数目种类,并根据cylinder分类计算cty平均值
首先利用set得到种类
cylinders=set(d['cyl'] for d in mpg)
cylinders
--Output:
{'4', '5', '6', '8'}
首先考虑用list来展示答案,对于各种cylinder对应的平均mpg,考虑用tuple或者dict来展示,方便起见,利用tuple,这样我们就要先创建一个CtyMpgByCyl的空list
接下来是代码的思路
对cylinder进行迭代: ? 设置两个统计量: ?1、当前cylinder的数量记为cyltypecount ?2、当前cylinder的mpg总里程数,记作summpg ?再对列表mpg进行迭代, ??如果迭代的值等于当前的cylinder值, ???对应的cyltypecount++, ???对应的summpg加上列表mpg中当前字典下的‘cty’中的值(mpg是一个列表,列表中的每一个元素都是字典格式)(注意:此时我们需要转换数据类型,因为读取数据时默认用str格式,而此处要进行数学运算!) ?计算平均值并以tuple的格式添加到CtyMpgByCyl的列表中 排序 代码如下:
CtyMpgByCyl=[]
for c in cylinders:
cyltypecount=0
summpg=0
for d in mpg:
if d['cyl']==c:
summpg+=float(d['cty'])
cyltypecount+=1
CtyMpgByCyl.append((c,summpg/cyltypecount))
CtyMpgByCyl.sort(key=lambda x:x[0])
CtyMpgByCyl
--Output:
[('4', 21.01), ('5', 20.50), ('6', 16.22), ('8', 12.57)]
(注:这里用到了lambda函数,lambda函数又称匿名函数,故名思义是对函数格式的变形与缩简,仍旧与函数具有相似的构建逻辑,本次笔记后段会简单介绍此函数格式,在此处,简单来说,list是一个有序的数据格式,在list.sort中有一个参数是key即对何值作为主键进行排序,lambda x: x[0]表示是list中的每一个元素的第一个值进行排序,此处list中的每一个元素是tuple,例如(‘4’, 21.01),即对’4’,'5’等值进行排序,便有了输出值,下文中key=lambda x:x[1]也是相同的原理,对tuple的第二个元素排序)
- 看class分类,并根据class分类计算hwy平均值
本质上与4.是一样的,可以通过查看自己写一遍代码来对比,查漏补缺,代码如下:
classes = set(d['class']for d in mpg)
classes
--Output:
{'2seater', 'compact', 'midsize', 'minivan', 'pickup', 'subcompact', 'suv'}
HwyMpgByclass=[]
for c in classes:
clstypecount=0
summpg=0
for d in mpg:
if d['class']==c:
summpg+=float(d['hwy'])
clstypecount+=1
HwyMpgByclass.append((c,summpg/clstypecount))
HwyMpgByclass.sort(key=lambda x:x[1])
HwyMpgByclass
--Output:
[('pickup', 16.88),
('suv', 18.13),
('minivan', 22.36),
('2seater', 24.80),
('midsize', 27.29),
('subcompact', 28.14),
('compact', 28.30)]
5.time & datetime Module 时间模块
python中的time模块和datetime模块可以得到当前时间、时间间隔、和计算相应间隔下的时间。 首先介绍time模块下的时间,python的最早初始的时间是1970年1月1日0点0分0秒,用time.gmtime(0)即可查到,而现在的时间可以用time.time()查到,注意,查到的结果是秒,意思是离初始时间过了多少秒,为了得到日期,可以用datetime模块中datetime.fromtimestamp(tm.time())来得到对应的数据,并可以得到年、月、日等数据代码如下:
import time as tm
import datetime as dt
tm.gmtime(0)
--Output:
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
tm.time()
dtnow=dt.datetime.fromtimestamp(tm.time())
dtnow.year
dtnow.month
dtnow.day
print(dtnow,dtnow.year,dtnow.month,dtnow.day)
--Output:
2021-12-10 22:10:36.146800 2021 12 10
另一种获得当天日期的办法是datetime.date.today(),同时datetime模块还可以得到时间间隔timedelta,通过加减时间间隔,我们可以得到对应的目标时间,代码如下:
today=dt.date.today()
delta=dt.timedelta(100)
target_time=today-delta
print('今天是:{}时间间隔:{}对应的间隔日期前是:{}'.format(today,delta,target_time))
--Output:
今天是:2021-12-10时间间隔:100 days, 0:00:00对应的间隔日期前是:2021-09-01
6.camel case in class
Python中的面相对象编程时的class名称要用驼峰命名法,即每个单词第一个字母大写,其他小写
7.lambda 匿名函数与map函数
- 在Python中,不通过def来声明函数名字,而是通过lambda关键字来定义的函数称为匿名函数或者lambda函数。
lambda函数能接收任何数量(可以是0个)的参数,但只能返回一个表达式的值,lambda函数是一个函数对象,直接赋值给一个变量,这个变量就成了一个函数对象。
一般函数与lambda函数:
def add(a,b,c):
return a+b+c
add = lambda a,b,c:a+b+c
在实际应用中可以采用**(lambda 参数:表达式)(参数)**的方式来更简化形式 来看以下例子:
people=['Dr. Bob Martin','Dr. Linda James','Dr. Joe Kings']
for person in people:
print((lambda x:x.split()[0]+' '+x.split()[-1])(person))
--Output:
Dr. Martin
Dr. James
Dr. Kings
在这里,我们将people中的每一个元素person按空格进行分割lambda函数的作用是将第一个和第三个值用空格连接起来,并直接对person进行利用,才得到了最终结果
其实我们也可以利用map函数和lambda函数结合的方法进一步缩减语句
先介绍下map函数:
- map() 会根据提供的函数对指定序列做映射。
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
注意:map函数是一个lazy evaluation,他返回的是一个map object,在你试图查看他的内部之前,他并不会运行,所以我们需要根据自己的需求,查看其内部的值,此处,我们用list的方法查看其内部结构,代码如下:
list(map(lambda x:x.split()[0]+' '+x.split()[-1],people))
--Output:
['Dr. Martin', 'Dr. James', 'Dr. Kings']
可以看到,得到的结果是和上面一样的,这是对people对所有的元素进行了lambda函数的操作,简化了迭代的书写时间和空间成本!
8.List Comprehension 列表推导式
LC表达式本质上是将迭代的语句进行压缩和重组(condensed form),其遵循的思路如下:
out_list=[out_express for out_express in input_list if out_express_condition]
我们来对一一下普通的迭代语句和LC表达式,就可以明显的发现其压缩的原理
for out_express in input_list:
if out_express_condition:
output_expression
简化之后大致可以分成三层
- Iteration (eg.for out_express in input_list)
- If statement (eg.if out_express_condition)
- execution (eg.output_expression)
那么在LC表达式中也是三层: [execution Iteration If statement] 用空格分割,只要搞明白这点,就可以轻松理解LC表达式
9.Numpy module
- np.array
可以通过np.array()的方法来获得矩阵,注意,在做二维矩阵的时候要记得加上一个square bracket[],这是一个容易犯的错误。
np.array([[1,2],[2,3]])
--Output:
[[1 2]
[2 3]]
- np.arange
可以用np.arange(start,end,skip)来获得一个sequence,start是序列起点(inclusive,包含)end是序列终点(exclusive,不包含)skip是间隔距离
print(np.arange(1,10,2))
--Output:
[1 3 5 7 9]
- np.linspace
首先注意是np.linspace不是np.linespace,可以用np.linspace(start,end,number)来获得一个序列,这个序列是float类型的,与arange不同的是它的三个参数,start是序列起点(inclusive,包含)end是序列终点(exclusive,包含),number是序列的个数
print(np.linspace(1,10,5))
--Output:
[ 1. 3.25 5.5 7.75 10. ]
- Element product or Matrix product
对于得到的矩阵,用Asterix(*)来进行矩阵元素与矩阵元素的相乘,用@或者np.dot(a,b)来进行矩阵与矩阵的代数相乘。
a=np.array([[1,2],[2,3]])
b=np.array([[1,2],[2,3]])
print('do element product:\n',a*b)
print('do matrix product:\n',a@b,'\n or\n',np.dot(a,b))
--Output:
do element product:
[[1 4]
[4 9]]
do matrix product:
[[ 5 8]
[ 8 13]]
or
[[ 5 8]
[ 8 13]]
- np的基本函数
包含sum(), mean(), min(), max() 用法是一目了然的
print(a.sum(),a.mean(),a.min(),a.max())
--Output:
8 2.0 1 3
10.PIL Module
Python Imaging Library 简称PIL,常用于python的图像计算与操作,在这里我们用到模块中的Image和IPython中的display来进行操作。
(注:如果python3.x的环境中没有PIL模块是正常的,因为PIL模块在 python2.7之后就没有更新了,现在的python3.x中用的PIL实际上是Pillow模块,Pillow是在PIL基础上建立的,且环境中PIL和Pillow不能兼容,只要有了Pillow就可以运行PIL的代码了,且Pillow的语法仍是PIL)
以princess Zelda为例,首先用Image.open()打开我们要的图片
from PIL import Image
from IPython.display import display
im=Image.open('Zelda.jpeg')
display(im)
彩色的图片涉及到RGB色彩理论,在这里我们先不考虑彩色图像,先转化成黑白图像,用im.conver(),
- conver(‘1’)是转化成二值图像,非黑即白,在计算机中多用uint8(uint8解释见下文)来储存,即0是黑,255是白,转化后的图像噪点多
我们来看下转换后的效果:
im=im.convert('1')
display(im)
- conver(‘L’)是转化成灰色图像,也是储存值也是uint8,0表示黑,255表示白,以下是转化公示:
L
=
R
?
299
/
1000
+
G
?
587
/
1000
+
B
?
114
/
1000
L = R * 299/1000 + G * 587/1000+ B * 114/1000
L=R?299/1000+G?587/1000+B?114/1000
我们来看一下转化的效果:
im=im.convert('L')
display(im)
接下来我们用numpy将这里的im转化成矩阵,看看转化后的结果是怎么样的
array=np.array(im)
array
--Output:
array([[215, 214, 213, ..., 216, 210, 210],
[215, 214, 214, ..., 215, 215, 215],
[215, 215, 215, ..., 215, 216, 216],
...,
[217, 217, 216, ..., 213, 214, 214],
[215, 215, 215, ..., 215, 215, 215],
[215, 215, 215, ..., 216, 216, 216]], dtype=uint8)
这里解释一下什么是uint8,uint意思是unsigned integers,8意味着8bits per type,意味着每一个值的取值范围在0-2^8-1即0-255之间取值,如果我们用阈值255减去当前的数字,理论上我们就可以得到黑白颠倒的图像,得到的图像就像我们看到的老式胶片那样。
首先我们先设置一个阈值矩阵mask,并计算im矩阵与阈值矩阵的差值矩阵再用Image.fromarray得到图像:
mask=np.full(array.shape,255)
modified_array=mask-array
modified_array=modified_array.astype(np.uint8())
modified_im=Image.fromarray(modified_array)
display(modified_im)
是不是很像胶底
如果将im矩阵reshape一下,将宽度加倍,高度减半,会发生什么呢?
display(Image.fromarray(modified_array.reshape(237,-1)))
。。。彳亍,今天就到这里吧
三、下节预告
下节的内容主要是正则表达式,用到re模块
|