Python数据分析(一)
打卡第五天啦!!!
Numpy库(一)
介绍
- 功能强大的Python库,主要用于对多维数组执行计算
- 非常高效的用于处理数值型运算的包
- 通过pip install numpy安装
- numpy数组和Python列表性能对比
import numpy as np
import time
t1 = time.time()
a = []
for x in range(1000000):
a.append(x**2)
pass
t2 = time.time()
print(t2-t1)
t3 = time.time()
b = np.arange(1000000)**2
t4 = time.time()
print(t4-t3)
数组的创建方式
- numpy中的数组和Python中的列表的区别:
(1)一个列表中可以存储多种数据类型,而数组只能存储同种数据类型 (2)数组可以是多维的,当多维数组中的所有的数据都是数值类型的时候,相当于线性代数中的矩阵,是可以进行相互间的运算的 - 创建数组的四种方式:
(1)使用np.array来创建 (2)使用np.arange来创建一个区间的数组 (3)使用np.random模块来创建 (4)使用np上面的一些特殊函数来创建
import numpy as np
a1 = np.array([1,2,3,4])
print(a,type(a))
a2 = np.arange(10)
print(a2)
a3 = np.arange(0,10,2)
print(a3)
a4 = np.random.random((2,2))
print(a4)
a5 = np.random.randint(0,9,size=(3,3))
print(a5)
b = np.zeros((3,3))
print(b)
b1 = np.ones((4,4))
print(b1)
b2 = np.full((2,3),4)
print(b2)
b3 = np.eye(3)
print(b3)
数组的数据类型
- 数据类型多:基于C语言编写,C语言中有很多数据类型,直接引用过来,而且为了考虑处理海量数据的性能,针对不同的数据给不同的数据类型,来节省内存空间
- 具体数据类型分类
a = np.arange(9)
print(a)
print(a.dtype)
b = np.array([1,2,3,4],dtype=np.int8)
print(b)
print(b.dtype)
c = np.array([1,2,3,4],dtype=np.float16)
print(c)
print(c.dtype)
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
pass
d = np.array([Person('潘小雷',20),Person('鲸鱼',20)])
print(d)
print(d.dtype)
- 数据类型转换 ndarray.astype
f = np.array(['a','b'],dtype='S')
print(f)
print(f.dtype)
uf = f.astype('U')
print(uf)
print(uf.dtype)
多维数组及其简单操作
- 一般把三维以上的数组转化为二维计算
- 通过ndarray.ndim可以看到数组的维度
a1 = np.array([1,2,3])
print(a1.ndim)
a2 = np.array([[1,2,3],[4,5,6]])
print(a2.ndim)
a3 = np.array([
[
[1,2,3],
[4,5,6]
],
[
[7,8,9],
[10,11,12]
]
])
print(a3.ndim)
- 通过ndarray.shape可以看到数组的形状(几行几列),shape是一个元组,里面有几个元素代表是几维数组
a1 = np.array([1,2,3])
print(a1.shape)
a2 = np.array([[1,2,3],[4,5,6]])
print(a2.shape)
a3 = np.array([
[
[1,2,3],
[4,5,6]
],
[
[7,8,9],
[10,11,12]
]
])
print(a3.shape)
- 通过ndarray.reshape可以修改数组的形状,条件只有一个,就是修改后的形状的元素个数必须与原来的个数一致。不会修改原来数组的形状,只会将修改后的结果返回
a4 = a3.reshape((2,6))
print(a4)
a5 = a3.reshape((12,))
a5 = a3.flatten()
print(a5)
- 通过ndarray.size可以看到数组总共有多少个元素
count = a3.size
print(count)
- 通过ndarray.itemsize可以看到数组中每个元素所占内存的大小,单位是字节(1个字节=8位)
itemsize = a3.itemsize
print(itemsize)
数组的索引和切片
- 如果数组是一维的,那么索引和切片就是跟python的列表是一样的。
a1 = np.arange(10)
print(a1[4])
print(a1[4:6])
print(a1[::2])
print(a1[-1])
- 如果是多维的(这里以二维为例),那么在中括号中,给两个值,两个值是通过逗号分隔的,逗号前面的是行,逗号后面的是列。如果中括号中只有一个值,那么就是代表的是行。
- 如果是多维数组(这里以二维为例),那么行的部分和列的部分,都是遵循一维数组的方式,可以使用整形,切片,还可以使用中括号的形式,来代表不连续的。比如a[[1,2],[3.4]],那么返回的就是(1,3),(2,4)的两个值。
a2 = np.random.randint(0,10,size=(4,6))
print(a2)
print(a2[0])
print(a2[0:2])
print(a2[[0,2,3]])
print(a2[1,1])
print(a2[[1,2],[4,5]])
print(a2[1:3,4:6])
print(a2[:,1])
布尔索引
- 布尔索引是通过相同数组上的True还是False进行提取的,提取的条件可有多个,用&表示且,用|表示或,如果有多个条件,每个条件要使用圆括号括起来
a2 = np.arange(24).reshape((4,6))
print(a2)
print(a2 < 10)
print(a2[a2 < 10])
print(a2[(a2 < 5) & (a2 > 1)])
数组值的替换
- 可以使用索引或切片来替换
a3 = np.random.randint(0,10,size=(3,5))
print(a3)
a3[1] = np.array([1,2,3,4,5])
print(a3)
- 可以使用条件索引来替换
a3[ a3 < 3] = 1
print(a3)
- 使用where函数实现
res = np.where(a3 < 5, 0 , 1)
print(res)
数组的广播机制
- 数组和数字直接进行运算是可以的
a1 = np.random.randint(0,5,size=(3,5))
print(a1)
print(a1*2)
- 两个shape相同的数组是可以进行运算的
a2 = np.random.randint(0,5,size=(3,5))
print(a2)
print(a1+a2)
- 如果两个shape不同的数组,想要进行运算,那么需要看他们是否满足广播原则
a3 = np.random.randint(0,5,size=(3,4))
a4 = np.random.randint(0,5,size=(3,1))
print(a4)
print(a1+a4)
- 广播原则:如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为他们是广播兼容的,广播会在缺失和(或)长度为1的维度上进行
数组形状操作
reshape、resize、flatten、ravel
- reshape和resize都是重新定义形状的。但是reshape不会修改数组本身,而是将修改后的结果返回回去,而resize是直接修改数组本身的。
a1 = np.random.randint(0,10,size=(3,4))
print(a1)
a2 = a1.reshape((2,6))
print(a2)
print(a1)
a1.resize((4,3))
print(a1)
- flatten和ravel都是用来将数组边成一维数组的,并且他们都不会对原数组造成修改,但是flatten返回的是一个拷贝,所以对flatten的返回值的修改不会影响到原来数组,而ravel返回的是一个View,那么对返回值的修改会影响到原来数组的值。
a2 = np.random.randint(0,10,size=(3,4))
print(a2)
print(a2.flatten())
print(a2)
print(a2.ravel())
print(a2)
a3 = a2.flatten()
a4 = a2.ravel()
a3[0] = 100
print(a2)
a4[0] = 100
print(a2)
数组的叠加
- hstack代表在水平方向叠加,如果想要叠加成功,那么他们的行必须一致。
h1 = np.random.randint(0,10,size=(3,4))
print(h1)
h2 = np.random.randint(0,10,size=(3,2))
print(h2)
h3 = np.hstack([h1,h2])
print(h3)
- vstack代表在垂直方向叠加,如果想要叠加成功,那么他们的列必须一致。
vstack1 = np.random.randint(0,10,size=(3,4))
print(vstack1)
vstack2 = np.random.randint(0,10,size=(2,4))
print(vstack2)
vstack3 = np.vstack([vstack1,vstack2])
print(vstack3)
- concatenate可以手动的指定axis参数具体在哪个方向叠加,如果axis=0,代表在垂直方向叠加,如果axis=1,代表在水平方向叠加,如果axis=None,那么会先进行叠加,再转换成1维数组。
v3 = np.concatenate([vstack1,vstack2],axis=0)
print(v3)
h3 = np.concatenate([h1,h2],axis=1)
print(h3)
h4 = np.concatenate([h1,h2],axis=None)
print(h4)
数组切割
- hsplit代表在水平方向切割,按列进行切割的。他的切割方式有两种,第一种就是直接指定平均切割成多少列,第二种就是指定切割的下标值。
hs1 = np.random.randint(0,10,size=(3,4))
print(hs1)
np.hsplit(hs1,2)
np.hsplit(hs1,(1,2))
- vsplit代表在垂直方向切割,按行进行切割。他的切割方式跟hsplit是一样的。
vs1 = np.random.randint(0,10,size=(4,5))
print(vs1)
np.vsplit(vs1,4)
np.vsplit(vs1,(1,3))
- split/array_split是手动的指定axis参数,axis=0,代表按行进行切割,axis=1,代表按列进行切割。
np.split(hs1,4,axis=1)
np.split(vs1,4,axis=0)
转置
- 可以通过ndarray.T的形式进行转置
t1 = np.random.randint(0,10,size=(3,4))
print(t1)
t1.T
t1.dot(t1.T)
- 可以通过ndarray.transpose()进行转置,这个方法返回的是一个view,所以对返回值上进行修改,会影响到原来的数组
t1.transpose()
t1.transpose()[0] = 100
print(t1)
数组的浅拷贝和深拷贝
- 不拷贝,直接赋值,那么栈区没有拷贝,只是用同一个栈区定义了不同的名称
a = np.arange(10)
b = a
print(b is a)
- 浅拷贝,只拷贝栈区,栈区指定的堆区并没有拷贝
a = np.arange(10)
c = a.view()
print(c is a)
c[0] = 100
print(a)
- 深拷贝,栈区和堆区都拷贝了
a = np.arange(10)
d = a.copy()
print(d is a)
d[0] = 100
print(a)
文件操作
csv文件操作
scores = np.random.randint(0,100,size=(20,2))
print(scores)
np.savetxt("scores.csv",scores,delimiter=",",header='英语,数学',comments='',fmt='%d')
b = np.loadtxt("scores.csv",dtype=np.int,delimiter=",",skiprows=1)
print(b)
save和load方式
- np. savetxt和np.loadtxt一般用来操作csv文件,他可以设置header,但是不能存储3维以上的数组。
- np. save和np.load一般用来存储非文本类型的文件,他不可以设置header,但是可以存储3维以上的数组。
- 如果想专门的操作CSV文件,其实还有另外一个模块叫做csv,这个模块是python内置的,不需要安装。
d = np.random.randint(0,10,size=(2,3,4))
np.save("d",d)
d1 = np.load("d.npy")
print(d1)
|