文章目录
- 1、类型
- 1、set
- 2、arange和range
- 3、Python 三种取随机数方法
- 2、numpy
- 2、union
- 3、axis=0 与 axis=1
- 3、数组广播机制
- 3、reduce
- 4、ascending=False 与 reverse=False
- 5、set_index和reset_index
- 6、json自定义函数提取数据
- 7、apply 与lambda
- 8、join
- 9、copy
- 9、len
- 9、append
- 10、merge
- 11、combine_first
- 12、concatenate
- 13、concat
- 14、groupby
- 15、values()与itervalues()
- 16、value_counts
- 17、sort 与sort_values
- 18、open
- 19、read_cav与to_csv
- 20、remove
- 21、series
- 22、DF的表头columns和index
- 23、字典
- 25、切片
- 25、loc和iloc
- 26、DataFrame
- 27、shape与reshape
- 28、替换函数strip(),replace(),sub()
- 30、unique
- 31、isnull,notnull
- 30、drop
- 31、 dropna()
- 31、fillna()
- 32、rename
- 33、linspace
- 34、日期时间
- 35、lambda 匿名函数
- 35、构造数组的几种方式
- 36、正则表达式
- 29、column_stack与hstack、vstack
- 30、contains
- 31、split
- 31、strip
- 33、期末考会考题
- 34、Sklearn的train_test_split用法
- 34、过拟合与欠拟合
- 35、oversample 过采样和欠采样undersampling
- 36、分类阈值
- 37、超参数
- 38、随机森林
- 39、 cut和qcut的用法(分桶分箱)
- 40、随机森林 n_estimators参数 max_features参数
- 41、VarianceThreshold
- 42、fit_transform,fit,transform区别和作用
- 43、特征预处理的独热编码
- 44、ravel和flattern
- 45、train_test_split
- 46、crosstab和pivotTab
- 47、使用函数处理DF当中的数据
- 48、全局变量、局部变量、类变量、实例变量
- 49、transpose()与.T()
- 50、并发与并行的区别
- 51、Python迭代器与生成器
- 52、yield关键字
- 53、正则表达式当中的贪婪匹配和非贪婪匹配的区别
- 54、类和面向对象的区别
- 55、Python当中的异常
- 56、Python的class
- 57、if __name__ == '__main__'
1、类型
数据类型
python3数据类型主要分为以下六大类:
- Numbers(数字)
- String(字符串)
- List(列表)
- Tuple(元组)
- Dictionary(字典)
- Set(集合)
Python3 的六个标准数据类型中:
- 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);
- 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。
数值类型
python 数值基本类型:
- int : 整数类型
- float : 浮点类型
- bool : 布尔类型(True False)
【1】 整数和浮点数由存在或不存在小数点区别:5是整数,而5.0是浮点数。复数以形式书写x + yj,其中x是实部,y是虚部。
【2】整数可以是任意长度,但浮点数最多只能精确到15个小数位(第16位不准确)。
值类型与引用类型
- 值类型
在Python中,数值(整型,浮点型),布尔型,字符串,元组属于值类型,本身不允许被修改(不可变类型),数值的修改实际上是让变量指向了一个新的对象(新创建的对象),所以不会发生共享内存问题。
修改值类型的值,只是让它指向一个新的内存地址,并不会改变变量b的值。
>>> x = 1
>>> id(x)
31106520
>>> y = 1
>>> id(y)
31106520
>>> x = 2
>>> id(x)
31106508
>>> y = 2
>>> id(y)
31106508
>>> z = y
>>> id(z)
31106508
>>> x += 2
>>> id(x)
31106484
为什么称之为不可变数据类型呢?这里的不可变可以理解为x引用的地址处的值是不能被改变的,也就是31106520地址处的值在没被垃圾回收之前一直都是1,不能改变,如果要把x赋值为2,那么只能将x引用的地址从31106520变为31106508,相当于x = 2这个赋值又创建了一个对象,即2这个对象,然后x、y、z都引用了这个对象,所以int这个数据类型是不可变的,如果想对int类型的变量再次赋值,在内存中相当于又创建了一个新的对象,而不再是之前的对象。
- 引用类型
在Python中,列表,集合,字典是引用类型,本身允许修改(可变类型)
list_a = [1,2]
list_b = list_a
list_a[0] = 3
print(list_b) #此时的输出结果是[3,2]
修改引用类型的值,因为list_b的地址和list_a的一致,所以也会被修改
可变与不可变对象类型
可修改(mutable)的类型叫做引用类型,不可修改(immutable)类型叫做值类型
不可变(immutable)对象类型
- int
- float
- decimal
- complex
- bool
- str
- tuple
- range
- frozenset
- bytes
可变(mutable)对象类型
- list
- dict
- set
- bytearray
- user-defined classes (unless specifically made immutable)
1、set
set 是一个不允许内容重复的组合,而且set里的内容位置是随意的,所以不能用索引列出。可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
2、arange和range
【1】range(start, end, step)
返回一个list对象也就是range.object,起始值为start,终止值为end,但不含终止值,步长为step。只能创建int型list。
range()函数的三种使用方法:
# range()函数的三种使用方法
# 1.仅设置终点参数,默认起点为0,步长为1,返回值范围为[起点,终点)
>>>range(10)
0,1,2,3,4,5,6,7,8,9
# 2.设置起点和终点,步长默认为1,返回值范围为[起点,终点)
>>>range(2,10)
2,3,4,5,6,7,8,9
# 3.设置起点、终点和步长
>>>range(1,10,2)
1,3,5,7,9
# 当设置起点、终点或步长为小数时,将会报错
>>>range(1,10,2.1)
TypeError: 'float' object cannot be interpreted as an integer
【2】arange(start, end, step)
与range()类似,也不含终止值。但是返回一个array对象。需要导入numpy模块(import numpy as np或者from numpy import*),并且arange可以使用float型数据。
np.arange()函数的整数型参数设置:
# np.arange()函数的整数型参数设置
# 1.仅设置终点参数,默认起点为0,步长为1,返回值范围为[起点,终点)
>>>np.arange(10)
0,1,2,3,4,5,6,7,8,9
# 2.设置起点和终点,步长默认为1,返回值范围为[起点,终点)
>>>np.arange(2,10)
2,3,4,5,6,7,8,9
# 3.设置起点、终点和步长
>>>np.arange(1,10,2)
1,3,5,7,9
np.arange()函数的小数型参数设置:
# np.arange()函数的整数型参数设置
# 1.终点为小数,默认起点为0.0,步长为1.0
>>>np.arange(10.2)
0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0
# 2.设置起点和终点均为小数,步长默认为1.0,返回值范围为[起点,终点)
>>>np.arange(2.1, 5.1)
2.1,3.1,4.1
# 3.设置起点、终点和步长均为小数
>>>np.arange(1.1, 5.2, 1.1)
1.1,2.2,3.3,4.4
range函数和arange函数的区别:
【1】range是Python内置的函数,直接调用即可;arange是numpy中的函数,调用时一般采用np.arange()。
【2】range()函数仅支持整数步长,np.arange()函数支持小数步长。
【3】两者数据类型不同:range()函数返回的类型为range对象,np.arange()函数返回的类型为array类型对象。
3、Python 三种取随机数方法
三种方法
- random.sample()
- random.choice()
- random.randint()
random.sample
语法:
random.sample(list, N)
【1】list: 一个数组,可以是元素数组,也可以是其他的数组。比如: numbers=[1,2,3,4,5]
【2】N: 从数组中随机取出N个
random.choice
语法:
random.choice(list)
从list 数组中随机获取一个元素
random.randint
语法:
random.randint(N, M)
N: 起始数
M: 终止数
从N到M随机取出一个数
2、numpy
np.eye
numpy.eye(N, M=None, k=0, dtype=<class ‘float’>, order=‘C’)
功能:
返回一个二维数组,其对角线元素为1,其余位置元素为0。
np.zeros
zeros(shape, dtype=float, order=‘C’)
返回:返回来一个给定形状和类型的用0填充的数组;
np.ones
ones函数用于创建指定长度或形状的全1数组(这里的数组指ndarray数组)。
>>> import numpy as np
>>> np.ones(3)
array([1., 1., 1.])
>>> np.ones((3,3))
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
>>> np.ones((3,1))
array([[1.],
[1.],
[1.]])
>>> np.ones((3,1),dtype=[('x', 'int'), ('y', 'float')]) #可分别指定x和y的数据类型,结果返回的数据类型为numpy的数据类型
array([[(1, 1.)],
[(1, 1.)],
[(1, 1.)]], dtype=[('x', '<i4'), ('y', '<f8')])
np.repeat
np.repeat用于将numpy数组重复
一维数组重复三次
import numpy as np
# 随机生成[0,5)之间的数,形状为(1,4),将此数组重复3次
pop = np.random.randint(0, 5, size=(1, 4)).repeat(3, axis=0)
print("pop\n",pop)
# pop
# [[0 0 3 1]
# [0 0 3 1]
# [0 0 3 1]]
np.empty
numpy.empty(shape, dtype=float, order=‘C’, *, like=None),用来输出一个空数组
like:默认为numpy数组,可以根据你的需要更改数组类型
order:在内存中是按行主(C样式)顺序还是按列主(Fortran样式)顺序存储多维数据。
shape:可以是int或是元组,也可以是列表
import numpy as np
x=np.empty((4,5))
x
--------------------------------------------
array([[6.23042070e-307, 3.56043053e-307, 1.60219306e-306,
7.56571288e-307, 1.89146896e-307],
[1.37961302e-306, 1.05699242e-307, 8.01097889e-307,
1.78020169e-306, 7.56601165e-307],
[1.02359984e-306, 3.56043054e-307, 1.37961641e-306,
1.33511562e-306, 1.42421160e-306],
[8.06632988e-308, 8.01106038e-307, 6.89805151e-307,
1.78020169e-306, 1.42410974e-306]])
2、union
union 取并集,效果等同于 | ,重复元素只会出现一次,但是括号里可以是 list,tuple, 甚至是 dict
同样uninon也不能用索引列出:
#TypeError: 'set' object is not subscriptable
#表示把不具有下标操作的集合对象用成了对象[i]
genres_list=set() # 获取所有的电影风格
for i in moviesdf['genresls'].str.split(' '):
genres_list=set().union(i,genres_list)
# 集合(set)是一个无序的不重复元素序列。可以使用大括号 { } 或者 set() 函数创建集合。
genres_list=list(genres_list)
genres_list
genres_list.remove('') # 去除空的元素
print(genres_list)
得到的结果:所有电影风格类型
['Movie', 'Documentary', 'Comedy', 'Crime', 'Fantasy', 'History', 'Drama', 'Horror', 'Action', 'War', 'Foreign', 'Thriller', 'Fiction', 'Animation', 'Science', 'Music', 'Western', 'Romance', 'Family', 'TV', 'Mystery', 'Adventure']
3、axis=0 与 axis=1
例子一:
例子二:
3、数组广播机制
1、用途:
在Numpy中当数组进行运算时,如果两个数组的形状相同,那么两个数组相乘就是两个数组的对应位相乘,这是要求维数相乘,并且各维度的长度相同,但是当运算中两个数组的形状不同使时,numpy将会自动触发广播机制,所以我们要了解numpy的广播机制,才能更好的进行数组的运算
简单来说就是将不能运算的数组变成可运算的,不过需要满足下面的条件
2、条件
- 数组拥有相同形状。
- 数组拥有相同的维数,且某一个或多个维度长度为 1 。
- 数组拥有极少的维度,可以在其前面追加长度为 1 的维度,使上述条件成立
3、广播的规则
- 规则 1:如果两个数组的维度数不相同,那么小维度数组的形状将会在最左边补 1。
- 规则 2:如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度 为 1 的维度扩展以匹配另外一个数组的形状。
- 规则 3:如果两个数组的形状在任何一个维度上都不匹配并且没有任何一个维度等于 1, 那么会引发异常。
4、
- 让所有的输入数组首先向其中位数最多的数组看起,shape属性中的不足部分通过在前面 加1补齐
- 输出数组的shape属性是输入数组的shape属性在各个轴的最大值
- 如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
- 如果两个数组的输入维数相同,后缘维度相同,但是前面的元素个数不同,无法运算,比如a.shape=[2,2] b.shape = [3,2],则无法进行广播
import numpy as np
# 创建一个二维数组
arr1 = np.arange(4).reshape((2, 2))
print("arr1:\n", arr1)
print("arr1 的形状:\n", arr1.shape) # (2,2)
arr2 = np.array([1, 2])
arr3 = np.array([[1, 2], [1, 2], [1, 2]])
print("arr2:\n", arr2)
print("arr2 的形状:\n", arr2.shape) # (2,)--->(1,2) # (3,2)
print("arr1 + arr2 :\n", arr1 + arr3)
# 问题 数组1 shape =(2,3,4,5,6,7,8)
# 数组2 shape = (1,7,8) 数组1和数组2 可以算术计算
# 数组3 shape=(7,8,9,4,2)
# 数组4 shape = (7,2,1,4,2) 数组3 和数组4不能进行算术计算
3、reduce
4、ascending=False 与 reverse=False
ascending与reverse刚好是相反的
ascending=False:降序
ascending=True:升序
reverse=False:升序
reverse=True:降序
5、set_index和reset_index
set_index( )
将 DataFrame 中的指定的列转化为行索引。
- set_index( ) 将 DataFrame 中的列转化为行索引。
- keys : 要设置为索引的列名(如有多个应放在一个列表里)
- drop : 将设置为索引的列删除,默认为True
- append : 是否将新的索引追加到原索引后(即是否保留原索引),默认为False
- inplace : 是否在原DataFrame上修改,默认为False
- verify_integrity : 是否检查索引有无重复,默认为False
import pandas as pd
data = pd.DataFrame([['Alice', 'Math', 93], ['Bob', 'Physics', 98], ['Chris', 'Chemistry', 96], ['David', 'Biology', 90]],
columns=['Name', 'Subject', 'Score'])
print(data)
print('\n')
data1 = data.set_index(keys='Name')
print(data1)
reset_index
可以还原索引,从新变为默认的整型索引
6、json自定义函数提取数据
#对于json格式的数据进行分割提取,通过自定义函数
def decode(column):
z=[]
for i in column:
z.append(i['name'])
return ' '.join(z)
# 获取dict中第一个元素的name值
def decode1(column):
z=[]
for i in column:
z.append(i['name'])
return ''.join(z[0:1]) #切片,只输出第一个分隔
# 获取演员列表,中间使用逗号分隔
def decodeactors(column):
z=[]
for i in column:
z.append(i['name'])
return ','.join(z) #切片,只输出第一个分隔
# 获取演员列表的前两位
def decode2(column):
z=[]
for i in column:
z.append(i['name'])
return ','.join(z[0:2]) #切片,只输出第一个分隔
# 获取电影风格数据
moviesdf['genresls']=moviesdf['genreslist'].apply(decode)
# 获取演员列表
moviesdf['actorsls']=moviesdf['castlist'].apply(decodeactors)
# 获取前两位演员
moviesdf['actorsn0102']=moviesdf['castlist'].apply(decode2)
# 获取第一位演员
moviesdf['actorsn01']=moviesdf['castlist'].apply(decode1)
# 获取制片的第一个国家或者地区
moviesdf['region']=moviesdf['countries'].apply(decode1)
7、apply 与lambda
apply通常与lambda一起使用
lambda原型为:lambda 参数:操作(参数)
lambda函数也叫匿名函数,即没有具体名称的函数,它允许快速定义单行函数,可以用在任何需要函数的地方。这区别于def定义的函数。
lambda与def的区别:
1)def创建的方法是有名称的,而lambda没有。
2)lambda会返回一个函数对象,但这个对象不会赋给一个标识符,而def则会把函数对象赋值给一个变量(函数名)。
3)lambda只是一个表达式,而def则是一个语句。
4)lambda表达式后面,只能有一个表达式,def则可以有多个。
5)像if或for或print等语句不能用于lambda中,def可以。
6)lambda一般用来定义简单的函数,而def可以定义复杂的函数。
#单个参数的:
g = lambda x : x ** 2
print g(3)
"""
9
"""
#多个参数的:
g = lambda x, y, z : (x + y) ** z
print g(1,2,2)
"""
9
"""
例子二:
# 将一个 list 里的每个元素都平方:
map( lambda x: x*x, [y for y in range(10)] )
这个写法要好过:
def sq(x):
return x * x
map(sq, [y for y in range(10)])
8、join
Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串。
语法:
str.join(sequence)
sequence – 要连接的元素序列。
返回通过指定字符连接序列中元素后生成的新字符串。
9、copy
这里将的是copy在数组切片当中的应用:数组的切片返回的是原始数组的视图,并不会产生新的数据,这就意味着在视图上的操作会使原数组发生改变。因此如果需要的并非原始图,而是复制数据,则可以通过copy的方式实现。
arr1=arr[04:-1].copy()
9、len
len函数返回对象的长度。 通常,len函数与序列(字符串, 元组 )和集合( dict , set )一起使用以获取项数。
9、append
a.append(b):是将b原封不动的追加到a的末尾上,会改变a的值,其中,b可为列表、元组、字符串、一串数/字符/字符串
【1】列表
a = [1,2,3]
b = [4,5]
a.append(b)
print(a) #输出:[1, 2, 3, [4, 5]]
【2】元组
a = [1,2,3]
b = (4,5)
a.append(b)
print(a) #输出:[1, 2, 3, (4, 5)]
【3】字符串
a = [1,2,3]
b = 'string'
a.append(b)
print(a) #输出:[1, 2, 3, 'string']
【4】一串数或者字符或者字符串
如果是一串数或者字符或者字符串,则会将b转化成元组追加到a的末尾
# b是一串数字
a = [1,2,3]
b = 4,5
a.append(b)
print(a) #输出:[1, 2, 3, (4, 5)]
# b是一串字符
a = [1,2,3]
b = 'l','a','n'
a.append(b)
print(a) #输出:[1, 2, 3, ('l', 'a', 'n')]
# b是一串字符串
a = [1,2,3]
b = 'lan','tian'
a.append(b)
print(a) #输出:[1, 2, 3, ('lan', 'tian')]
append和join的区别
# coding=utf-8
#append
# append是list(列表)的方法,函数参数是可以是任意一个元素,
#作用是在列表的最后添加上这个新元素。例如a=[1,2,3]则
# a.append(4)以后a就是[1,2,3,4]
a = [1,2,3]
print a
a.append(4)
print a
#join
# join是string(字符串)的方法,函数参数是一个由字符串组成的列表比如['a','b','c'],
#作用是用字符串把这个字符串列表里的字符串连接起来,比如:
# a='-'
# 则a.join(['a','b','c'])='a-b-c'
a = ["hello","world","!"]
#用' '隔开
b = ' '
print b.join(a)
#结果:hello world !
#用':'隔开
print ':'.join(a)
# 结果:hello:world:!
10、merge
pandas.merge的报错:MergeError: No common columns to perform merge on.
原因:没有共同的列来进行融合,则会报错
因为merge函数默认需要提供相同的列来进行融合,如果没有的话可以通过设置left_index
和right_index=True
来融合所有的列
解决:指定让两个df的索引相同来进行融合df.merge(s,left_index=True,right_index=True)
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=True,
suffixes=('_x', '_y'), copy=True, indicator=False,
validate=None)
left:
拼接的左侧DataFrame对象right:
拼接的右侧DataFrame对象on:
用于连接的列名。 必须在左侧和右侧DataFrame对象中找到。 如果未传递且left_index和right_index为False,则DataFrame中的列的交集将被推断为连接键。left_on:
左侧DataFrame中用于连接键的列。right_on:
左侧DataFrame中用于连接键的列。left_index:
左侧DataFrame中行索引作为连接键right_index:
右侧DataFrame中行索引作为连接键how:
有五种参数(inner,left,right,outer,cross) 默认inner。inner是取交集,outer取并集。left是包含左边的全部数据,如果右边没有相应的数据则使用NAN填充。right是包含右边的全部数据,如果左边没有则使用NAN值填充。cross表示将左右两个DataFrame进行笛卡尔积。两个数据框的数据交叉匹配,行数为两者相乘,列数为两者相加。sort:
按字典顺序通过连接键对结果DataFrame进行排序。 默认为True,设置为False将在很多情况下显着提高性能。suffixes:
修改重复列名。(可指定我们自己想要的后缀)
import pandas as pd
price=pd.DataFrame({'fruit':['apple','grape','orange','orange'],'price':[8,7,9,11]})
amount=pd.DataFrame({'fruit':['apple','grape','orange','banana'],'amount':[1,2,2,3]})
display(price,amount,pd.merge(price,amount))
pd.merge(price,amount)
等价于pd.merge(price,amount,on='fruit',how='inner')
import pandas as pd
df1=pd.DataFrame({'name1':['小1','小2','小3','小4'],'age':[25,28,39,35]})
df2=pd.DataFrame({'name2':['小1','小2','小4'],'score':[70,60,90]})
display(df1,df2,pd.merge(df1,df2))
上面这段代码报错:
原因在于df1使用的是name1,df2使用的是name2。两张表当中没有相同的字段。这种情况下就必须指定left_on,和right_on。
MergeError: No common columns to perform merge on. Merge options: left_on=None, right_on=None, left_index=False, right_index=False
11、combine_first
如上图是S5和S6,两者存在重复的索引f和g,此时使用merge和concat都无法正确的合并,因此使用combine_first。
如上图combine_first可以去除重复的索引值,原因在于s5.combine_first(s6)
表示的是使用s6去填充s5的缺失值。
12、concatenate
numpy提供了numpy.concatenate((a1,a2,…), axis=0)函数。能够一次完成多个数组的拼接。其中a1,a2,…是数组类型的参数
>>> a=np.array([1,2,3])
>>> b=np.array([11,22,33])
>>> c=np.array([44,55,66])
>>> np.concatenate((a,b,c),axis=0) # 默认情况下,axis=0可以不写
array([ 1, 2, 3, 11, 22, 33, 44, 55, 66]) #对于一维数组拼接,axis的值不影响最后的结果
>>> a=np.array([[1,2,3],[4,5,6]])
>>> b=np.array([[11,21,31],[7,8,9]])
>>> np.concatenate((a,b),axis=0)
array([[ 1, 2, 3],
[ 4, 5, 6],
[11, 21, 31],
[ 7, 8, 9]])
>>> np.concatenate((a,b),axis=1) #axis=1表示对应行的数组进行拼接
array([[ 1, 2, 3, 11, 21, 31],
[ 4, 5, 6, 7, 8, 9]])
numpy.append()和numpy.concatenate()相比,concatenate()效率更高,适合大规模的数据拼接
13、concat
如果要合并的DataFrame之间没有连接键,就无法使用merge方法,此时可以使用concat方法,把两个完全无关的数据拼起来。
concat方法相当于数据库中的全连接(UNION ALL),可以指定按某个轴进行连接,也可以指定连接的方式join(outer,inner 只有这两种)。
与数据库不同的是concat不会去重,要达到去重的效果可以使用drop_duplicates方法
concat(
objs, axis=0, join='outer', join_axes=None,
ignore_index=False, keys=None, levels=None, names=None,
verify_integrity=False, copy=True
)
df1 = DataFrame({'a1': ['Chicago', 'San Francisco', 'New York City'], 'rank': range(1, 4)})
df2 = DataFrame({'a2': ['Chicago', 'Boston', 'Los Angeles'], 'rank': [1, 4, 5]})
pd.concat([df1,df2])
从上面的结果可以看出,concat的连接方式是外连接(并集),通过传入join=‘inner’可以实现内连接。
winedf=pd.concat([pd.DataFrame(wine.data),pd.DataFrame(wine.target)],axis=1)
14、groupby
groupby:可以根据索引或字段对数据进行分组。
DataFrame.groupby(by=None,axis=0,level=None,as_index=True,sort=True,group_keys=True,squeeze=False)
by | 可以传入函数、字典、Series等,用于确定分组的依据 |
---|---|
axis | 接收int,表示操作的轴方向,默认为0 |
level | 接收int或索引名,代表标签所在级别,默认为None |
as_index | 接收boolean,表示聚合后的聚合标签是否以 DataFrame索引输出 |
sort | 接收boolean,表示对分组依据和分组标签排序,默认为True |
group_keys | 接收boolean,表示是否显示分组标签的名称,默认为True |
squeeze | 接收boolean ,表示是否在允许情况下对返回数据降维,默认为False |
对于by,如果传入的是一个函数,则对索引进行计算并分组;如果传入的是字典或者Series,则用字典或者Series的值作为分组的依据;如果传入的是numpy数组,则用数据元素作为分组依据‘如果传入的是字符串或者字符串列表,则用这些字符串所代表的字段作为分组依据。
15、values()与itervalues()
1、values():
python内置的values()函数返回一个字典中所有的值。
即只返回{key0:value0,key1:value1}中的value0、value1……
并且重复值都会返回
- values() 方法把一个 dict 转换成了包含 value 的list。
- itervalues() 方法不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。
- 打印 itervalues() 发现它返回一个对象,这说明在Python中,for 循环可作用的迭代对象远不止 list,tuple,str,unicode,dict等,任何可迭代对象都可以作用于for循环,而内部如何迭代我们通常并不用关心。
16、value_counts
pandas 的value_counts()
函数可以对Series里面的每个值进行计数并且排序。
如果我们想知道,每个区域出现了多少次,可以简单如下:
每个区域都被计数,并且默认从最高到最低做降序排列。
如果想用升序排列,可以加参数ascending=True:
如果想得出的计数占比,可以加参数normalize=True:
空值是默认剔除掉的。value_counts()返回的结果是一个Series数组,可以跟别的数组进行运算。
例子二:结合分桶函数cut
ages = [20,22,25,27,21,23,37,31,61,45,41,32]
#将所有的ages进行分组
bins = [18,25,35,60,100]
#使用pandas中的cut对年龄数据进行分组
cats = pd.cut(ages,bins)
print(cats)
#调用pd.value_counts方法统计每个区间的个数
number=pd.value_counts(cats)
print(pd.value_counts(cats))
17、sort 与sort_values
sorted(iterable[, cmp[, key[, reverse]]])
iterable.sort(cmp[, key[, reverse]])
参数解释:
(1)iterable指定要排序的list或者iterable,不用多说;
(2)cmp为函数,指定排序时进行比较的函数,可以指定一个函数或者lambda函数,如:
students为类对象的list,每个成员有三个域,用sorted进行比较时可以自己定cmp函数,例如这里要通过比较第三个数据成员来排序,代码可以这样写:
students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]
sorted(students, key=lambda student : student[2])
(3)key为函数,指定取待排序元素的哪一项进行排序,函数用上面的例子来说明,代码如下:
sorted(students, key=lambda student : student[2])
key指定的lambda函数功能是去元素student的第三个域(即:student[2]),因此sorted排序时,会以students所有元素的第三个域来进行排序。
18、open
open(file, mode='r')
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
file: 必需,文件路径(相对或者绝对路径)。
mode: 可选,文件打开模式
buffering: 设置缓冲
encoding: 一般使用utf8
errors: 报错级别
newline: 区分换行符
closefd: 传入的file参数类型
19、read_cav与to_csv
-
read_csv
-
to_csv
【1】获取当前工作路径
import os
os.getcwd() # 获取当前工作路径
【2】to_csv()是DataFrame类的方法,read_csv()是pandas的方法
dt.to_csv() #默认dt是DataFrame的一个实例,参数解释如下
【3】路径 path_or_buf: A string path to the file to write or a StringIO
dt.to_csv('Result.csv') #相对位置,保存在getwcd()获得的路径下
dt.to_csv('C:/Users/think/Desktop/Result.csv') #绝对位置
【4】分隔符 sep : Field delimiter for the output file (default ”,”)
dt.to_csv('C:/Users/think/Desktop/Result.csv',sep='?')#使用?分隔需要保存的数据,如果不写,默认是,
【5】替换空值 na_rep: A string representation of a missing value (default ‘’)
dt.to_csv('C:/Users/think/Desktop/Result1.csv',na_rep='NA') #缺失值保存为NA,如果不写,默认是空
【6】格式 float_format: Format string for floating point numbers
dt.to_csv('C:/Users/think/Desktop/Result1.csv',float_format='%.2f') #保留两位小数
【7】保存某列数据 cols: Columns to write (default None)
dt.to_csv('C:/Users/think/Desktop/Result.csv',columns=['name']) #保存索引列和name列
【8】是否保留列名 header: Whether to write out the column names (default True)
dt.to_csv('C:/Users/think/Desktop/Result.csv',header=0) #不保存列名
【9】是否保留行索引 index: whether to write row (index) names (default True)
dt.to_csv('C:/Users/think/Desktop/Result1.csv',index=0) #不保存行索引
20、remove
remove() 函数可以删除列表中的指定元素。
语法:
list.remove(obj)
【1】obj – 列表中要移除的对象。
【2】返回值:该方法没有返回值但是会移除列表中的某个值的第一个匹配项。
分析一下结果为什么是【2,4】
remove方法用于移除列表中某个值的第一个匹配,这个没错。但是在上述例子中,第一次循环时,i=1,因此移除1,此时list为:[2,3,4,5]
此时索引为0的元素已经变成了2,而不再是1,而循环会从索引为1的元素开始,此时 i=3,然后根据 if 的判断,3会被remove掉,元素 4 的索引位置再往前变为2,循环再次开启,从索引为 3 的地方开始,即 5,再remove掉,故此最后遗留下来的list是:[2, 4]
21、series
import numpy as np
import pandas as pd
l1 = [1,2,"中国",4.5]
display(type(l1)) #list
display(l1) # [1, 2, '中国', 4.5]
display(l1[2]) # '中国'
=================================================================
a1 = np.array([1,2,5,6,8])
display(a1) # array([1, 2, 5, 6, 8])
display(type(a1)) #numpy.ndarray
display(a1[4]) # 8
=================================================================
s1 = pd.Series([1,3,5,7,9])
display(s1)
'''
0 1
1 3
2 5
3 7
4 9
dtype: int64
'''
display(s1[4]) # 9
=================================================================
s2 = pd.Series([1,3,5,7,9],index=["a","b","c","d","e"])
display(s2)
'''
a 1
b 3
c 5
d 7
e 9
dtype: int64
'''
display(s2["d"]) # 7
display(s2[3]) # 7
=================================================================
s3 = pd.Series([1,3,5,7,9],index=[3,4,5,6,6]) #index是可以重复的
display(s3)
'''
3 1
4 3
5 5
6 7
6 9
dtype: int64
'''
display(s3[6])
# 括号里面指的都是索引index ,由于有两个index都是6,因此两个都输出
'''
6 7
6 9
dtype: int64
'''
创建Series序列时,当不指定索引的时候,默认使用的从0开始的整数索引;当自己指定了字符串索引,既可以通过这个字符串索引访问元素,也可以通过默认的整数索引访问元素;当自己指定一个整数索引,那么该索引会覆盖掉原有的默认的整数索引,只能通过这个新的整数索引访问元素,默认的整数索引会失效。
【1】创建Series的语法:pd.Series();
【2】常用的几个参数:index,用于指定新的索引;dtype,用于指定元素的数据类型;
【3】大前提:要记住Series是一个一维的结构
1、通过一维列表创建Series
x = [1,3,5,7,9]
y = pd.Series(x,index=["a","b","c","d","e"],dtype=np.float32)
display(y)
'''
a 1.0
b 3.0
c 5.0
d 7.0
e 9.0
dtype: float32
'''
2、通过可迭代对象创建Series
x = range(2,7)
y = pd.Series(x)
display(y)
'''
0 2
1 3
2 4
3 5
4 6
dtype: int64
'''
3、通过字典创建Series
x = dict(a=22,b=18,c=35)
y = pd.Series(x)
display(y)
'''
a 22
b 18
c 35
dtype: int64
'''
4、通过一维数组创建Series
x = np.arange(1,6)
y = pd.Series(x)
display(y)
'''
0 1
1 2
2 3
3 4
4 5
dtype: int32
'''
5、通过标量(常数)创建Series
x = 22
y1 = pd.Series(x)
display(y1)
y2 = pd.Series(x,index=list(range(5)))
display(y2)
'''
0 22
dtype: int64
0 22
1 22
2 22
3 22
4 22
dtype: int64
'''
6、list、ndarray、Series的简单比较
【1】list列表,列表中的元素可以是不同的数据类型,使用从0开始的整数值作为默认索引;
【2】ndarray数组,数组中的元素必须是同种数据类型,也是使用从0开始的整数值作为默认索引;
【3】Series序列,是一种一维的结构,类似于一维列表和ndarray中的一维数组,但是功能比他们要更为强大,Series由两部分组成:索引index和数值values;
一维列表和一维数组中都是采用从0开始的整数值作为默认索引,索引值一般不显示的给出,但是我们可以通过索引去获取其中的元素。对于Series来说,默认索引也是从0开始的整数值作为默认索引,但是是显示地给出,更为强大的是,Series中的索引可以随意设置,方便我们取数。
22、DF的表头columns和index
对于DataFrame表格来说,dataframe.columns
返回的是横向的表头,dataframe.index
返回的是纵向的表头
import numpy as np
df1= pd.DataFrame([('bird', 389.0),('bird', 24.0),
('mammal', 80.5),('mammal', np.nan)],
index=['falcon', 'parrot', 'lion', 'monkey'],
columns=('class', 'max_speed'))
df2= pd.DataFrame([('bird', 389.0),('bird', 24.0),
('mammal', 80.5),('mammal', np.nan)],)
display(df1,df2)
用columns修改列名:
import pandas as pd
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})
df.columns = ['a', 'b', 'c', 'd', 'e']
改变Dataframe一列当中的列名:
# (作业:分类型数据类型转换成int型)
lidf23=lidf23.astype({'评价':'int'})
Series和ndarray中常用属性对比:
s = pd.Series([1,3,5,7,9])
display(s)
display(s.ndim) # 1:表示一维
display(s.shape) # (5,):表示一维,并且有5个元素
display(s.dtype) # dtype('int64') 类型
display(s.size) # 5 元素个数
display(s.nbytes)# 40:所有元素所占空间的大小
display(s.T)# 转置,由于是一维的所以没有变化
23、字典
Python字典是另一种可变容器模型,可存储任意类型对象。如字符串、数字、元组等其他容器模型
因为字典是无序的所以不支持索引和切片。
元素以键值对存在》》》key(键值):value(实值)
空字典:字典名={} 或者字典名=dict()
dict = {"nane": "张三", "age": 20, "sex": "男"}
dict1={}
print(dict) # {'nane': '张三', 'age': 20, 'sex': '男'}
print(dict1) # {}
【1】key不可以重复,否则只会保留第一个;
【2】value值可以重复;
【3】key可以是任意的数据类型,但不能出现可变的数据类型,保证key唯一;
【4】key一般形式为字符串。
字典的增删改查
- 增
格式: 字典名[new key]=new value
# 定义一个字典
dict = {"nane": "张三", "age": 20, "sex": "男"}
# 增加元素
dict["score"] = 100
print(dict) # {'nane': '张三', 'age': 20, 'sex': '男', 'score': 100}
- 删
格式:del 字典名[key]
# 定义一个字典
dict = {"name": "张三", "age": 20, "sex": "男"}
#删除元素
del dict["name"]
print(dict) # {'age': 20, 'sex': '男'}
- 改
格式: 字典名[key]=new value
# 定义一个字典
dict = {"name": "张三", "age": 20, "sex": "男"}
#修改元素
dict["name"]="李四"
print(dict) # {'name': '李四', 'age': 20, 'sex': '男'}
- 查
格式: value=字典名[key]
# 定义一个字典
dict = {"name": "张三", "age": 20, "sex": "男"}
#查找元素
value=dict["sex"]
print(value) # 男
- 清空字典
#清空字典
dict.clear()
print(dict)
名称 | 解释 |
---|---|
len() | 测量字典中键值对个数 |
keys() | 返回字典中所有的key |
values() | 返回包含value的列表 |
items() | 返回包含(键值,实值)元组的列表 |
in \ not in | 判断key是否存在字典中 |
# 定义一个字典
dict = {"name": "张三", "age": 20, "sex": "男"}
#常见操作
#len():测量字典中的键值对
print(len(dict)) # 3
#keys():返回所有的key
print(dict.keys()) #dict_keys(['name', 'age', 'sex'])
#values():返回包含value的列表
print(dict.values()) # dict_values(['张三', 20, '男'])
#items():返回包含(键值,实值)元组的列表
print(dict.items()) # dict_values(['张三', 20, '男'])
#in not in
if 20 in dict.values():
print("我是年龄")
if "李四" not in dict.values():
print("李四不存在")
字典函数values(),keys(),items()
- values()函数:返回一个字典中所有的值。即只返回{key0:value0,key1:value1}中的value0、value1。
- keys()函数:以列表形式(并非直接的列表,若要返回列表值还需调用list函数)返回字典中的所有的键。
- items()函数:是可以将字典中的所有项,以列表方式返回。因为字典是无序的,所以用items方法返回字典的所有项,也是没有顺序的。
字典三种取值方式
1.value=字典名[key]:
这种是比较简单的方式,通过key值进行取值
#字典的定义
my_dict={"name":"小红","age":20,"sex":"女"}
#1.value=字典名[key]
print(my_dict["age"]) # 20
2.setdefault:
格式:字典名.setdefault(k,value)
如果key值存在,那么返回对应字典的value,不会用到自己设置的value;
如果key值不存在.返回None,并且把新设置的key和value保存在字典中;
如果key值不存在,但设置了value,则返回设置的value;
#字典的定义
my_dict={"name":"小红","age":20,"sex":"女"}
#2.setdefault: 格式:字典名.setdefault(k,default)
#如果key存在返回对应的value
print(my_dict.setdefault("name")) # 小红
print(my_dict.setdefault("name","111")) # 小红
print(my_dict) #{'name': '小红', 'age': 20, 'sex': '女'}
#如果key不存在,返回None,并且将设置的加入字典中
print(my_dict.setdefault("name1")) # None
print(my_dict.setdefault("name1","555")) # None
print(my_dict) # {'name': '小红', 'age': 20, 'sex': '女', 'name1': None}
3.get:
格式:字典名.get(k,value)
如果key值存在,那么返回对应字典的value,不会用到自己设置的value;
如果key值不存在.返回None,但是不会把新设置的key和value保存在字典中;
如果key值不存在,但设置了value,则返回设置的value;
#字典的定义
my_dict={"name":"小红","age":20,"sex":"女"}
#3.get: 格式:字典名.get(k,default)
#如果key存在返回对应的value
print(my_dict.get("name")) #小红
print(my_dict.get("name","李四")) # 小红
#如果key不存在,返回None,设置的不加入字典中
print(my_dict.get("name2")) # None
print(my_dict.get("name2","王五")) # 王五
print(my_dict) # {'name': '小红', 'age': 20, 'sex': '女'}
字典的遍历
#字典的定义
my_dict={"name":"小红","age":20,"sex":"女"}
#1.key
for i in my_dict.keys():
print(i)
'''
name
age
sex
'''
#2.value
for i in my_dict.values():
print(i)
'''
小红
20
女
'''
#3.所有项(元素) item
for i in my_dict.items():
print(i)
'''
('name', '小红')
('age', 20)
('sex', '女')
'''
#4.依次打印key和value,通过索引
for key,value in my_dict.items():
print(key,value)
'''
name 小红
age 20
sex 女
'''
#5.元素值和对应的下标索引 enumerate(列表名)
for i in enumerate(my_dict):
print(i)
'''
(0, 'name')
(1, 'age')
(2, 'sex')
'''
25、切片
正下标从0开始,负下标从-1开始1。切片的时候包括头不包括尾部。
25、loc和iloc
loc是指location的意思,iloc中的i是指integer。
【1】iloc:根据标签的所在位置,从0开始计数,先选取行再选取列
【2】loc:根据DataFrame的具体标签选取行列,同样是先行标签,后列标签
lypdfdata=lypdf.iloc[:,1:-1].values
lypdftarget=lypdf.iloc[:,:-1].values
# 逗号前面是属于行,后面是属于列
1. 利用loc、iloc提取行数据
import numpy as np
import pandas as pd
#创建一个Dataframe
data=pd.DataFrame(np.arange(16).reshape(4,4),index=list('abcd'),columns=list('ABCD'))
In[1]: data
Out[1]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
#取索引为'a'的行
In[2]: data.loc['a']
Out[2]:
A 0
B 1
C 2
D 3
#取第一行数据,索引为'a'的行就是第一行,所以结果相同
In[3]: data.iloc[0]
Out[3]:
A 0
B 1
C 2
D 3
2. 利用loc、iloc提取列数据
In[4]:data.loc[:,['A']] #取'A'列所有行,多取几列格式为 data.loc[:,['A','B']]
Out[4]:
A
a 0
b 4
c 8
d 12
In[5]:data.iloc[:,[0]] #取第0列所有行,多取几列格式为 data.iloc[:,[0,1]]
Out[5]:
A
a 0
b 4
c 8
d 12
3.利用loc、iloc提取指定行、指定列数据
In[6]:data.loc[['a','b'],['A','B']] #提取index为'a','b',列名为'A','B'中的数据
Out[6]:
A B
a 0 1
b 4 5
In[7]:data.iloc[[0,1],[0,1]] #提取第0、1行,第0、1列中的数据
Out[7]:
A B
a 0 1
b 4 5
4.利用loc、iloc提取所有数据
In[8]:data.loc[:,:] #取A,B,C,D列的所有行
Out[8]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
In[9]:data.iloc[:,:] #取第0,1,2,3列的所有行
Out[9]:
A B C D
a 0 1 2 3
b 4 5 6 7
c 8 9 10 11
d 12 13 14 15
5.利用loc函数,根据某个数据来提取数据所在的行
In[10]: data.loc[data['A']==0] #提取data数据(筛选条件: A列中数字为0所在的行数据)
Out[10]:
A B C D
a 0 1 2 3
In[11]: data.loc[(data['A']==0)&(data['B']==2)] #提取data数据(多个筛选条件)
Out[11]:
A B C D
a 0 1 2 3
26、DataFrame
data=[[-1,2],[-0.5,6],[0,10],[1,18]]
python读取DataFrame的某几列(根据列名)
import pandas as pd
data=pd.read_csv("titanic.csv")
data1=data[['Age','Sex','Embarked','Survived']]
DF删除特定的一列:
data.loc[:,-1]=label
data.head()
data.drop(['Survived'],axis=1,inplace=True)
DF修改表头的名字,使用rename:
data.rename(columns={'-1':'Survived'})
Dataframe中添加一列对原始数据进行对比:
result['YN']=(result['实际类别']==result['预测类别']) # 得到的结果是布尔值
result.loc[result['YN']==False]
27、shape与reshape
shape函数是numpy.core.fromnumeric中的函数,它的功能是读取矩阵或者数组的维数,比如shape[0]就是读取矩阵第一维度的长度。
例如:建立一个4×2的矩阵c, c.shape[0]
为第二维的长度,c.shape[1]
为第二维的长度。
shape中数字的含义:
【1】a.shape 输出 (4,),其中只有一个数字4,表示一维;数字4表示含有4个数据。
【2】b.shape 输出 (3,2),其中含有两个数字(分别是3,2)表示二维数组。3,2的含义为:3表示其中含有3个一维数组,2表示一维数组中含有2个元素
也可以直接使用ndim的方法进行维度的输出。
reshape()是数组对象中的方法,用于改变数组的形状。
# 使用众数填充Embarked,但是Embarked默认是字符型
Embarked=data.loc[:,'Embarked'].values.reshape(-1,1) # 变成二维矩阵
Embarked.shape
三维数组:
对于三维数组的shape:
三维数组就是包含多少个二维数组,后两个数字表示二维数组的形状
在机器学习中的reshape的作用:
sklearn不接受任何一维矩阵作为特征矩阵被输入。如果你的数据的确只有一个特征,那必须用reshape(-1,1)来给矩阵降维或者升维。
reshape中的一个参数可以设置成-1,表示数组的维度可以通过数据本身来判断。
-1的意思是模糊控制,例如:reshape(-1,2)表示重构数组的为数之后固定是两列,但是行数未知。
28、替换函数strip(),replace(),sub()
- replace是用在将查询到的数据替换为指定数据。
Python replace()
方法把字符串Q中的old (l旧字符串)替换成new(新字符串),如果指定第三个参数max,则替换不超过max次。
语法:
str.replace(old, new, max)
在DF中也可以使用:
import pandas as pd
price1=pd.DataFrame({'fruit':['apple','grape','orange'],'price':[8,7,9]})
display(price1)
price2=price1.replace('orange','watermelon')
display(price2)
2. Python strip()
方法用于移除字符串头尾指定的字符(默认为空格)或字符序列。
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
str.strip([chars]);
参数:
chars – 移除字符串头尾指定的字符序列。
如果不带参数,默认是清除两边的空白符,例如:/n, /r, /t, ’ ’
当你传的参数不管是“12”还是12的其他排列形式,这都不重要,重要的是函数只知道你要删除的字符是”1”,”2”。函数会把你传的参数拆解成一个个的字符,然后把头尾的这些字符去掉。
30、unique
【1】a = np.unique(A)
对于一维数组或者列表,unique函数去除其中重复的元素,并按元素由大到小返回一个新的无元素重复的元组或者列表
import numpy as np
A = [1, 2, 2, 5,3, 4, 3]
a = np.unique(A)
B= (1, 2, 2,5, 3, 4, 3)
b= np.unique(B)
C= ['fgfh','asd','fgfh','asdfds','wrh']
c= np.unique(C)
print(a)# 输出为 [1 2 3 4 5]
print(b)# [1 2 3 4 5]
print(c)# ['asd' 'asdfds' 'fgfh' 'wrh']
【2】c,s=np.unique(b,return_index=True)
return_index=True表示返回新列表元素在旧列表中的位置,并以列表形式储存在s中。
a, s= np.unique(A, return_index=True)
print(a)
print(s)
# 运行结果
# [1 2 3 4 5]
# [0 1 4 5 3]
【3】a, s,p = np.unique(A, return_index=True, return_inverse=True)
return_inverse=True 表示返回旧列表元素在新列表中的位置,并以列表形式储存在p中
a, s,p = np.unique(A, return_index=True, return_inverse=True)
print(a)
print(s)
print(p)
# 运行结果
# [1 2 3 4 5]
# [0 1 4 5 3]
# [0 1 1 4 2 3 2]
31、isnull,notnull
# coding=utf-8
import numpy as np
import pandas as pd
# 创建DataFrame
df = pd.DataFrame(np.arange(12, 32).reshape((5, 4)), index=["a", "b", "c", "d", "e"], columns=["WW", "XX", "YY", "ZZ"])
df.loc[["b"],["YY"]] = np.nan # NaN是float类型,对应列会自动变成float类型。
df.loc[["d"],["XX"]] = np.nan
print(df)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
b 16 17.0 NaN 19
c 20 21.0 22.0 23
d 24 NaN 26.0 27
e 28 29.0 30.0 31
'''
# pandas判断是否是NaN
print(pd.isnull(df))
'''
WW XX YY ZZ
a False False False False
b False False True False
c False False False False
d False True False False
e False False False False
'''
# pandas判断是否不是NaN
print(pd.notnull(df))
'''
WW XX YY ZZ
a True True True True
b True True False True
c True True True True
d True False True True
e True True True True
'''
# 也可以只判断某一列的NaN
print(pd.notnull(df["XX"]))
'''
a True
b True
c True
d False
e True
Name: XX, dtype: bool
'''
# 布尔索引
print(df[pd.notnull(df["YY"])]) # 选出"YY"列不为NaN的所有行
'''
WW XX YY ZZ
a 12 13.0 14.0 15
c 20 21.0 22.0 23
d 24 NaN 26.0 27
e 28 29.0 30.0 31
'''
30、drop
drop() 删除行和列
drop([ ],axis=0,inplace=True)
【1】drop([]),默认情况下删除某一行;
【2】如果要删除某列,需要axis=1;
【3】参数inplace 默认情况下为False,表示保持原来的数据不变,True 则表示在原来的数据上改变。
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(5,3),index = list('abcde'),columns = ['one','two','three'])
df.iloc[1,:-1] = np.nan #第二行,排除倒数第一个都是Nan
df.iloc[1:-1,2] = np.nan #第三列,排除第一个和最后一个都是Nan
得到的df:
将第一列删除:
print(df.drop(['one'],axis=1))
将a和c行删除:
print(df.drop(['a','c'],axis = 0))
31、 dropna()
# coding=utf-8
import numpy as np
import pandas as pd
# 创建DataFrame
df = pd.DataFrame(np.arange(12, 32).reshape((5, 4)), index=["a", "b", "c", "d", "e"], columns=["WW", "XX", "YY", "ZZ"])
df.loc[["b"],["YY"]] = np.nan # NaN是float类型,对应列会自动变成float类型。
df.loc[["d"],["XX"]] = np.nan
print(df)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
b 16 17.0 NaN 19
c 20 21.0 22.0 23
d 24 NaN 26.0 27
e 28 29.0 30.0 31
'''
# NaN的处理方式一:直接删除
df1 = df.dropna(axis=0) # axis=0表示删除行,axis=1表示删除列
print(df1)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
c 20 21.0 22.0 23
e 28 29.0 30.0 31
'''
df2 = df.dropna(axis=0, how="all") # how="all"表示某行(列)全为NaN才会删除。how="any"表示只要有一个NaN就会删除(默认)。
print(df2)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
b 16 17.0 NaN 19
c 20 21.0 22.0 23
d 24 NaN 26.0 27
e 28 29.0 30.0 31
'''
df.dropna(axis=0, inplace=True) # inplace=True表示原地修改,修改后的结果直接作用于原df。 默认False
print(df)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
c 20 21.0 22.0 23
e 28 29.0 30.0 31
'''
31、fillna()
# coding=utf-8
import numpy as np
import pandas as pd
# 创建DataFrame
df = pd.DataFrame(np.arange(12, 32).reshape((5, 4)), index=["a", "b", "c", "d", "e"], columns=["WW", "XX", "YY", "ZZ"])
df.loc[["b"],["YY"]] = np.nan # NaN是float类型,对应列会自动变成float类型。
df.loc[["d"],["XX"]] = np.nan
print(df)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
b 16 17.0 NaN 19
c 20 21.0 22.0 23
d 24 NaN 26.0 27
e 28 29.0 30.0 31
'''
# NaN的处理方式二:填充
df2 = df.fillna(100) # 填充成100
print(df2)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
b 16 17.0 100.0 19
c 20 21.0 22.0 23
d 24 100.0 26.0 27
e 28 29.0 30.0 31
'''
# 填充平均值
df3 = df.fillna(df.mean())
# df.mean()表示每一列的平均值(Series类型)。 df.median()中位数
print(df3)
'''
WW XX YY ZZ
a 12 13.0 14.0 15
b 16 17.0 23.0 19
c 20 21.0 22.0 23
d 24 20.0 26.0 27
e 28 29.0 30.0 31
'''
# 可以只填充某一列
df4 = df["YY"].fillna(df["YY"].mean())
# df.mean()表示每一列的平均值(Series类型)
print(df4) # (Series类型)
'''
a 14.0
b 23.0
c 22.0
d 26.0
e 30.0
Name: YY, dtype: float64
'''
# df["YY"] = df["YY"].fillna(df["YY"].mean())
# 只填充某一列,再赋值给原df的对应列。
# df[df==0] = np.nan # df.mean()计算均值时,NaN不会参与计算,但0会
32、rename
**pandas.Dataframe.rename()**函数主要是用来修改Dataframe数据的行名和列名。
主要用到的参数有
【1】columns:列名
【2】index:行名
【3】axis:指定坐标轴
【4】inplace:是否替换,默认为False。inplace为False时返回修改后结果,变量自身不修改。inplace为True时返回None,变量自身被修改。
>>> import pandas as pd
>>> df
A B
0 1 4
1 2 5
2 3 6
# 方法一:不用axis修改
>>> df.rename(columns={"A": "a", "B": "c"}) # 修改columns。inplace未设置,返回修改后的结果
a c
0 1 4
1 2 5
2 3 6
>>> df # inplace未设置,默认为false,则df自身不被改变
A B
0 1 4
1 2 5
2 3 6
>>> df_re=df.rename(index={0:"0a",1:"1a"}) # 同样的方式修改行名
>>> df
A B
0 1 4
1 2 5
2 3 6
>>> df_re
A B
0a 1 4
1a 2 5
2 3 6
>>> df_re=df.rename(columns={"A": "a", "B": "c"},index={0:"0a",1:"1a"})
> # 同时修改行名和列名
>>> df_re
a c
0a 1 4
1a 2 5
2 3 6
# 方法二:用axis修改,只修改行名列名之一时等价,无法同时修改
>>> df.rename({1: 2, 2: 4}, axis='index') # 修改行名
A B
0 1 4
2 2 5
4 3 6
>>> df.rename(str.lower, axis='columns') # 列名大写变小写
a b
0 1 4
1 2 5
2 3 6
# 让inplace为True
>>> df_re=df.rename(columns={"A": "a", "B": "c"},inplace=True)
>>> print(df_re) # inplace为True时返回空值
None
>>> df # 自身被修改,可对照上面进行理解
a c
0 1 4
1 2 5
2 3 6
33、linspace
【1】linspace生成线性间距向量
【2】语法:
y = linspace(x1,x2) 返回包含 x1 和 x2 之间的 100 个等间距点的行向量。
y = linspace(x1,x2,n) 生成 n 个点。这些点的间距为 (x2-x1)/(n-1)
from numpy import linspace
b = linspace(0,10,4)
b
import numpy as np
x=np.linspace(0,1,20)
x
34、日期时间
to_datetime
# 增加辅助列
ssqdatav2['ssqyear']=ssqdatav2['date'].dt.year # 如果原来的数据不是 datetime64[ns]类型则不能使用这个函数
ssqdatav2['ssqmonth']=ssqdatav2['date'].dt.month
ssqdatav2['ssqquarter']='Q'+(ssqdatav2['date'].dt.quarter).apply(str) #不加这个 .apply(str)会报错
ssqdatav2['ssqym']=ssqdatav2['date'].apply(lambda x:x.strftime('%Y%m'))
ssqdatav2['ssqyq']=ssqdatav2['date'].dt.to_period('Q')
ssqdatav2['ssqseason']=ssqdatav2['ssqmonth'].apply(lambda x:'spring' if x<=3 else 'summer' if x<=6 else 'autumn' if x<=9 else 'winter')
ssqdatav2.head()
strftime
35、lambda 匿名函数
1、匿名函数处理DF数据
traintemp['sizecabin']=traintemp['Cabin'].apply(lambda x:x.split(" ")) # 使用空格切分
2、处理汉字
# 为分解firstprize定义函数
def fpp(x):
if len(x)<=2: # 判断是否只有汉字,还是也有数字
return "待定"
else: # 使用正则表达式获取中文
pattern="[\u4e00-\u9fa5]"
pat=re.compile(pattern)
return ''.join(pat.findall(x))
#使用fp()
ssqdatav2['fpprovince']=ssqdatav2['first'].apply(lambda x:fpp(x))
ssqdatav2.head(310)
35、构造数组的几种方式
【1】使用array()函数创建数组
函数可基于序列型的对象(如列表、元组、集合等,还可以是一个已经创建好的数组)
#使用array函数创建数组
import numpy as np #导入numpy模块,用as可以起别名
a=np.array([1,2,3,4])
b=np.array(['产品编号','销售数量','销售单价','销售金额'])
print(a) # [1 2 3 4]
print(b) # ['产品编号' '销售数量' '销售单价' '销售金额']
创建二维数组:
import numpy as np
a=np.array([[1,2,3],[4,5,6],[7,8,9]])
print(a)
'''
[[1 2 3]
[4 5 6]
[7 8 9]]
'''
【2】创建等差数组
用arange()函数创建数组会更加方便
import numpy as np
d=np.arange(1,20,3)#起始值是1,结束值是20(结果不含该值),步长为1
print(d)# [ 1 4 7 10 13 16 19]
【3】创建随机数组
引用numpy模块的子模块random中的函数,主要有rand()函数、randn()函数、randint()函数。
rand函数创建的数组中每个元素都是[0,1)区间内的随机数
import numpy as np
e=np.random.rand(3)
print(e) # [0.51329163 0.7495376 0.8405663 ]
如果给rand()函数传入一对参数值,就会生成一个相应行、列数的二维数组,区间也是[0,1)的随机数
import numpy as np
e=np.random.rand(3,4)
print(e)
'''
[[0.80648692 0.48873991 0.78737971 0.43398966]
[0.81899231 0.16496186 0.32348197 0.52354873]
[0.47461709 0.44495098 0.59928444 0.92171408]]
'''
【4】randn()函数
用randn()函数创建的数组中的元素是符合标准正态分布(均值为0,标准差为1)的随机数
import numpy as np
e=np.random.randn(3,4)
print(e)
'''
[[-0.41245544 0.476043 -1.46849374 -0.38213323]
[ 0.74496601 -1.10202045 0.65940684 -0.01535774]
[-1.4760861 0.09343092 -0.6481946 1.00991138]]
'''
【5】randint()函数
用randint()函数创建的数组中元素是制定范围内的随机整数
import numpy as np
e = np.random.randint(1,5,10) #10个元素区间在[1,5)区间内的随机整数,随机数不包括5
print(e) #[1 1 4 2 1 4 3 3 4 3]
36、正则表达式
1、findall:
含义: findall()
是将所有匹配到的字符,以列表的形式返回。如果未匹配,则返回空列表。
语法: findall(string=None, pos=0, endpos=9223372036854775807, *, source=None)
函数作用:在string[pos,endpos]
区间从pos下标开始查找所有满足pattern的子串,直到endpos位置结束,并以列表的形式返回查找的结果,如果未找到则返回一个空列表。
参数说明:
- string:被匹配的字符串
- pos: 匹配的起始位置,可选,默认为0
- endpos: 匹配的结束位置,可选,默认为len(string)。也就是说如果不指定pos和endpos的话,该方法会在整个字符串中查找满足条件的子串。
2、re.compile():
compile 函数用于编译正则表达式,生成一个 Pattern 对象,它的一般使用形式如下:
re.compile(pattern[, flag])
从compile()函数的定义中,可以看出返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用。 compile()与findall()一起使用,返回一个列表。
其中,pattern 是一个字符串形式的正则表达式,flag 是一个可选参数,表示匹配模式,比如忽略大小写,多行模式等。
29、column_stack与hstack、vstack
对于一维数组的堆叠:
(1)column_stack()会将一位数组转化成二维数组后再进行堆叠;
(2)hstack()不会进行转化,而是直接进行堆叠,所得到的堆叠后的数组还是一维数组。
另一方面,row_stack()和stack()不会产生这样的问题,他们的结果都是二维数组。
30、contains
cond=ssqdatav2['first'].str.contains('深圳')
ssqdatav2.loc[cond] # 查找出first字段下所有包含深圳的记录,并准备将深圳用深或圳进行替换
ssqdatav2['first']
31、split
String a="a:b:c:d"
split(" : “)[0]表示把指定的字符串按照”:"来拆分成字符串数组.结果是:{a,b,c,d}
[0]是拆分出来的数组第一个元素了。
ssqdatav3['p001']=ssqdatav3['fpprovince'].apply(lambda x:x if x.count(',')==0 else x.split(',')[0])
ssqdatav3['p002']=ssqdatav3['fpprovince'].apply(lambda x:x.split(',')[1] if x.count(',')>=1 else '')
ssqdatav3['p003']=ssqdatav3['fpprovince'].apply(lambda x:x.split(',')[2] if x.count(',')>=2 else '')
ssqdatav3['p004']=ssqdatav3['fpprovince'].apply(lambda x:x.split(',')[3] if x.count(',')>=3 else '')
ssqdatav3['p005']=ssqdatav3['fpprovince'].apply(lambda x:x.split(',')[4] if x.count(',')>=4 else '')
31、strip
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
【1】strip()方法语法:
str.strip([chars]);
【2】参数
chars – 移除字符串头尾指定的字符序列。
【3】返回值
返回移除字符串头尾指定的字符生成的新字符串。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
str = "00000003210Runoob01230000000";
print str.strip( '0' ); # 去除首尾字符 0
str2 = " Runoob "; # 去除首尾空格
print str2.strip();
输出:
3210Runoob0123
Runoob
33、期末考会考题
过滤法也是重点
简答题:特征工程主要的任务有哪些?
双色球是考试的重点,一定要把双色球所有的特征都跑一遍,期末一定有一道特征工程选择的题目(10分,代码填充),(特征工程选择的题目,代码填充)
这三句话相同,都是去除掉省份当中包含深的字
ssqdataprov=ssqdataprov[(ssqdataprov['PROVINCE']!='深')]
ssqdataprov=ssqdataprov[~(ssqdataprov['PROVINCE']=='深')]
ssqdataprov=ssqdataprov[~(ssqdataprov['PROVINCE'].str.contains('深'))]
nbadata2.loc[nbadata2['ischampion'].isnull(),'ischampion']='no'
# 将空值替换为字符‘no’
nbadata2.loc[nbadata2['ischampion']==1,'ischampion']='yes'
# 将原本数据为1的地方改成字符‘yes’
nbadata2
【1】改变决策树的参数绘制学习曲线
# 使用学习曲线判断最佳的最小叶子节点样本个数
# 选取的最小样本从1到30
import matplotlib.pyplot as plt
plt.figure(figsize=(15,8))
test = []
for i in range(30):
clf = tree.DecisionTreeClassifier(min_samples_leaf=i+1 #1-10层
,criterion="entropy" # 使用gini系数
,random_state=30
,splitter="random"
)
clf = clf.fit(Xtrain, Ytrain)
score = clf.score(Xtest, Ytest) #分别计算测试集上的表现
test.append(score)
plt.plot(range(1,31),test,color="red",label="min_samples_leaf")
plt.legend()
plt.show()
【2】class_weight是权重:简答题
【3】min_weight_fraction_leaf:基于权重的剪枝参数
【4】数据模型有那四种?层次,网状,关系,面向对象
【5】期末小问答:降维和特征选择的区别?
降维本质上是从一个维度空间映射到另一个维度空间,特征的多少没有减少,当然在映射的过程中特征值也会相应的变化。举个例子,现在的特征是1000维,我们想要把它降到500维。降维的过程就是找个一个从1000维映射到500维的映射关系。原始数据中的1000个特征,每一个都对应着降维后的500维空间中的一个值。假设原始特征中有个特征的值是9,那么降维后对应的值可能是3。
举个例子来说,比如一个原始样本中的数据为( 0.1 0.4 0.8),显示原始的维度为3维,现在我们把这个三维的数据通过降维映射到二维空间,降维后原始的数据可能就成了 (0.2 0.5),这里其实( 0.1 0.4 0.8)和(0.2 0.5)表示的是同一个样本
特征选择就是单纯地从提取到的所有特征中选择部分特征作为训练集特征,特征在选择前和选择后不改变值,但是选择后的特征维数肯定比选择前小,毕竟我们只选择了其中的一部分特征。举个例子,现在的特征是1000维,现在我们要从这1000个特征中选择500个,那个这500个特征的值就跟对应的原始特征中那500个特征值是完全一样的。对于另个500个没有被选择到的特征就直接抛弃了。假设原始特征中有个特征的值是9,那么特征选择选到这个特征后它的值还是9,并没有改变。
1.所谓的特征选择和数据降维(特征提取)都是降维的一种方式。
2.特征选择是“取其精华,去其糟粕”进行筛选,特征值不变;数据降维(特征提取)是经过映射改变了特征值。
34、Sklearn的train_test_split用法
用途:
在机器学习中,该函数可按照用户设定的比例,随机将样本集合划分为训练集 和测试集,并返回划分好的训练集和测试集数据。
语法:
X_train,X_test, y_train, y_test =cross_validation.train_test_split(X,y,test_size, random_state)
参数说明:
Code | Text |
---|---|
X | 待划分的样本特征集合 |
y | 待划分的样本标签 |
test_size | 若在0~1之间,为测试集样本数目与原始样本数目之比;若为整数,则是测试集样本的数目。 |
random_state | 随机数种子 |
X_train | 划分出的训练集数据(返回值) |
X_test | 划分出的测试集数据(返回值) |
y_train | 划分出的训练集标签(返回值) |
y_test | 划分出的测试集标签(返回值) |
例子: |
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2)
test_size=0.2
:表示将20%的数据作为测试集,剩余的80%作为训练集
34、过拟合与欠拟合
无论在机器学习还是深度学习建模当中都可能会遇到两种最常见结果,一种叫过拟合(over-fitting )另外一种叫欠拟合(under-fitting)。
-
过拟合(over-fitting)
,其实就是所建的机器学习模型或者是深度学习模型在训练样本中表现得过于优越,导致在验证数据集以及测试数据集中表现不佳。打个比喻就是当我需要建立好一个模型之后,比如是识别一只狗狗的模型,我需要对这个模型进行训练。恰好,我训练样本中的所有训练图片都是二哈,那么经过多次迭代训练之后,模型训练好了,并且在训练集中表现得很好。基本上二哈身上的所有特点都涵括进去,那么问题来了!假如我的测试样本是一只金毛呢?将一只金毛的测试样本放进这个识别狗狗的模型中,很有可能模型最后输出的结果就是金毛不是一条狗(因为这个模型基本上是按照二哈的特征去打造的)。所以这样就造成了模型过拟合,虽然在训练集上表现得很好,但是在测试集中表现得恰好相反,在性能的角度上讲就是协方差过大(variance is large),同样在测试集上的损失函数(cost function)会表现得很大。 -
欠拟合呢(under-fitting)
相对过拟合欠拟合还是比较容易理解。还是拿刚才的模型来说,可能二哈被提取的特征比较少,导致训练出来的模型不能很好地匹配,表现得很差,甚至二哈都无法识别。
造成过拟合的原因有可以归结为:参数过多。增大训练样本规模同样也可以防止过拟合。
欠拟合基本上都会发生在训练刚开始的时候,经过不断训练之后欠拟合应该不怎么考虑了。但是如果真的还是存在的话,可以通过增加网络复杂度或者在模型中增加多点特征点,这些都是很好解决欠拟合的方法。
35、oversample 过采样和欠采样undersampling
-
过采样
(右上)只是单纯的重复了正例,因此会过分强调已有的正例。如果其中部分点标记错误或者是噪音,那么错误也容易被成倍的放大。因此最大的风险就是对正例过拟合。 -
欠采样
(左下)抛弃了大部分反例数据,从而弱化了中间部分反例的影响,可能会造成偏差很大的模型。当然,如果数据不平衡但两个类别基数都很大,或许影响不大。同时,数据总是宝贵的,抛弃数据是很奢侈的,因此另一种常见的做法是反复做欠采样,生成1655/176约等于9个新的子样本。其中每个样本的正例都使用这176个数据,而反例则从1655个数据中不重复采样。最终对这9个样本分别训练,并集成结果。这样数据达到了有效利用,但也存在风险;
- 训练多个模型造成了过大的开销,合并模型结果需要额外步骤,有可能造成其他错误。
- 正例被反复使用,和过采样一样,很容易造成模型的过拟合
36、分类阈值
逻辑回归返回的是概率。可以“原样”使用返回的概率(例如,用户点击此广告的概率为 0.00023),也可以将返回的概率转换成二元值(例如,这封电子邮件是垃圾邮件)。
如果某个逻辑回归模型对某封电子邮件进行预测时返回的概率为 0.9995,则表示该模型预测这封邮件非常可能是垃圾邮件。相反,在同一个逻辑回归模型中预测分数为 0.0003 的另一封电子邮件很可能不是垃圾邮件。可如果某封电子邮件的预测分数为 0.6 呢?为了将逻辑回归值映射到二元类别,必须指定分类阈值(也称为判定阈值)。如果值高于该阈值,则表示“垃圾邮件”;如果值低于该阈值,则表示“非垃圾邮件”。人们往往会认为分类阈值应始终为 0.5,但阈值取决于具体问题,因此必须对其进行调整。
我们将在后面的部分中详细介绍可用于对分类模型的预测进行评估的指标,以及更改分类阈值对这些预测的影响。
“调整”逻辑回归的阈值不同于调整学习速率等超参数。在选择阈值时,需要评估将因犯错而承担多大的后果。例如,将非垃圾邮件误标记为垃圾邮件会非常糟糕。
37、超参数
什么是超参数,参数和超参数的区别?
区分两者最大的一点就是是否通过数据来进行调整,模型参数通常是有数据来驱动调整,超参数则不需要数据来驱动,而是在训练前或者训练中人为的进行调整的参数。例如卷积核的具体核参数就是指模型参数,这是有数据驱动的。而学习率则是人为来进行调整的超参数。这里需要注意的是,通常情况下卷积核数量、卷积核尺寸这些也是超参数,注意与卷积核的核参数区分。
38、随机森林
随机森林是一个用随机方式建立的,包含多个决策树的分类器。其输出的类别是由各个树输出的类别的众数而定。
随机性主要体现在两个方面:
(1)训练每棵树时,从全部训练样本(样本数为N)中选取一个可能有重复的大小同样为N的数据集进行训练(即bootstrap取样);
(2)在每个节点,随机选取所有特征的一个子集,用来计算最佳分割方式。
优点
1、 在当前的很多数据集上,相对其他算法有着很大的优势,表现良好
2、它能够处理很高维度(feature很多)的数据,并且不用做特征选择(因为特征子集是随机选择的)
3、在训练完后,它能够给出哪些feature比较重要
4、在创建随机森林的时候,对generlization error使用的是无偏估计,模型泛化能力强
5、训练速度快,容易做成并行化方法(训练时树与树之间是相互独立的)
6、 在训练过程中,能够检测到feature间的互相影响
7、 实现比较简单
8、 对于不平衡的数据集来说,它可以平衡误差。
9、如果有很大一部分的特征遗失,仍可以维持准确度。
10、随机森林能够解决分类与回归两种类型的问题,并在这两方面都有相当好的估计表现。(虽然RF能做回归问题,但通常都用RF来解决分类问题)。
在创建随机森林时候,对generlization error(泛化误差)使用的是无偏估计模型,泛化能力强。
缺点:
随机森林在解决回归问题时,并没有像它在分类中表现的那么好,这是因为它并不能给出一个连续的输出。当进行回归时,随机森林不能够做出超越训练集数据范围的预测,这可能导致在某些特定噪声的数据进行建模时出现过度拟合。(PS:随机森林已经被证明在某些噪音较大的分类或者回归问题上回过拟合)。
对于许多统计建模者来说,随机森林给人的感觉就像一个黑盒子,你无法控制模型内部的运行。只能在不同的参数和随机种子之间进行尝试。
可能有很多相似的决策树,掩盖了真实的结果。
对于小数据或者低维数据(特征较少的数据),可能不能产生很好的分类。(处理高维数据,处理特征遗失数据,处理不平衡数据是随机森林的长处)。
执行数据虽然比boosting等快(随机森林属于bagging),但比单只决策树慢多了。
39、 cut和qcut的用法(分桶分箱)
数据分箱:是指将值划分到离散区间。好比不同大小的苹果归类到几个事先布置的箱子中;不同年龄的人划分到几个年龄段中。
一丶cut qcut的区别
1.qcut:传入参数,要将数据分成多少组,即组的个数,具体的组距是由代码计算。
2,cut:传入参数,是分组依据。
二丶qcut方法
(1)参数:
x :要进行分组的数据,数据类型为一维数组,或Series对象;
q :组数,即要将数据分成几组,后边举例说明;
labels :可以理解为组标签,这里注意标签个数要和组数相等;
retbins :默认为False,当为False时,返回值是Categorical类型(具有value_counts()方法),为True是返回值是元组。
(2)示例
三丶cut方法
(1)举例
ages = [20,22,25,27,21,23,37,31,61,45,41,32]
#将所有的ages进行分组
bins = [18,25,35,60,100] # 自定义分类数据,包括端点
#使用pandas中的cut对年龄数据进行分组
cats = pd.cut(ages,bins)
print(cats)
#调用pd.value_counts方法统计每个区间的个数
number=pd.value_counts(cats)
print(pd.value_counts(cats))
#显示第几个区间index值
index=pd.cut(ages,bins).codes
print(index)
#为分类出来的每一组年龄加上标签
group_names = ["Youth","YouthAdult","MiddleAged","Senior"]
personType=pd.cut(ages,bins,labels=group_names)
print(personType)
plt.hist(personType)
plt.show()
四丶总结
1,cut: 按连续数据的大小分到各个桶里,每个桶里样本量可能不同,但是,每个桶相当于一个等长的区间,即:以数据的最大和最小为边界,等分成p个桶。
2,qcut: 与cut主要的区别就是每个桶里的样本数量是一定的。
40、随机森林 n_estimators参数 max_features参数
要构造一个随机森林模型,第一步是确定森林中树的数目,通过模型的 进行调节。n_estimators
越大越好,但占用的内存与训练和预测的时间也会相应增长,且边际效益是递减的,所以要在可承受的内存/时间内选取尽可能大的n_estimators
。而在sklearn
中,n_estimators
默认为10。
第二步是对数据进行自助采样,也就是说,从n_sample
个数据点中有放回地重复随机抽取一个样本,共抽取n_sample
次。新数据集的容量与原数据集相等,但抽取的采样往往与原数据集不同。注意,构建的n_estimators
棵树采用的数据集都是独立自助采样的,这样才能保证所有树都互不相同。
第三步就是基于这个新数据集来构造决策树。由于加入了随机性,故构造时与一般的决策树不同。构造时,在每个结点处选取特征的一个子集,并对其中一个特征寻找最佳测试。选取的特征子集中特征的个数通过max_features参数来控制,max_features越小,随机森林中的树就越不相同,但过小(取1时)会导致在划分时无法选择对哪个特征进行测试。而在sklearn中,max_features有以下几种选取方法:“auto”, “sqrt”, “log2”, None。auto与sqrt都是取特征总数的开方,log2取特征总数的对数,None则是令max_features直接等于特征总数,而max_features的默认值是"auto"。
随机森林还有一个重要参数是n_jobs,决定了使用的CPU内核个数,使用更多的内核能使速度增快,而令n_jobs=-1可以调用所有内核。当然,构造时同样可以使用max_depth,min_samples_leaf和max_leaf_nodes来进行预剪枝,以减小内存占用与时间消耗。
41、VarianceThreshold
使用方差阈值过滤(VarianceThreshold)进行特征选择、删除方差低于某一阈值的特征、详解及实战方差阈值(VarianceThreshold)法是一种过滤特征选择法。
42、fit_transform,fit,transform区别和作用
-
fit和transform没有任何关系,仅仅是数据处理的两个不同环节,之所以出来fit_transform这个函数名,仅仅是为了写代码方便,会高效一点。
-
sklearn里的封装好的各种算法使用前都要fit,fit相对于整个代码而言,为后续API服务。fit之后,然后调用各种API方法,transform只是其中一个API方法,所以当你调用transform之外的方法,也必须要先fit。
-
fit原义指的是安装、使适合的意思,其实有点train的含义,但是和train不同的是,它并不是一个训练的过程,而是一个适配的过程,过程都是确定的,最后得到一个可用于转换的有价值的信息。
1. 数据预处理中方法
【1】fit(): Method calculates the parameters μ and σ and saves them as internal objects.
解释:简单来说,就是求得训练集X的均值,方差,最大值,最小值,这些训练集X固有的属性。
【2】transform(): Method using these calculated parameters apply the transformation to a particular dataset.
解释:在fit的基础上,进行标准化,降维,归一化等操作(看具体用的是哪个工具,如PCA,StandardScaler等)。
【3】fit_transform(): joins the fit() and transform() method for transformation of dataset.
解释:fit_transform是fit和transform的组合,既包括了训练又包含了转换。
transform()
和fit_transform()
二者的功能都是对数据进行某种统一处理(比如标准化~N(0,1),将数据缩放(映射)到某个固定区间,归一化,正则化等)
fit_transform(trainData)对部分数据先拟合fit,找到该part的整体指标,如均值、方差、最大值最小值等等(根据具体转换的目的),然后对该trainData进行转换transform,从而实现数据的标准化、归一化等等。
根据对之前部分trainData进行fit的整体指标,对剩余的数据(testData)使用同样的均值、方差、最大最小值等指标进行转换transform(testData),从而保证train、test处理方式相同。所以,一般都是这么用:
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit_tranform(X_train)
sc.tranform(X_test)
43、特征预处理的独热编码
One-Hot编码,又称为一位有效编码,主要是采用N位状态寄存器来对N个状态进行编码,每个状态都由他独立的寄存器位,并且在任意时候只有一位有效。
One-Hot编码是分类变量作为二进制向量的表示。这首先要求将分类值映射到整数值。
性别特征:[“男”,“女”],按照N位状态寄存器来对N个状态进行编码的原理,咱们处理后应该是这样的(这里只有两个特征,所以N=2):
男 => 10
女 => 01
祖国特征:[“中国”,"美国,“法国”](这里N=3):
中国 => 100
美国 => 010
法国 => 001
运动特征:[“足球”,“篮球”,“羽毛球”,“乒乓球”](这里N=4):
足球 => 1000
篮球 => 0100
羽毛球 => 0010
乒乓球 => 0001
所以,当一个样本为[“男”,“中国”,“乒乓球”]的时候,完整的特征数字化的结果为:
[1,0,1,0,0,0,0,0,1]
下图可能会更好理解:
44、ravel和flattern
python 中的 ravel() 函数将数组多维度拉成一维数组。
ravel 英文译为散开,解开;
flatten 英文译为变平。
两者的区别在于返回拷贝(copy)还是返回视图(view)。
【1】 numpy.ravel()
返回的是视图,会影响原始矩阵;
【2】numpy.flatten()
返回的是拷贝,对拷贝所做的修改不会影响原始矩阵。
45、train_test_split
import numpy as np
from sklearn.model_selection import train_test_split
#创建一个数据集X和相应的标签y,X中样本数目为100
X, y = np.arange(200).reshape((100, 2)), range(100)
#用train_test_split函数划分出训练集和测试集,测试集占比0.33
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.33, random_state=42)
#打印出原始样本集、训练集和测试集的数目
print("The length of original data X is:", X.shape[0])
print("The length of train Data is:", X_train.shape[0])
print("The length of test Data is:", X_test.shape[0])
46、crosstab和pivotTab
【1】透视表(pivotTab)
透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数
# 透视表是将原有的DataFrame的列分别作为行索引和列索引,然后对指定的列应用聚集函数
import pandas as pd
df = pd.DataFrame({'类别':['水果','水果','水果','蔬菜','蔬菜','肉类','肉类'],
'产地':['美国','中国','中国','中国','新西兰','新西兰','美国'],
'水果':['苹果','梨','草莓','番茄','黄瓜','羊肉','牛肉'],
'数量':[5,5,9,3,2,10,8],
'价格':[5,5,10,3,3,13,20]})
print(pd.DataFrame(df))
'''
类别 产地 水果 数量 价格
0 水果 美国 苹果 5 5
1 水果 中国 梨 5 5
2 水果 中国 草莓 9 10
3 蔬菜 中国 番茄 3 3
4 蔬菜 新西兰 黄瓜 2 3
5 肉类 新西兰 羊肉 10 13
6 肉类 美国 牛肉 8 20
'''
print(df.pivot_table(index=['产地','类别']))
价格 数量
产地 类别
中国 水果 7.5 7
蔬菜 3.0 3
新西兰 肉类 13.0 10
蔬菜 3.0 2
美国 水果 5.0 5
肉类 20.0 8
【2】交叉表(crosstab)
用于统计分组频率的特殊透视表
print(df.pivot_table('价格',index='产地',columns='类别',aggfunc='max',margins=True,fill_value=0))
#行索引为"产地",列索引为'类别'
#对“价格”应用'max',并提供分项统计,缺失值填充0
'''
类别 水果 肉类 蔬菜 All
产地
中国 10 0 3 10
新西兰 0 13 3 13
美国 5 20 0 20
All 10 20 3 20
'''
print(pd.crosstab(df['类别'],df['产地'],margins=True))
'''
产地 中国 新西兰 美国 All
类别
水果 2 0 1 3
肉类 0 1 1 2
蔬菜 1 1 0 2
All 3 2 2 7
'''
47、使用函数处理DF当中的数据
【1】空格变成逗号
# 为分解firstprize定义函数
def fpp(x):
if len(x)<=2: # 判断是否只有汉字,还是也有数字
return "待定"
else: # 使用正则表达式获取中文
pattern="[\u4e00-\u9fa5]"
pat=re.compile(pattern)
return ''.join(pat.findall(x))
#使用fp()
ssqdatav2['fpprovince']=ssqdatav2['first'].apply(lambda x:fpp(x))
ssqdatav2.head(310)
48、全局变量、局部变量、类变量、实例变量
1、全局变量
2、局部变量
3、类变量
4、实例变量
5、变量命名
- 变量名可以使用字母、数字及下划线。
- 变量名不可使用数字开头,不可使用中文。
- 严格区分大小写,例如:A与a是不一样的变量名。
- 不可使用关键字作为变量名,例如:else,if,True,False等。
49、transpose()与.T()
在 NumPy 中,transpose() 和 .T 都用于数组的转置操作,但是它们有一些区别:
transpose()
是一个函数,需要以方法调用的形式使用,例如 arr.transpose(),并且可以接受表示维度顺序的元组作为参数,用于指定转置后的维度顺序。.T
是数组对象的属性,可以直接通过数组对象来调用,例如 arr.T,它会返回数组的转置,但不支持参数来指定维度顺序。
总的来说,transpose()
更灵活,可以指定转置后的维度顺序,而 .T
是一种简便的方式,用于获取数组的转置。
import numpy as np
arr=np.arange(16).reshape(2,2,4)
print('arr:')
print(arr)
print('arr.transpose:')
print(arr.transpose())
print('arr.transpose(2,1,0):')
print(arr.transpose(2,1,0))
print('arr.T:')
print(arr.T)
结果:
arr:
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 8 9 10 11]
[12 13 14 15]]]
arr.transpose:
[[[ 0 8]
[ 4 12]]
[[ 1 9]
[ 5 13]]
[[ 2 10]
[ 6 14]]
[[ 3 11]
[ 7 15]]]
arr.transpose(2,1,0):
[[[ 0 8]
[ 4 12]]
[[ 1 9]
[ 5 13]]
[[ 2 10]
[ 6 14]]
[[ 3 11]
[ 7 15]]]
arr.T:
[[[ 0 8]
[ 4 12]]
[[ 1 9]
[ 5 13]]
[[ 2 10]
[ 6 14]]
[[ 3 11]
[ 7 15]]]
从上面的例子中可以看出arr.transpose(), arr.T ,arr.transpose(2,1,0)的结果是相同的。现在我们详细看看transpose()带参数的情况,就会明白为什么arr.transpose(2,1,0)有这样的结果。
首先因为arr这个数组有三个维度,三个维度的编号对应为(0,1,2),假如我们需要拿到arr的7这个元素,肯定需要些三个维度的值,7的第一个维度为0,第二个维度为1,第三个3,所以arr[0,1,3] = 7。
再回到transpose()这个函数,它里面参数的顺序就是维度的顺序,比如transpose(2,1,0),就是把之前第三个维度转为第一个维度,之前的第二个维度不变,之前的第一个维度变为第三个维度,我们继续拿7这个值来说,之前的索引为[0,1,3],按照我们的转换方法,把之前的第三维度变为第一维度,之前的第一维度变为第三维度,那么现在7的索引就是(3,1,0)
同理所有的数组内的数字都是这样变得,这就是transpose()内参数的变化。
50、并发与并行的区别
并发和并行的主要区别在于:1.处理任务不同;2.存在不同;3.CPU资源不同;
一、处理任务不同
-
并发(Concurrent)
并发是一个CPU处理器同时处理多个线程任务
。(宏观上是同时处理多个任务,微观上其实是CPU在多个线程之间快速的交替执行CPU把运行时间划分成若干个(微小)时间段,公平的分配给各个线程执行,在一个时间段的线程运行时,其他线程处于挂起状态,这种就称之为并发。) -
并行(parallel)
并行是多个CPU处理器同时处理多个线程任务
。(当一个CPU执行一个线程时,另一个CPU可以执行另一个线程,两个线程互不抢占CPU资源,可以同时进行,这就被称之为并行。)
二、存在不同
-
并发(Concurrent)
并发可以在一个CPU处理器和多个CPU处理器系统中都存在。(多个CPU处理器系统其中的一个CPU也可以进行并发操作) -
并行(parallel)
并行在多个CPU处理器系统存在。
三、CPU资源不同
-
并发(Concurrent)
并发过程中,线程之间会去抢占CPU资源,轮流使用。(其实CPU会多个各个线程公平的分配时间片和进行执行。) -
并行(parallel)
并行过程中,线程间不会抢占CPU资源。(因为是多个CPU处理器,各做各的。)
51、Python迭代器与生成器
52、yield关键字
53、正则表达式当中的贪婪匹配和非贪婪匹配的区别
54、类和面向对象的区别
55、Python当中的异常
56、Python的class
1、类和方法的概念和实例
- 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
- 方法: 类中定义的函数。 类的构造方法__init__():类有一个名为 init() 的特殊方法(构造方法),该方法在类实例化时会自动调用。
- 实例变量: 在类的声明中,属性是用变量来表示的,这种变量就称为实例变量,实例变量就是一个用 self 修饰的变量。
通用格式:
class 类名:
类属性 = 值
def __init__(self, 参数):
self.属性1 = 参数1
self.属性2 = 参数2
def 方法1(self, 参数):
# 方法代码
def 方法2(self, 参数):
# 方法代码
- class 是声明类的关键字。
- init 是类的构造方法,当创建类的对象时,会自动调用这个方法。
- self 表示对象本身,其他参数就是对象的属性。 属性是类的成员变量,可以在类内部和外部使用。可以在类外使用类名访问类属性,如:类名.类属性。
- 方法是类的成员函数,接受的第一个参数是self,表示对象本身。在类内使用方法时,不需要传递这个参数。外部访问方法时,需要在对象后面加上方法名,如:对象.方法名()。
举例子:
class Dog:
# 类属性
species = '犬科'
# 构造方法
def __init__(self, name, age):
self.name = name
self.age = age
# 方法
def bark(self):
print("汪汪汪")
# 创建对象
dog1 = Dog('大黄', 2)
dog2 = Dog('二黄', 1)
# 访问属性
print(dog1.name)
print(dog2.age)
# 调用方法
dog1.bark()
(1)python类:class
python的class(类)相当于一个多个函数组成的家族,如果在这个Myclass
大家族里有一个人叫f,假如这个f具有print天气的作用,那么如果有一天我需要这个f来print一下今天的天气,那么我必须叫他的全名MyClass.f
才可以让他给我print,即在调用他的时候需要带上他的家族名称+他的名称。
- 属性:属性就是在这个类里的变量。如果变量是物品,那么不同的属性就是这个大家族里不同的物品
- 方法:方法就是在这个类里的函数。如果函数是人,那么不同的方法就是这个大家族里不同的人。
#Myclass家族,但是这个家族只有一个人f
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i) #家族x + 物品名i
print("MyClass 类的方法 f 输出为:", x.f()) #家族x + 人名f
- MyClass 类包含一个属性 i,它被赋值为 12345。
- 类中定义了一个方法 f,该方法接受一个参数 self,这个参数是类的实例。在 Python 中,类的方法的第一个参数通常是 self,表示实例本身。
- f 方法返回字符串 ‘hello world’。
运行程序会报错:MyClass.f() takes 0 positional arguments but 1 was given
意思是:MyClass.f() 这个函数不需要参数,但是函数却被传递了一个参数,可是我们调用MyClass.f()函数的时候,并没有写参数,为什么会出现这样的Error呢?
这是因为 “每个与类相关联的方法调用都自动传递实参self , 它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。”
init中的参数self会自动传递给MyClass.f(),而MyClass.f()在定义的时候没有形参,就会报错。
修改方法:def f(): 改为 def f(self):
(2)类的构造方法__init__()
假如init()也是人,但是他是家族和外界联络员,当外界的人想调用自己家族的人,就必须要先告诉他,所以只要家族的人被调用,那么init()就会被先执行,然后由他去告诉那个被调用的人,执行被调用的。
class Complex:
def __init__(self, realpart, imagpart): #必须要有一个self参数,
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
(3)类中方法的参数self
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self, 且为第一个参数,self代表的是类的实例。
- self:类的方法与普通的函数只有一个特别的区别——必须有一个额外的第一个参数名称, 按照惯例它的名称是self。
- 类的实例: 是将类应用在实例场景之中,比如有个类里的函数是f,假如这个f具有print某一时刻的天气状况的能力,那么如果我需要这个f来print一下今天12点的天气,那么让他打印今天12点的天气这个动作,就是类的实例化,让类中的函数具有的能力变成真实的动作。
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
#定义构造方法
def __init__(self,n,a):
self.name = n
self.age = a
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('Susie',10)
p.speak()
(4)继承
假如有两个家族,有一个家族A开始没落了,另一个新兴的家族B想继承A家族的物资和佣人,那么就可以通过如下的方式实现继承,在这里,家族A即是父类,家族B是子类。在用法上,如果B家族可以任意使用A家族的物品和佣人。
class [子类]([父类]):
- BaseClassName(示例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用。
- python还支持多继承,即可以继承多个父类。继承方式和单继承方式一样,方式如下:
class [子类]([父类]1, [父类]2, [父类]3):
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people): #student为子类,people为父类
grade = ''
def __init__(self,n,a,g,w):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,3,60)
s.speak()
在Python中,使用双下划线(__)
作为前缀可以将属性设置为私有属性。但需要注意的是,Python中的私有属性并不是绝对安全的,因为可以通过一些特殊的方式来访问它们。然而,这种机制足够用于大多数情况下的封装需求。
- 由于
__weight
是私有属性,因此不能直接调用,而且直接在子类中使用super().__weight
也是不允许的,因为私有属性不能直接在类外部或子类中访问。要访问父类的私有属性,可以有以下几种方法:
方法一:使用Getter和Setter方法
可以在父类中定义一个公有的Getter方法用于获取私有属性的值,并在需要的时候定义Setter方法用于修改私有属性的值。子类可以通过调用这些方法来访问和修改私有属性。
class people:
# ... 其他代码 ...
def get_weight(self):
return self.__weight
def set_weight(self, weight):
self.__weight = weight
在子类中调用:
super().set_weight(new_weight)
weight = super().get_weight()
(5)方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法。即如果B家族继承了A家族,但是B家族有个佣人只会扫地,于是A家族给这个人洗脑,让他啥都不会,然后再教这个佣人洗碗、擦桌子的技能,那么这个佣人就只会洗碗和擦桌子了。
- super()函数是用于调用父类(超类)的一个方法。
class Parent: # 定义父类
def myMethod(self):
print('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
2、类的特殊属性与方法
(1)类的私有属性
类的私有属性
_private_attrs
:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时self.__private_attrs
。
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print(counter.publicCount)
print(counter.__secretCount) # 报错,实例不能访问私有变量
如果想访问实例变量,可以采用getter方法
(2)类的私有方法
__private_method
:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__private_methods。
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('Python', 'www.irvingao.com')
x.who() # 正常输出
x.foo() # 正常输出
x.__foo() # 报错
虽然不推荐在外部直接访问私有方法,但仍然可以通过以下方式调用:
class Site:
def __init__(self, name, url):
self.name = name # public
self.__url = url # private
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self): # 公共方法
print('这是公共方法')
self.__foo()
x = Site('Python', 'www.irvingao.com')
x.who() # 正常输出
x.foo() # 正常输出
# 访问私有方法的方式
x._Site__foo() # 输出 '这是私有方法'
请注意,这种方式不是Python的官方推荐做法,因为它违反了封装的原则。私有方法和属性是意图在类的内部使用的,而不应该在外部直接访问。如果有必要,可以考虑提供公共方法来间接调用私有方法。
3、Python装饰器
57、if name == ‘main’
if __name__ == '__main__':
是 Python 中常见的用法,它的作用是判断当前模块是否是作为主程序执行的,或者是被其他模块导入的。当一个 Python 文件被直接执行时,name 的值会被设置为 ‘main’,因此这段代码的意思是:如果当前模块是作为主程序执行的话,就执行下面的代码块。
而 app.run() 是 Flask 框架中用于启动 Web 应用程序的方法,它会启动一个本地的服务器,以便用户可以通过浏览器访问应用程序。
因此,这段代码的作用是当当前模块被直接执行时,启动 Flask 应用程序。