本文已参与「新人创作礼」活动,一起开启掘金创作之路。
🔥 本文由 程序喵正在路上 原创,在稀土掘金首发!
💖 系列专栏:数据挖掘
🌠 首发时间:2022年8月30日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🌟 一以贯之的努力 不得懈怠的人生
四、ndarray运算
1. 逻辑运算
如果我们想要操作符合某一条件的数据时,该怎么做呢?
import numpy as np
stock_change = np.random.normal(loc=0, scale=1, size=(8, 10))
# 重新生成8只股票10个交易日的涨跌幅数据
stock_change = np.random.normal(0, 1, (8, 10))
stock_change = stock_change[0:5, 0:5]
# 需求一:逻辑判断,如果涨跌幅大于0.5就标记为True,否则为False
stock_change > 0.5
# 需求二:BOOL赋值,将满足条件的设置为指定的值-布尔索引
stock_change[stock_change > 0.5] = 1
stock_change
通用判断函数
-
np.all()
# 判断stock_change[0:2, 0:5]是否全部是上涨的 np.all(stock_change[0:2, 0:5] > 0)False -
np.any()
# 判断前5只股票这段期间是否有上涨的 np.any(stock_change[0:5, :] > 0)True
np.where(三元运算符)
通过使用 np.where 能够进行更加复杂的运算
-
np.where(布尔值,True的位置的值,False的位置的值)
# 判断前4个股票前4天的涨跌幅,大于0的置为1,否则为0 temp = stock_change[:4, :4] np.where(temp > 0, 1, 0)
-
复合逻辑需要结合 np.logical_and 和 np.logical_or 使用
# 判断前4个股票前4天的涨跌幅,大于0.5且小于1的,换为1,否则为0 np.where(np.logical_and(temp > 0.5, temp < 1), 1, 0)
# 判断前4个股票前4天的涨跌幅,大于0.5或者小于-0.5的,换为1,否则为0
np.where(np.logical_or(temp > 0.5, temp < -0.5), 1, 0)
2. 统计计算
如果想要知道涨幅或者跌幅最大的数据,应该怎么做?
(1)统计指标
在数据挖掘 / 机器学习领域,统计指标的值也是我们分析问题的一种方式,常用的指标如下:
- np.min(a[, axis, out, keepdims])
Return the minimum of an array or minimum along an axis
返回数组的最小值或沿轴的最小值 - np.max(a[, axis, out, keepdims])
Return the maximum of an array or maximum along an axis
返回数组的最大值或沿轴的最大值 - np.median(a[, axis, out, overwrite_input, keepdims])
Compute the median along the specified axis
沿指定轴计算中值 - np.mean(a[, axis, dtype, out, keepdims])
Compute the arithmetic mean along the specified axis
沿指定轴计算算术平均值 - np.std(a[, axis, dtype, out, ddof, keepdims])
Compute the standard deviation along the specified axis
沿指定轴计算标准偏差 - np.var(a[, axis, dtype, out, ddof, keepdims])
Compute the variance along the specified axis
沿指定轴计算方差
(2)股票涨跌幅统计运算
进行统计的时候,axis 轴的取值并不一定,Numpy 中不同的 API 轴的值都不一样,在这里,axis=0 代表列,axis=1 代表行去进行统计
import numpy as np
# 接下来对于这4只股票的4天数据,进行一些统计运算
temp = stock_change[:4, :4]
# 指定行去统计
print("前4只股票前4天的最大涨幅为{}".format(np.max(temp, axis=1)))
# 使用min,std,mean
print("前4只股票前4天的最大跌幅为{}".format(np.min(temp, axis=1)))
print("前4只股票前4天的波动程度为{}".format(np.std(temp, axis=1)))
print("前4只股票前4天的平均涨跌幅为{}".format(np.mean(temp, axis=1)))
如果需要统计出哪一只股票在某个交易日的涨幅最大或者最小?
- np.argmax(temp, axis=)
- np.argmin(temp, axis=)
# 获取股票指定哪一天的涨幅最大
print("前4只股票前4天内涨幅最大为{}".format(np.argmax(temp, axis=1)))
print("前4天1天内涨幅最大的股票为{}".format(np.argmax(temp, axis=0)))
3. 数组间运算
(1)场景
数据:
[[80, 86],
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]]
(2)数组与数的运算
arr = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr + 1
arr / 2
# 对比python列表的运算,看出区别
a = [1, 2, 3, 4, 5]
a * 3
(3)数组与数组的运算
arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr2 = np.array([[1, 2, 3, 4], [3, 4, 5, 6]])
arr1 + arr2 # 两个数组这样是不能进行运算的
(4)广播机制
执行 broadcast 的前提在于,两个 ndarray 执行的是 element-wise 的运算,Broadcast 机制的功能而是为了方便不同形状的 ndarray(numpy 库的核心数据结构)进行数学运算
当操作两个数组时,numpy 会逐个比较它们的 shape (构成的元组 tuple),只有在下述情况下,两个数组才能够进行数组与数组的运算
- 维度相等
- shape(其中相对应的一个地方为 1)
例如:
维度相等
Image (3d array): 256 x 256 x 3
Scale (1d array): 3
Result (3d array): 256 x 256 x 3
其中相对应的一个地方为 1
A (4d array): 9 x 1 x 7 x 1
B (3d array): 8 x 1 x 5
Result (4d array): 9 x 8 x 7 x 5
其中相对应的一个地方为 1
A (2d array): 5 x 4
B (1d array): 1
Result (2d array): 5 x 4
维度相等,其中相对应的一个地方为 1
A (3d array): 15 x 3 x 5
B (3d array): 15 x 1 x 1
Result (3d array): 15 x 3 x 5
最终结果是取最大维度
如果是下面这样,则不匹配:
A (1d array): 10
B (1d array): 12
A (2d array): 2 x 1
B (3d array): 8 x 4 x 3
思考:下面两个 ndarray 是否能够进行运算?
arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr2 = np.array([[1], [3]])
arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]]) # 2 x 6
arr2 = np.array([[1], [3]]) # 2 x 1
# 维度相等,其中相对应的一个地方为 1,可以进行运算
arr1 + arr2
4. 矩阵运算
现在再次回到最开始的学生成绩问题:
思考:如何能够直接得出每个学生的成绩呢?
(1)什么是矩阵
矩阵,英文 matrix,和 array 的区别是:矩阵必须是二维的,但是 array 可以是多维的
-
np.mat() 将数组转换成矩阵类型
a = np.array([[80, 86], [82, 80], [85, 78], [90, 90], [86, 82], [82, 90], [78, 80], [92, 94]]) np.mat(a)
(2)矩阵乘法运算
矩阵乘法的两个关键:
- 形状改变
- 运算规则
形状改变:
(M行,N列)x (N行,L列)= (M行,L列)
必须符合上面的式子,否则运算出错!
运算规则:
设 A 为 m x p 的矩阵,B 为 p x n 的矩阵,那么称 m x n 的矩阵 C 为 A 与 B 的乘积,记作 C = AB,其中矩阵 C 中的第 i 行第 j 列元素可以表示为下式:
例如:
上式:(2,3)x(3,2)=(2,2)
左上 —— A第1行 x B第1列 右上 —— A第1行 x B第2列 左下 —— A第2行 x B第1列 右下 —— A第2行 x B第2列
直接得出每个学生的成绩:
a = np.array([[80, 86], # (8 x 2)
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]])
b = np.array([[0.3], # (2 x 1)
[0.7]])
a_mat = np.mat(a)
b_mat = np.mat(b)
a_mat * b_mat
(3)矩阵乘法API
- np.matmul
- np.dot
a = np.array([[80, 86], # (8 x 2)
[82, 80],
[85, 78],
[90, 90],
[86, 82],
[82, 90],
[78, 80],
[92, 94]])
b = np.array([[0.3], # (2 x 1)
[0.7]])
np.matmul(a,b)
np.dot(a,b)
拓展解法:
a @ b
5. 合并、分割
合并、分割的用处:
实现数据的切分和合并,将数据进行切分合并处理
(1)合并
- numpy.hstack(tup) Stack arrays in sequence horizontally (column wise)
- numpy.vstack(tup) Stack arrays in sequence vertically (row wise)
- numpy.concatenate((a1, a2, ...), axis=0)
实例:
- np.hstack()
a = np.array((1, 2, 3))
b = np.array((2, 3, 4))
np.hstack((a, b))
a = np.array([[1], [2], [3]])
b = np.array([[2], [3], [4]])
np.hstack((a, b))
- np.vstack()
a = np.array([1, 2, 3])
b = np.array([2, 3, 4])
np.vstack((a, b))
a = np.array([[1], [2], [3]])
b = np.array([[2], [3], [4]])
np.vstack((a, b))
- np.concatenate()
a = np.array([[1, 2], [3, 4]])
b = np.array([[5, 6]])
np.concatenate((a, b), axis=0)
np.concatenate((a, b.T), axis=1) # 。T 进行转置
比如我们将两部分股票的数据拼接在一起:
stock_change = np.random.normal(loc=0, scale=1, size=(8, 10))
a = stock_change[:2, 0:4]
b = stock_change[4:6, 0:4]
# axis=1时,按照数组的列方向拼接在一起
# axis=0时,按照数组的行方向拼接在一起
np.concatenate([a, b], axis=0)
np.concatenate([a, b], axis=1)
np.vstack((a, b))
np.hstack((a, b))
(2)切割
- numpy.split(ary, indices_or_sections, axis=0)
Split an array into mutiple sub-arrays
x = np.arange(9.0)
x
np.split(x, 3)
x = np.arange(8.0)
x
np.split(x, [3, 5, 6, 10])
6. IO操作与数据处理
大多数数据并不是我们自己构造的,而是存在文件当中,需要我们用工具来获取
但是,Numpy 其实并不适合用来读取和处理数据,因此我们这里了解相关 API,以及 Numpy 不方便的地方即可
(1)Numpy读取
- genfromtxt(fname[, dtype, comments, ...]) Load data from a text file, with missing values handed as specified
准备一个 “test.csv” 文件,内容如下
id,value1,value2,value3
1,123,1.4,23
2,110,,18
3,,2.1,19
data = np.genfromtxt("test.csv",delimiter=",")
data
可以看到,读取结果有缺失值
(2)如何处理缺失值
什么是缺失值?
什么时候 Numpy 中会出现 nan:当我们读取本地的文件为 float 的时候,如果有缺失 (或者为 None),就会出现 nan
缺失值处理
那么,如果我们单纯地把数据中的 nan 替换为 0,合适吗?会带来什么样的影响?
比如,全部替换为 0 后,替换之前的平均值如果大于 0,替换之后的均值肯定会变小,所以更一般的方式是把缺失的数值替换为均值(中值)或者是直接删除有缺失值的一行
所以:
- 如何计算一组数据的中值或者是均值
- 如何删除有缺失数据的那一行(列)在 pandas 中介绍
# data中存在nan值,如何操作把其中的nan填充为每一列的均值
data = array([[ nan, nan, nan, nan],
[ 1. , 123. , 1.4, 23. ],
[ 2. , 110. , nan, 18. ],
[ 3. , nan, 2.1, 19. ]])
处理逻辑:
def fill_nan_by_column_mean(t):
for i in range(t.shape[1]):
# 计算nan的个数
nan_num = np.count_nonzero(t[:, i][t[:, i] != t[:, i]])
if nan_num > 0:
now_col = t[:, i]
# 求和
now_col_not_nan = now_col[np.isnan(now_col) == False].sum()
# 和/个数
now_col_mean = now_col_not_nan / (t.shape[0] - nan_num)
# 赋值给now_col
now_col[np.isnan(now_col)] = now_col_mean
# 赋值给t,即更新t的当前列
t[:, i] = now_col
return t
fill_nan_by_column_mean(data)
看了上面的处理过程,你肯定觉得太麻烦了吧,等我们学了 pandas 之后就好处理了