Python数据分析
Posted 雨宙
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python数据分析相关的知识,希望对你有一定的参考价值。
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)
# 0.3191087245941162
t3 = time.time()
b = np.arange(1000000)**2
t4 = time.time()
print(t4-t3)
# 0.006983041763305664
数组的创建方式
- numpy中的数组和Python中的列表的区别:
(1)一个列表中可以存储多种数据类型,而数组只能存储同种数据类型
(2)数组可以是多维的,当多维数组中的所有的数据都是数值类型的时候,相当于线性代数中的矩阵,是可以进行相互间的运算的 - 创建数组的四种方式:
(1)使用np.array来创建
(2)使用np.arange来创建一个区间的数组
(3)使用np.random模块来创建
(4)使用np上面的一些特殊函数来创建
import numpy as np
# 使用np.array创建数组
a1 = np.array([1,2,3,4])
print(a,type(a))
# [1 2 3] <class 'numpy.ndarray'>
# 使用np.arange创建数组
a2 = np.arange(10)
print(a2)
# [0 1 2 3 4 5 6 7 8 9]
a3 = np.arange(0,10,2)
print(a3)
# [0 2 4 6 8]
# 使用np.random.random来创建一个N行N列的数组,其中里面的值是0-1之间的随机数
a4 = np.random.random((2,2))
print(a4)
# [[0.37701883 0.5439565 ]
# [0.23671606 0.54575213]]
# 使用np.random.randint来创建一个N行N列的数组,其中值的范围可以通过前面2个参数来指定
a5 = np.random.randint(0,9,size=(3,3))
print(a5)
# [[0 8 1]
# [2 8 7]
# [0 5 6]]
# 特殊函数
b = np.zeros((3,3))
print(b)
# [[0. 0. 0.]
# [0. 0. 0.]
# [0. 0. 0.]]
b1 = np.ones((4,4))
print(b1)
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
b2 = np.full((2,3),4)
print(b2)
# [[4 4 4]
# [4 4 4]]
b3 = np.eye(3)
print(b3)
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
数组的数据类型
- 数据类型多:基于C语言编写,C语言中有很多数据类型,直接引用过来,而且为了考虑处理海量数据的性能,针对不同的数据给不同的数据类型,来节省内存空间
- 具体数据类型分类
a = np.arange(9)
print(a)
print(a.dtype)
# [0 1 2 3 4 5 6 7 8]
# int32
b = np.array([1,2,3,4],dtype=np.int8)
print(b)
print(b.dtype)
# [1 2 3 4]
# int8
c = np.array([1,2,3,4],dtype=np.float16)
print(c)
print(c.dtype)
# [1. 2. 3. 4.]
# float16
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)
# [<__main__.Person object at 0x000001DE69ACF130>
# <__main__.Person object at 0x000001DE69ACF460>]
# object
- 数据类型转换 ndarray.astype
# 类型转换
f = np.array(['a','b'],dtype='S')
print(f)
print(f.dtype)
uf = f.astype('U')
print(uf)
print(uf.dtype)
# [b'a' b'b']
# |S1
# ['a' 'b']
# <U1
多维数组及其简单操作
- 一般把三维以上的数组转化为二维计算
- 通过ndarray.ndim可以看到数组的维度
# 数组的维数
a1 = np.array([1,2,3])
print(a1.ndim) # 1
a2 = np.array([[1,2,3],[4,5,6]])
print(a2.ndim) # 2
a3 = np.array([
[
[1,2,3],
[4,5,6]
],
[
[7,8,9],
[10,11,12]
]
])
print(a3.ndim) # 3
- 通过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)
# [[ 1 2 3 4 5 6]
# [ 7 8 9 10 11 12]]
a5 = a3.reshape((12,))
a5 = a3.flatten() # 扁平化
print(a5)
# [ 1 2 3 4 5 6 7 8 9 10 11 12]
- 通过ndarray.size可以看到数组总共有多少个元素
count = a3.size
print(count) #12
- 通过ndarray.itemsize可以看到数组中每个元素所占内存的大小,单位是字节(1个字节=8位)
# 获取每一个元素所占的字节大小
itemsize = a3.itemsize
print(itemsize) #4
数组的索引和切片
- 如果数组是一维的,那么索引和切片就是跟python的列表是一样的。
# 一维数组索引和切片
a1 = np.arange(10)
print(a1[4])
print(a1[4:6])
print(a1[::2])
print(a1[-1])
# 4
# [4 5]
# [0 2 4 6 8]
# 9
- 如果是多维的(这里以二维为例),那么在中括号中,给两个值,两个值是通过逗号分隔的,逗号前面的是行,逗号后面的是列。如果中括号中只有一个值,那么就是代表的是行。
- 如果是多维数组(这里以二维为例),那么行的部分和列的部分,都是遵循一维数组的方式,可以使用整形,切片,还可以使用中括号的形式,来代表不连续的。比如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]) # 获取第一列数据
# [[9 8 2 7 8 1]
# [6 1 1 1 2 7]
# [2 3 3 6 7 6]
# [4 0 5 8 0 2]]
# [9 8 2 7 8 1]
# [[9 8 2 7 8 1]
# [6 1 1 1 2 7]]
# [[9 8 2 7 8 1]
# [2 3 3 6 7 6]
# [4 0 5 8 0 2]]
# 1
# [2 6]
# [[2 7]
# [7 6]]
# [8 1 3 0]
布尔索引
- 布尔索引是通过相同数组上的True还是False进行提取的,提取的条件可有多个,用&表示且,用|表示或,如果有多个条件,每个条件要使用圆括号括起来
a2 = np.arange(24).reshape((4,6))
print(a2)
print(a2 < 10)
print(a2[a2 < 10])
print(a2[(a2 < 5) & (a2 > 1)])
# [[ 0 1 2 3 4 5]
# [ 6 7 8 9 10 11]
# [12 13 14 15 16 17]
# [18 19 20 21 22 23]]
# [[ True True True True True True]
# [ True True True True False False]
# [False False False False False False]
# [False False False False False False]]
# [0 1 2 3 4 5 6 7 8 9]
# [2 3 4]
数组值的替换
- 可以使用索引或切片来替换
a3 = np.random.randint(0,10,size=(3,5))
print(a3)
a3[1] = np.array([1,2,3,4,5])
print(a3)
# [[5 6 9 6 1]
# [2 0 3 8 8]
# [0 0 1 0 0]]
# [[5 6 9 6 1]
# [1 2 3 4 5]
# [0 0 1 0 0]]
- 可以使用条件索引来替换
a3[ a3 < 3] = 1
print(a3)
# [[5 6 9 6 1]
# [1 1 3 4 5]
# [1 1 1 1 1]]
- 使用where函数实现
res = np.where(a3 < 5, 0 , 1)
print(res)
# [[1 1 1 1 0]
# [0 0 0 0 1]
# [0 0 0 0 0]]
数组的广播机制
- 数组和数字直接进行运算是可以的
a1 = np.random.randint(0,5,size=(3,5))
print(a1)
print(a1*2)
# [[3 3 0 0 4]
# [4 3 1 0 2]
# [1 3 2 3 0]]
# [[6 6 0 0 8]
# [8 6 2 0 4]
# [2 6 4 6 0]]
- 两个shape相同的数组是可以进行运算的
a2 = np.random.randint(0,5,size=(3,5))
print(a2)
print(a1+a2)
# [[2 2 4 0 0]
# [0 1 2 2 2]
# [2 2 4 0 3]]
# [[5 5 4 0 4]
# [4 4 3 2 4]
# [3 5 6 3 3]]
- 如果两个shape不同的数组,想要进行运算,那么需要看他们是否满足广播原则
a3 = np.random.randint(0,5,size=(3,4))
a4 = np.random.randint(0,5,size=(3,1))
print(a4)
print(a1+a4)
# [[3]
# [4]
# [1]]
# [[6 6 3 3 7]
# [8 7 5 4 6]
# [2 4 3 4 1]]
- 广播原则:如果两个数组的后缘维度(即从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为他们是广播兼容的,广播会在缺失和(或)长度为1的维度上进行
数组形状操作
reshape、resize、flatten、ravel
- reshape和resize都是重新定义形状的。但是reshape不会修改数组本身,而是将修改后的结果返回回去,而resize是直接修改数组本身的。
a1 = np.random.randint(0,10,size=(3,4))
print(a1)
# [[0 6 0 9]
# [0 3 6 9]
# [5 5 3 6]]
a2 = a1.reshape((2,6))
print(a2)
# [[0 6 0 9 0 3]
# [6 9 5 5 3 6]]
print(a1)
# [[0 6 0 9]
# [0 3 6 9]
# [5 5 3 6]]
a1.resize((4,3))
print(a1)
# [[0 6 0]
# [9 0 3]
# [6 9 5]
# [5 3 6]]
- flatten和ravel都是用来将数组边成一维数组的,并且他们都不会对原数组造成修改,但是flatten返回的是一个拷贝,所以对flatten的返回值的修改不会影响到原来数组,而ravel返回的是一个View,那么对返回值的修改会影响到原来数组的值。
a2 = np.random.randint(0,10,size=(3,4))
print(a2)
# [[5 7 6 4]
# [6 8 1 7]
# [5 7 6 2]]
print(a2.flatten())
# [5 7 6 4 6 8 1 7 5 7 6 2]
print(a2)
# [[5 7 6 4]
# [6 8 1 7]
# [5 7 6 2]]
print(a2.ravel())
# [5 7 6 4 6 8 1 7 5 7 6 2]
print(a2)
# [[5 7 6 4]
# [6 8 1 7]
# [5 7 6 2]]
a3 = a2.flatten()
a4 = a2.ravel()
a3[0] = 100
print(a2)
# [[5 7 6 4]
# [6 8 1 7]
# [5 7 6 2]]
a4[0] = 100
print(a2)
# [[100 7 6 4]
# [ 6 8 1 7]
# [ 5 7 6 2]]
数组的叠加
- hstack代表在水平方向叠加,如果想要叠加成功,那么他们的行必须一致。
h1 = np.random.randint(0,10,size=(3,4))
print(h1)
h2 = np.random.randint(0,10,size=(3,2))
print(h2)
# [[5 1 3 0]
# [0 0 3 5]
# [8 1 7 6]]
# [[8 4]
# [5 6]
# [1 8]]
h3 = np.hstack([h1,h2])
print(h3)
# [[5 1 3 0 8 4]
# [0 0 3 5 5 6]
# [8 1 7 6 1 8]]
- vstack代表在垂直方向叠加,如果想要叠加成功,那么他们的列必须一致。
vstack1 = np.random.randint(0,10,size=(3,4))
print(vstack1)
vstack2 = np.random.randint(0,10,size=(2,4))
print(vstack2)
# [[3 5 0 3]
# [2 5 7 3]
# [6 2 8 0]]
# [[1 1 4 2]
# [1 3 9 6]]
vstack3 = np.vstack([vstack1,vstack2])
print(vstack3)
# [[3 5 0 3]
# [2 5 7 3]
# [6 2 8 0]
# [1 1 4 2]
# [1 3 9 6]]
- concatenate可以手动的指定axis参数具体在哪个方向叠加,如果axis=0,代表在垂直方向叠加,如果axis=1,代表在水平方向叠加,如果axis=None,那么会先进行叠加,再转换成1维数组。
v3 = np.concatenate([vstack1,vstack2],axis=0)
print(v3)
# [[3 5 0 3]
# [2 5 7 3]
# [6 2 8 0]
# [1 1 4 2]
# [1 3 9 6]]
h3 = np.concatenate([h1,h2],axis=1)
print(h3)
# [[5 1 3 0 8 4]
# [0 0 3 5 5 6]
# [8 1 7 6 1 8]]
h4 = np.concatenate([h1,h2],axis=None)
print(h4)
# [5 1 3 0 0 0 3 5 8 1 7 6 8 4 5 6 1 8]
数组切割
- hsplit代表在水平方向切割,按列进行切割的。他的切割方式有两种,第一种就是直接指定平均切割成多少列,第二种就是指定切割的下标值。
hs1 = np.random.randint(0,10,size=(3,4))
print(hs1)
# [[8 4 2 1]
# [5 6 2 1]
# [6 5 7 0]]
np.hsplit(hs1,2)
# [array([[8, 4],
# [5, 6],
# [6, 5]]),
# array([[2, 1],
# [2, 1],
# [7, 0]])]
np.hsplit(hs1,(1,2))
# [array([[8],
# [5],
# [6]]),
# array([[4],
# [6],
# [5]]),
# array([[2, 1],
# [2, 1],
# [7, 0]])]
- vsplit代表在垂直方向切割,按行进行切割。他的切割方式跟hsplit是一样的。
vs1 = np.random.randint(0,10,size=(4,5))
print(vs1)
# [[8 7 6 7 9]
# [1 9 2 5 9]
# [4 9 2 2 8]
# [8 6 4 4 1]]
np.vsplit(vs1,4)
# [array([[8, 7, 6, 7, 9]]),
# array([[1, 9, 2, 5, 9]]),
# array([[4, 9, 2, 2, 8]]),
# array([[8, 6, 4, 4, 1]])]
np.vsplit(vs1,(1,3))
# [array([[8, 7, 6, 7, 9]]),
# array([[1, 9, 2, 5, 9],
# [4, 9, 2, 2, 8]]),
# array([[8, 6, 4, 4, 1]])]
- split/array_split是手动的指定axis参数,axis=0,代表按行进行切割,axis=1,代表按列进行切割。
np.split(hs1,4,axis=1)
# [array([[8],
# [5],
# [6]]),
# array([[4],
# [6],
# [5]]),
# array([[2],
# [2],
# [7]]),
# array([[1],
# [1],
# [0]])]
np.split(vs1,4,a以上是关于Python数据分析的主要内容,如果未能解决你的问题,请参考以下文章