数据分析 | NumPy

NumPy,全称是 Numerical Python,它是目前 Python 数值计算中最重要的基础模块。NumPy 是针对多维数组的一个科学计算模块,这个模块封装了很多数组类型的常用操作。

使用numpy来创建数组

python 复制代码
import numpy as np

data = np.array([1, 2, 3])
print(data)
# 输出:[1 2 3]
print(type(data))
# 输出:<class 'numpy.ndarray'>

除了使用 np.array() 方法来创建一个多维数组,numpy 还提供了两个实用的方法------np.ones()np.zeros(),分别生成元素全为 1 和 0 的多维数组。

python 复制代码
ones = np.ones(3)
print(ones)
# 输出:[1. 1. 1.]

zeros = np.zeros(3)
print(zeros)
# 输出:[0. 0. 0.]
  • np.ones()np.zeros() 的参数用于指定生成的多维数组里有多少个元素。
  • 并且生成出来的不是 1 和 0,而是 1. 和 0.。这是因为默认生成的是浮点数,numpy 会省略小数点后的 0,因此 1.0 和 0.0 变成了 1. 和 0.。

如果想要生成整数的话,可以传入 dtype 参数来指定类型:

python 复制代码
ones = np.ones(3, dtype='int')
print(ones)
# 输出:[1 1 1]
zeros = np.zeros(3, dtype='int')
print(zeros)
# 输出:[0 0 0]

数组的加减乘除:

列表间只有加法操作,作用是将两个列表的元素合并在一起。而多维数组间可以进行加减乘除的四则运算,运算规则也很简单:将两个数组中对应位置的元素一一进行运算。

两个多维数组的形状必须一致才能进行四则运算

python 复制代码
data = np.array([1, 2])
ones = np.ones(2)
print(data + ones)
# 输出:[2. 3.]

除了多维数组间的四则运算,多维数组直接和数字进行计算的方式也很常用

python 复制代码
data = np.array([1, 2])
print(data + 1)
# 输出:[2 3]

上述效果用列表来实现也是可以的

python 复制代码
data = []
for i in [1, 2]:
  data.append(i + 1)
print(data)
# 输出:[2, 3]

用列表就必须用到循环,而 numpy 中这种不用编写循环就可以对数据进行批量运算的方式叫做 矢量化。numpy 中的矢量化操作把内部循环委托给高度优化的 C 和 Fortran 函数,从而实现更清晰,更快速的 Python 代码。

多维数组:

一维数组只有行,二维数组相比一维数组多了列这个维度,而三维数组则类似多个二维数组堆叠在一起,形如一个立方体。

将单层嵌套列表传入 np.array() 方法创建一个二维数组:

python 复制代码
# 单层嵌套列表
nested_list = [[1, 2], [3, 4]]
print(nested_list)
# 输出:[[1, 2], [3, 4]]

# 二维数组
data = np.array(nested_list)
print(data)
# 输出:
# [[1 2]
#  [3 4]]

通过嵌套列表创建的二维数组也是用空格分隔的,并且分成了两行。列表中的第一个元素 [1, 2] 在第一行,第二个元素 [3, 4] 在第二行。

ones()zeros() 方法同样也能快速创建元素全为 1 和 0 的二维数组。

创建二维数组要传入一个包含行和列信息的元组。比如:np.ones((m, n)) 表示创建一个 m 行 n 列且元素全为 1 的二维数组。

python 复制代码
ones = np.ones((3, 2))
print(ones)
# 输出:
# [[1. 1.]
#  [1. 1.]
#  [1. 1.]]

zeros = np.zeros((3, 2))
print(zeros)
# 输出:
# [[0. 0.]
#  [0. 0.]
#  [0. 0.]]

多维数组的属性:

  • ndim:多维数组维度的个数。例如:二维数组的 ndim 为 2;
  • shape:多维数组的形状。它是一个元组,每个元素分别表示每个维度中数组的长度。对于 m 行和 n 列的的数组,它的 shape 将是 (m, n)。因此,shape 元组的长度(元素个数)就是 ndim 的值;
  • size:多维数组中所有元素的个数。shape 元组中每个元素的乘积就是 size 的值;
  • dtype:多维数组中元素的类型。
python 复制代码
data = np.array([[1, 2, 3], [4, 5, 6]])

print('ndim:', data.ndim)
print('shape:', data.shape)
print('size:', data.size)
print('dtype:', data.dtype)
# 输出:
# ndim: 2
# shape: (2, 3)
# size: 6
# dtype: int64

int64 是 numpy 提供的类型,表示 64 位的整数。

二维数组的通用方法:

通过 axis 参数可以指定计算方向

python 复制代码
data = np.array([[1, 2], [5, 3], [4, 6]])

# 不指定 axis
print(data.max())
# 输出:6

# axis=0
print(data.max(axis=0))
# 输出:[5 6]

# axis=1
print(data.max(axis=1))
# 输出:[2 5 6]

二维数组的索引和分片:

  • 二维数组的索引和分片同样和一维数组类似,只是在行索引的基础上再加上列索引。形如 data[m, n],其中 data 是二维数组,m 是行索引或分片,n 是列索引或分片。
  • 那么,data[0, 1] 就表示获取 data 中第一行第二列的元素。如果省略第二个参数 n 的话表示获取所有列,data[0] 就表示获取整个第一行,相当于 data[0, :]
  • 如果想要获取第一列则可以写成 data[:,0];如果想获取 2、3 两行可以写成 data[1:3],相当于 data[1:3, :]
python 复制代码
data = np.array([[1, 2], [3, 4], [5, 6]])

print(data[0, 1])
# 输出:2

print(data[:, 0])
# 输出:[1 3 5]

print(data[1:3])
# 输出:
# [[3 4]
#  [5 6]]

numpy 中的高级索引:

布尔索引
python 复制代码
data = np.array([[1, 2], [3, 4], [5, 6]])
print(data > 3)
#输出:[[False False]
#     [False  True]
#    [ True  True]]
print(data[data>3])
#输出:[4 5 6]
# 大于 3 并且小于 5
print(data[(data>3) & (data<5)])
#输出:[4]
# 大于 3 或者小于 2
print(data[(data > 3) | (data < 2)])
# 输出:[1 4 5 6]
# 大于 3 或者不小于 2(即大于等于 2)
print(data[(data > 3) | ~(data < 2)])
# 输出:[2 3 4 5 6]
# 等于 3
print(data[data == 3])
# 输出:[3]
# 不等于 3
print(data[data != 3])
# 输出:[1 2 4 5 6]

and 改用 &or 改用 |not 改用 ~,并且每个条件要用括号括起来。

实用方法:

arange() 方法:

numpy 中的 arange() 方法和 Python 中的 range() 用法类似,不同之处在于 arange() 方法生成的是数组,而 range() 方法生成的是 range 类型的序列。

python 复制代码
# 生成 1-9 的数组
print(np.arange(1, 10))
# 输出:[1 2 3 4 5 6 7 8 9]

# 生成 0-9 的数组
print(np.arange(10))
# 输出:[0 1 2 3 4 5 6 7 8 9]

# 生成 1-9 的数组,步长为 2
print(np.arange(1, 10, 2))
# 输出:[1 3 5 7 9]
随机方法:

numpy 中的 np.random.rand() 方法和 Python 中 random.random() 方法类似,都是生成 [0, 1) 之间的随机小数。不同的是,numpy 中的 np.random.rand() 方法可以生成多个 [0, 1) 之间的随机小数,只需我们传入要生成的随机数组的形状(shape)即可。

python 复制代码
# 不传参数时
print(np.random.rand())
# 输出:0.1392571183916036

# 传入一个参数时
print(np.random.rand(3))
# 输出:[0.7987698  0.52115291 0.70452156]

# 传入多个参数时
print(np.random.rand(2, 3))
# 输出:
# [[0.08539006 0.97878203 0.23976172]
#  [0.34301963 0.48388704 0.63304024]]

numpy 中的 np.random.randint() 方法和 Python 中的 random.randint() 类似,

不同之处在于,random.randint(m, n) 生成的是**[m, n]**之间的整数,

np.random.randint(m, n) 生成的是 [m, n) 之间的整数。

python 复制代码
# 不传入形状时
print(np.random.randint(0, 5))
# 输出:3

# 形状为一维数组时
print(np.random.randint(0, 5, 3))
# 输出:[4 0 1]

# 形状为二维数组时
print(np.random.randint(0, 5, (2, 3)))
# 输出:
# [[0 2 1]
#  [4 2 0]]
genfromtxt() 方法:

genfromtxt() 方法用于文件的读取。

genfromtxt() 方法常用的参数有两个,分别是数据源和分隔符。假设我们要用 numpy 读取一个以逗号分隔的 CSV 文件,可以这样写:

python 复制代码
data = np.genfromtxt('data.csv', delimiter=',')

第一个参数是数据源,可以是本地文件的路径,也可以是网络文件的地址。delimiter 参数用于指定分隔符,CSV 文件一般是用逗号作为分隔符,当遇到其他符号分隔的文件时,用 delimiter 参数进行指定即可。

genfromtxt() 方法的返回值是一个多维数组。


索引:

numpy 中多维数组的索引也是从 0 开始,以多维数组的长度减 1 结束,可以直接使用 data[-1] 获取数组中的最后一个元素。写法也和列表索引一样:

python 复制代码
data = np.array([1, 2, 3])
print(data[0])
# 输出:1
print(data[-1])
# 输出:3

分片:

多维数组的分片和列表的分片也是基本类似的,形如 data[m:n]。分片是左闭右开区间,即包含 m 不包含 n,也就是获取索引为 m 到 n-1 之间的元素(包含 m 和 n-1)。

python 复制代码
data = np.array([1, 2, 3])
print(data[0:2])  # 获取索引为 0 和 1 的元素
# 输出:[1 2]

多维数组也同样支持反向索引分片,使用 data[-3:-1] 也同样能得到 [1 2]

在列表分片时,冒号前后的值是可以省略的。省略后冒号前默认为 0,冒号后默认为列表的长度。这同样适用于多维数组,所以通过冒号前后值的省略,有如下分片小技巧:

python 复制代码
data = np.array([1, 2, 3])
# 获取前 2 个元素
print(data[:2])
# 输出:[1 2]

# 获取后 2 个元素
print(data[-2:])
# 输出:[2 3]

# 获取所有元素
print(data[:])
# 输出:[1 2 3]

**注意:**列表分片是将分片后的数据复制了一份,而多维数组的分片则是返回原数据其中的一块,并没有复制数据。

因此,对列表分片后的数据进行更改不会影响原数据,但对多维数组分片后的数据进行更改会影响到原数据。

python 复制代码
# 列表
lst_data = [1, 2, 3]
lst_data2 = lst_data[:]
lst_data2[0] = 6
print(lst_data)
# 输出:[1, 2, 3]

# 多维数组
arr_data = np.array([1, 2, 3])
arr_data2 = arr_data[:]
arr_data2[0] = 6
print(arr_data)
# 输出:[6 2 3]

numpy 设计的目的是处理大数据,所以,numpy 中的切片默认不会复制一份副本,而是返回原数据中的一块,被称为视图(View)。如果想要得到一份副本,则需要手动调用 copy() 方法进行复制,例如:arr_data[:].copy()

分片支持传入第三个参数------步长(分片时每隔几个数据取一次值,步长的默认值为 1)

python 复制代码
data = np.array([1, 2, 3, 4, 5, 6])
print(data[::2])  # 省略前两个参数
# 输出:[1 3 5]

上述例子中省略了前两个参数,默认为 0 和 6,步长为 2。所以 data[::2] 等价于 data[0:6:2],作用是索引在 0 到 5 之间的元素,且索引每次加 2。最终将得到索引为 0、2、4 的元素,结果为 [1 3 5]

当步长为负数时,会将顺序反转。

python 复制代码
data = np.array([1, 2, 3, 4, 5, 6])
print(data[::-1])  # 省略前两个参数
# 输出:[6 5 4 3 2 1]

可以利用这个特性来实现列表或多维数组的快速反转。

numpy的方法

求平均值的 mean() 方法,最大值的 max() 方法、求最小值的 min() 方法、求和的 sum() 方法

求中位数的median()方法,求极差的ptp()方法,求标准差的std()方法,求方差的var()方法

python 复制代码
import numpy as np

data = np.array([4, 2, 3, 7])
print(np.mean(data))
#输出:4.0
print(np.median(data))
#输出:3.5
print(np.min(data))
#输出:2
print(np.max(data))
#输出:7
print(np.ptp(data))
#输出:5
print(np.std(data))
#输出:1.8708286933869707
print(np.var(data))
#输出:3.5
  • 离中趋势是指一组数据中各数据值以不同程度的距离偏离其中心(平均数)的趋势。其常用指标有 极差方差标准差
  • 极差是一组数据的最大值减去最小值得到的,反应了数据变动的最大范围。
  • 方差的计算方式是:将一组数据中的每个数减去这组数据的平均数,然后将得到的结果进行平方求和,最后再除以数据的个数。
  • 标准差是方差的平方根。
  • 方差和标准差都能反映数据的离散程度,也就是数据的波动程度。方差和标准差的值越小,说明数据越稳定。
相关推荐
一点媛艺10 分钟前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风14 分钟前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生1 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功1 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
Nu11PointerException1 小时前
JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习
笔记·学习
闲晨1 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
_.Switch2 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
老猿讲编程2 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
亦枫Leonlew3 小时前
三维测量与建模笔记 - 3.3 张正友标定法
笔记·相机标定·三维重建·张正友标定法