numpy---python数据分析

在这里插入图片描述

最后大图可点开保存

学习目标

  • 目标
    • 了解Numpy运算速度上的优势
    • 知道Numpy的数组内存块风格
    • 知道Numpy的并行优化运算
  • 应用
    • 机器学习,深度学习各种框架的基础库
  • 内容预览
    • 3.1.1 Numpy介绍
    • 3.1.2 ndarray介绍
    • 3.1.3 ndarray与python原生list运算效率对比
    • 3.1.4 ndarray的优势

3.1.1Numpy介绍

num - numerical
py - python
numpy - numerical python
Numpy是一个开源的Python科学计算库,用于快速处理任意维度的数组。
Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器
ndarray:
n - 任意个
d - dimension 维度
array - 数组

3.1.2 ndarray介绍

Numpy提供了一个N维数组类型ndarray,它描述了相同类型的"items"的集合。
在这里插入图片描述
使用ndarray进行存储:

import numpy as np

# 创建ndarray
score = np.array([[80, 89, 86, 67, 79],
                 [78, 97, 89, 67, 81],
                 [90, 94, 78, 67, 74],
                 [91, 91, 90, 67, 69],
                 [76, 87, 75, 67, 86],
                 [70, 79, 84, 67, 84],
                 [94, 92, 93, 67, 84],
                 [86, 85, 83, 67, 80]])

使用Python列表可以存储一维数组,通过列表的嵌套可以实现多维数组,那么为什么还需要使用Numpy的ndarray呢?

3.1.3 ndarray与Python原生list运算效率对比

import random
import time
import numpy as np


a = []
for i in range(100000000):  # 随机生成一亿个数字
    a.append(random.random())
t1 = time.time()
sum1 = sum(a)
t2 = time.time()

b = np.array(a)
t4 = time.time()
sum2 = np.sum(b)
t5 = time.time()
print(t2-t1, t5-t4)
 # 0.9411723613739014   0.18763375282287598

从中我们可以看出ndarray的计算速度要快很多,节约了时间。

机器学习的最大特点:就是大量的数据运算,那么如果没有一个快速的解决方案,那可能现在python也在机器学习领域达不到好的效果。

3.1.4 ndarray的优势

  • 内存块存储风格

ndarray ; 元素相同类型 ; 通用性不强, 元素在内存中连续。

list ; 元素不同类型 ; 通用性很强, 元素在内存中不一定连续,如列表中还有个字典

  • 并行化运算(向量化运算)

不需要循环,直接向量化运算,同时计算。

  • 底层语言

Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,效率远高于纯Python代码。

3.2 认识N维数组 -ndarray属性

3.2.1 ndarray的属性

数组属性反映了数组本身固有的信息:

属性名字 属性解释
ndarray.shape 数组维度的元组
ndarray.ndim 数组维数
ndarray.size 数组中的元素数量
ndarray.dtype 数组元素的类型
ndarray.itemsize 一个数组元素的长度(字节)

最重要的两个属性是shapedtype

当我们知道了形状shap即维度的时候,我们就可以知道维数ndim、数组的元素个数(数组大小)size

当我们知道数组中的元素的类型的时候,我们就可以知道一个数组元素的长度itemsize,因为不同类型的元素在内存中的占用是固定的。

示例:

score = np.array([[80, 89, 86, 67, 79],
                 [78, 97, 89, 67, 81],
                 [90, 94, 78, 67, 74],
                 [91, 91, 90, 67, 69],
                 [76, 87, 75, 67, 86],
                 [70, 79, 84, 67, 84],
                 [94, 92, 93, 67, 84],
                 [86, 85, 83, 67, 80]])
# 整个数组
print(score.shape)  # (8, 5) 
print(score.ndim)  # 2  二维
print(score.size)  # 40  数组元素个数
# 单个元素
print(score.dtype)  # int32 元素的类型
print(score.itemsize) # 4  元素大小

3.2.2 ndarray的形状

a = np.array([[1, 2, 3], [4, 5, 6]])
a.shape  # (2, 3)

b = np.array([1, 2, 3, 4])
b.shape  # (4, )

c = np.array([[[1, 2, 3], [4, 5, 6]], [[1, 2, 3], [4, 5, 6]]])
c.shape  # (2, 2, 3)
# shape先看第一个中括号内几个部分,再看第二个中括号....

3.2.3 ndarray元素类型

  • 默认:
    • 整数 int64
    • 小数 float64
  • 创建数组的时候指定类型
np.array([1.1, 1.2, 1.3], dtype="float32")
np.array([1.1, 1.2, 1.3], dtype=float32)
# 两种方式是等价的

3.3 基本操作

学习目标

  • 目标
    • 理解数组的各种生成方法;
    • 应用数组的索引机制实现数组的切片获取
    • 应用维度变换实现数组的形状改变
    • 应用类型变换实现数组类型改变
    • 应用数组的转换
  • 应用
    • 应用正态分布实现模拟股票的涨跌幅数据操作
  • 内容预览
    • 3.3.1 生成数组的方法
      • 1 生成0和1的数组
      • 2 从现有数组生成
      • 3 生成固定范围的数组
      • 4 生成随机数组
    • 3.3.2 数组的索引、切片
    • 3.3.3 形状修改
    • 3.3.4 类型修改
    • 3.3.5 数组的去重

3.3.1 生成数组的方法

1 生成0和1的数组

生成这样的数组的方式有很多,没有必要全都记住,这里推荐ones方法和zeros方法:

np.zeros(shape=(3, 4), dtype="float32")
np.ones(shape=[2, 3], dtype=int32)
# 列表和元素表示都可以

2从现有数组中生成

有array、asarray、copy几种方法:

score = np.array([[80, 89, 86, 67, 79],
                 [78, 97, 89, 67, 81],
                 [90, 94, 78, 67, 74],
                 [91, 91, 90, 67, 69],
                 [76, 87, 75, 67, 86],
                 [70, 79, 84, 67, 84],
                 [94, 92, 93, 67, 84],
                 [86, 85, 83, 67, 80]])
                 
data1 = np.array(score)
print(data1)
'''array([[80, 89, 86, 67, 79],
                 [78, 97, 89, 67, 81],
                 [90, 94, 78, 67, 74],
                 [91, 91, 90, 67, 69],
                 [76, 87, 75, 67, 86],
                 [70, 79, 84, 67, 84],
                 [94, 92, 93, 67, 84],
                 [86, 85, 83, 67, 80]])'''

data2 = np.asarray(score)
print(data2)
'''array([[80, 89, 86, 67, 79],
                 [78, 97, 89, 67, 81],
                 [90, 94, 78, 67, 74],
                 [91, 91, 90, 67, 69],
                 [76, 87, 75, 67, 86],
                 [70, 79, 84, 67, 84],
                 [94, 92, 93, 67, 84],
                 [86, 85, 83, 67, 80]])'''
                 
data2 = np.copy(score)
print(data2)
'''array([[80, 89, 86, 67, 79],
                 [78, 97, 89, 67, 81],
                 [90, 94, 78, 67, 74],
                 [91, 91, 90, 67, 69],
                 [76, 87, 75, 67, 86],
                 [70, 79, 84, 67, 84],
                 [94, 92, 93, 67, 84],
                 [86, 85, 83, 67, 80]])'''

但是这三个是有区别的:array和copy是深拷贝; asarray是浅拷贝。

3生成固定范围的数组

有np.linspace()和np.arange()方法;

  • np.linspace(0, 10, 100)
    生成[0, 10]等距离的100个
data = np.linspace(0, 10, 6)  # 等分生成6个
print(data)
# [ 0.  2.  4.  6.  8. 10.]
  • np.arange(a, b, c)
    和range是一样的
data2 = np.arange(0, 10, 6) # 步长是6
print(data2)  # [0, 6]

生成随机数

  • np.random
  • np.random.uniform(low=0, high=1, size=None)
  • 均匀分布(Uniform Distribution)
    是概率论统计中的重要分布之一。顾名思义,均匀,表示可能性相等的含义。均匀分布在自然情况下极为罕见,而人工栽培的有一定株行距的植物群落是均匀分布。
# 生成均匀分布的随机数
x1 = np.random.uniform(-1, 1, 1000)

# 返回结果
print(x1)
[ 0.56347276 -0.94591979 -0.23197083  ... -0.79391627 -0.32959637]


# 这里用直方图来表示这个均匀分布
import matplotlib.pyplot as plt

# 1. 创建画布
plt.figure(figseze=(20, 8), dpi=80)

# 2. 绘制直方图
plt.hist(x1, 1000)

# 3. 显示图像
plt.show()

画出的直方图:
在这里插入图片描述

  • 正态分布
    是具有两个参数μ和σ的连续型随机变量的分布,第一参数μ是服从正态分布的随机变量的均值,第二个参数σ是此随机变量的标准差,所以正态分布记作N(μ, σ).
    σ 幅度、波动程度、集中程度、稳定性
    μ决定图像的位置

f(x) = (1 / σ(2π)0.5 ) e^((x-μ)**2) / 2 σ**2^

方差:
在这里插入图片描述
标准差是s

方差越小越稳定

np.random.normal(loc=0.0, scale=1.0, size=None)
loc是均值, scale是标准差,对应图像的宽度

data2 = np.random.normal(loc=1.75, scale=0.1, size=10000)
print(data2)
[1.55345983 1.73792734 1.62380419 ... 1.80401868 1.90379977 1.69976006]

# 这里用直方图来表示这个正态分布
import matplotlib.pyplot as plt

# 1. 创建画布
plt.figure(figseze=(20, 8), dpi=80)

# 2. 绘制直方图
plt.hist(data2, 10000)

# 3. 显示图像
plt.show()

在这里插入图片描述

案例:随机生成8只股票2周的交易日涨幅数据

stock_change = np.random.normal(loc=0, scale=1, size=(8, 10))

数组的索引、切片

  • 获取第一支股票的前3个交易日的涨跌幅数据
# 二维数组,两个维度
stock_change[0, 0:3]

形状修改

  • 需求:让刚才的股票行、日期列反过来,变成日期行、股票列
stock_change.reshape(10, 8) # 我们发现只是对数据进行了重新分割,并没有反转
stock_change.resize(10, 8) # in-place, 没返回,并没有反转

stock_change.T  # 转置,行变成列, 列变成行,有返回

3.3.4 类型修改

  • ndarray.astype(type)
    如果想要序列化到本地,先要转成bytes类型
stock_change.astype("int32")

stock_change.tostring() # bytes类型

扩展:
jupyter对输出的字节数有限制,需要去修改配置文件, 但是不建议

3. 3. 5 数组的去重

temp = np.array([1, 2, 3, 4], [3, 4, 5, 6])
np.unique(temp) # 返回array[1, 2, 3, 4, 5, 6]
temp.flatten()  # 扁平化
set(temp)

3.3.6 小结

  • 创建数组
    • 均匀
    • 随机(正态分布)
  • 正太分布
  • 数组索引
  • 数组形状改变
  • 数组类型
    • reshape
    • resize
  • 数组转换
    • T
    • tostring
    • unique

3.4 ndarray运算

学习目标

  • 目标
    • 应用数组的通用判断函数
    • 应用np.where实现数组的三元运算
  • 应用
    • 股票涨跌幅数据逻辑运算
  • 内容预览
    • 3.4.1逻辑运算
    • 3.4.2通用判断函数
    • 3.4.3np.where(三元运算符)
    • 3.4.4统计运算

问题

如果想要操作符合某一条件的数据,应该怎么做?

3.4.1逻辑运算

# 重新生成8只股票10个交易日的涨跌幅数据
stock_change = np.random.normal(0, 1, (8, 10)) # loc=0, 方差=1, 8行10列
stock_change = stock_change[0:5, 0:5]  # 获取前五行的前五列

# 逻辑判断,如果涨幅大于0.5就标记为True 否则为False
stock_changes > 0.5  # 返回新的,bool
stock_changes[stock_changes > 0.5] = 1.1  # 满足条件的统一处理

3.4.2 通用判断函数

  • np.all()
    只有全是True才会返回True
判断stock_changes[0:2, 0:5]是否全是上涨的
np.all(stock_changes[0:2, 0:5] > 0)
false
  • np.any()
    只要有一个True就会返回True
# 判断前5只股票这段时间是否有上涨
np.any(stock_changes[0:5, :] > 0)
True

3.4.3 np.where (三元运算符)

通过使用np.where能够进行更加复杂的运算

  • np.where()
# 判断前四只股票前四天的涨跌幅  大于0的置为1, 否则为0
temp = stock_changes[:4, :4]
np.where(temp > 0, 1, 0)
  • 复合逻辑需要结合np.logical_and和logical_or使用
# 判断前四个股票前四天的涨跌幅  大于0.5并且小于1的, 换为1, 否则0
# 判断前四个股票前四天的涨跌幅 大于0.5或者小于-0.5的, 换为1, 否则为0
np.where(np.logical_and(temp > 0.5, temp < 1), 1, 0)
np.where(np.logical_or(temp > 0.5, temp < -0.5), 1, 0)

3.4.4 统计指标

使用方法:np.函数名 ; ndarray.方法名

  • np.min(a[, axis, out, keepdims])

  • np.max(a[, axis, out, keepdims])

  • np.median(a[, axis, out, overwrite_input, keeepdims])

  • np.mean(a[, axis, dtype, out, keepdims])

  • np.std(a[, axis, dtype, out, ddof, keepdims])

  • np.var(a[, axis, dtype, out, ddof, keepdims])

进行统计的时候,axis轴的取值并不一定,Numpy中不同的API轴的值不一样,在这里,axis 0 代表列, axis 1 代表行进行统计

print("前四只股票前四天的最大涨幅{}".format(np.max(temp, axis=1)))
print("前四只股票前四天的最大跌幅{}".format(np.min(temp, axis=1)))
print("前四只股票前四天的波动程度{}".format(np.std(temp, axis=1)))
print("前四只股票前四天的平均涨跌幅{}".format(np.mean(temp, axis=1)))

np.argmax(temp, axis=1)  # 返回的是索引

3.5 数组间的运算

3.5.1 应用场景

3.5.2 数组与数的运算

arr = np.array([1, 2, 3, 4], [2, 3, 4, 5])
arr + 1   # 每个元素加1  - 、 *、 / 都是可以的

3.5.3 数组与数组的运算


3.5.4 广播机制

执行broadcast的前提在于, 两个ndarray执行的是element-wise的运算,Broadcast机制的功能是为了方便不同形状的ndarray进行数学运算。
当操作两个数组时,numpy会逐个比较他们的shape(构成的元组tuple), 只有在下述情况下,两个数组才能够进行数组与数组的运算。

  • 维度相等
  • shape(其中相对应的一个地方为1)

3.5.5 矩阵运算

1 矩阵存储
两种方法存储矩阵:

  1. matrix
  2. ndarray
data = np.array([1, 2], [2, 4], [5, 6])
data1 = np.mat([1, 2], [2, 4], [5, 6])

2 矩阵乘法运算
形状改变:
m行n列 * n行任l列 = m行l 列

矩阵乘法api

  • np.matmul
    mat是matrix; mul是multiply
  • np.dot
np.matmul(a, b)
np.dot(a, b)

ndarray要用这两个进行乘法;如果是matrix直接 * 就可以了
ndarray也可以用 @,ndarray * ndarray是检查广播机制

3.6合并、分割的用处

3.6.1 合并

np.hstack(tup)
np.vstack(tup)

np.concatenate((a1, a2, …), axis=0) 0是竖直拼接; 1是水平拼接

3.6.2 分割

np.split(ary, indices_or_sections, axis=0)

3.7 IO操作与数据处理

学习目标

  • 目标
    • 知道Numpy文件的读取
  • 应用
  • 内容预览
    • 3.7.1 Numpy读取
    • 3.7.2 如何处理缺失值
      • 1 什么是缺失值
      • 2 缺失值处理
        问题
        大多数数据并不是我们自己创造的, 而是存在文件当中,需要我们用工具获取。
        但是Numpy其实并不适合用来读取和处理数据,因此我们这里了解相关API,以及Numpy不方便的地方即可。

3.7.1 Numgy读取

test = np.genfromtxt("test.csv", delimiter=",")

3.7.2 如何处理缺失值

1.什么是缺失值
什么时候numpy中会出现nan:当我们读取本地的文件为float的时候,nan

2 如何处理缺失值
两种思路:
- 直接删除
- 替换/插补

3.8总结

在这里插入图片描述

posted @ 2019-10-11 11:44  段明  阅读(394)  评论(0编辑  收藏  举报