Numpy模块(一).
在使用拼接前, 先创建两个数组
import numpy as np
arr = np.arange(12).reshape(2, 6)
arr1 = np.arange(12, 24).reshape(2, 6)
print(arr)
print(arr1)
# 返回结果
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
[[12 13 14 15 16 17]
[18 19 20 21 22 23]]
使用垂直拼接, 拼接两个数组
arr2 = np.vstack((arr, arr1)) # 垂直拼接, 行堆叠数组
print(arr2)
#返回结果
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
使用水平拼接, 拼接两个数组
arr3 = np.hstack((arr, arr1))
print(arr3) # 水平拼接, 列堆叠数组
#返回结果
[[ 0 1 2 3 4 5 12 13 14 15 16 17]
[ 6 7 8 9 10 11 18 19 20 21 22 23]]
先创建一维数组
import numpy as np
arr = np.arange(10)
print(arr)
# 返回结果:
[0 1 2 3 4 5 6 7 8 9]
一维数组切片其实和list的切片很类似
print(arr[2]) # 取下标为2的值, 下标从0开始
# 返回结果
2
print(arr[:2]) # 取前两个数值
# 返回结果
[0 1]
print(arr[7:]) # 取后面三个值
# 返回结果
[7 8 9]
print(arr[-1]) # 取最后一个值
# 返回结果
9
print(arr[1::2]) #取[1,3,5,7,9]
# 返回结果
[1 3 5 7 9]
print(arr[::-1]) # 倒序取值
# 返回结果
[9 8 7 6 5 4 3 2 1 0]
先创建二维数组
import numpy as np
arr = np.arange(24).reshape(4, 6)
print(arr)
# 返回结果
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
其实简单的看二维数组, 它跟列表嵌套列表很像"[[ ], [ ], [ ],[ ]]", 因此取值也跟这种列表嵌套列表的方式一样。
print(arr[1]) # 取第二行
# 返回结果
[ 6 7 8 9 10 11]
print(arr[1][1]) # 取第二行的第二个数
#返回结果
7
但是数组中有更加方便的取值方式, 利用逗号分隔即可, 即"[行, 列]"
print(arr[1, :]) # 取第二行, 由于是取整行的数据, 因此列写个:即可
# 返回结果
[ 6 7 8 9 10 11]
print(arr[1, 1]) # 取第二行的第二个数
# 返回结果
7
print(arr[1:3, :]) # 取第2~3连续行
# 返回结果
[[ 6 7 8 9 10 11]
[12 13 14 15 16 17]]
print(arr[1:3, 1:5]) # 取第2~3连续行并且第2~4连续列
# 返回结果
[[ 7 8 9 10]
[13 14 15 16]]
print(arr[1:4:2, :]) # 取第2和第4行
#返回结果
[[ 6 7 8 9 10 11]
[18 19 20 21 22 23]]
数组中还有一个神奇索引, 如果我要取第1和第3行, 就可以利用神奇索引来完成
print(arr[(1,3), :]) #使用数组的神奇索引可以直接指定要取的行, 但是需要用()或[]括住, 效果与arr[1:4:2, :]是相等的
# 返回结果
[[ 6 7 8 9 10 11]
[18 19 20 21 22 23]]
但是如果行和列都是用了神奇索引, 那它最后取出的不是一个子矩阵, 而是坐标点.
print(arr[(1, 2), (3, 4)])
# 返回结果
[ 9 16]
原因是它的执行顺序问题,这里arr[(1, 2), (3, 4)] 可以看为2个坐标(1, 3)和(2, 4)。首先根据(1, 3) 就是找到行索引为1,列索引3的值,也就是9; 然后根据 (3, 4)找到行索引为2,列索引为4的值, 也就是16。 因此最后得出的结果是(9, 16)
沿用上面的数组继续使用
arr[:, 1] = 0 # 将第2列所有的值都改为0
print(arr)
#返回结果
[[ 0 0 2 3 4 5]
[ 6 0 8 9 10 11]
[12 0 14 15 16 17]
[18 0 20 21 22 23]]
arr[:, (1,3)] = 1 # 将第2列和第4列的值都改为1
print(arr)
#返回结果
[[ 0 1 2 1 4 5]
[ 6 1 8 1 10 11]
[12 1 14 1 16 17]
[18 1 20 1 22 23]]
在数组中,索引还可以使用比较运算,该方法被称为布尔索引
print(arr[arr<10]) # 筛选出小于10的值
# 返回结果
[0 1 2 1 4 5 6 1 8 1 1 1 1 1]
arr[arr<10] = 2 # 将小于10的值都改为2
print(arr)
# 返回结果
[[ 2 2 2 2 2 2]
[ 2 2 2 2 10 11]
[12 2 14 2 16 17]
[18 2 20 2 22 23]]
numpy.where()函数是三元表达式 x if condition else y 的向量化版本。
# <10的值变为0, 大于10变为10
print(np.where(arr<10, 0, 10))
# 返回结果
[[ 0 0 0 0 0 0]
[ 0 0 0 0 10 10]
[10 0 10 0 10 10]
[10 0 10 0 10 10]]
# arr中<8的变为0, 其他的不变
print(np.where(arr<8, 0, arr)) # 传入arr本身就等同于值不变
# 返回结果
[[ 0 0 0 0 0 0]
[ 0 0 0 0 10 11]
[12 0 14 0 16 17]
[18 0 20 0 22 23]]
# arr中小于5的都变为5, 大于10的都变为10, 两者都不满足的就不变
print(arr.clip(5, 15))
# 返回结果
[[ 5 5 5 5 5 5]
[ 5 5 5 5 10 11]
[12 5 14 5 15 15]
[15 5 15 5 15 15]]
方法 | 描述 |
---|---|
sum | 沿着轴向计算所有元素的累和,0长度的数组,累和为0 |
mean | 数学平均,0长度的数组平均值为NaN |
max,min | 最大值和最小值 |
argmax,argmin | 最大值和最小值的位置 |
std,var | 标准差和方差 |
ptp | 极值 |
cumsum | 从0开始元素累积和 |
median | 中值 |
先创建一个数组, 用于试验
import numpy as np
arr = np.arange(12).reshape(3, 4)
print(arr)
# 返回结果
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
sum:沿着轴向计算所有元素的累和,0长度的数组,累和为0
arr.sum()
#或
np.sum(arr) # 两个方式是相等的
# 返回结果
66
print(np.sum(arr, axis=0)) # 求行轴向的累加和
# 返回结果
[12 15 18 21]
print(np.sum(arr, axis=1)) # 求列轴向的累加和
#返回结果
[ 6 22 38]
数学平均,0长度的数组平均值为NaN
print(np.mean(arr)) # 求平均值
# 返回结果
print(np.mean(arr, axis=0)) # 求行轴向的平均值
# 返回结果
[4. 5. 6. 7.]
print(np.mean(arr, axis=1)) # 求列轴向的平均值
# 返回结果
[1.5 5.5 9.5]
最大值和最小值
print(np.max(arr)) # 求最大值
# 返回结果
11
print(np.min(arr)) # 求最小值
# 返回结果
0
arr[0,0] = 50 # 将数组中第一个数改为50
print(arr)
print(np.max(arr, axis=0)) # 求行轴向的最大值
# 返回结果
[[50 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[50 9 10 11]
最大值和最小值的位置
这里沿用上面的数组, 上面的数组中第一个数值为50, 索引位置是0
print(np.argmax(arr)) # 最大值的索引位置
# 返回结果
0
print(np.argmax(arr, axis=0)) # 以行轴方向找最大值的位置
# 返回结果, 结果中的0和2, 指的是每一列的最大值的索引位置, 如第1列最大值是50,因此索引为0; 第二列最大值为9, 因此索引为2, 以此类推.
[0 2 2 2]
标准差和方差
print(np.std(arr)) # 求标准差
# 返回结果
12.532180798071641
print(np.var(arr)) # 求方差
# 返回结果
157.05555555555557
极差
print(np.ptp(arr)) # 求极值
# 返回结果
49
print(np.ptp(arr, axis=0))
# 返回结果
[46 8 8 8]
从0开始元素累积和
用回最初的数组: arr = np.arange(12).reshape(3, 4)
print(np.cumsum(arr)) # 相当于0+1+2+3+4+5...+N 每次相加都会输出一个结果,最后输出为一个一维数组
# 返回结果
[ 0 1 3 6 10 15 21 28 36 45 55 66]
中值
print(np.median(arr)) # 求数组的中值
# 返回结果
5.5
print(np.median(arr, axis=0)) # 以行轴向求中值
# 返回结果
[4. 5. 6. 7.]
先创建一个数组
import numpy as np
arr = np.arange(16).reshape(4, 4)
print(arr)
# 返回结果
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
用上面的数组除0
print(arr/0)
# 返回结果
[[nan inf inf inf]
[inf inf inf inf]
[inf inf inf inf]
[inf inf inf inf]]
再看看上面的返回结果, 0/0=NaN, 但是其余数值除0得到的是inf, 这是因为在这里0是相当于无穷小, 类似函数y=1/x,当x→0时,y→∞;反之亦然。
NaN在numpy中属于float类型, 如果想要将数组的某个值改为NaN, 则需要将数组改为float类型; inf也是同理。
arr1 = arr.astype("float") # 改变数组类型为float
arr1[1,2] = np.nan # 将索引坐标为(1,2)的值改为NaN
print(arr1)
# 返回结果
[[ 0. 1. 2. 3.]
[ 4. 5. nan 7.]
[ 8. 9. 10. 11.]
[12. 13. 14. 15.]]
NaN有个特性,两个NaN之间是不相等的
np.nan == np.nan
# 返回结果
False
基于此特性, 可以通过比较数组自身判断一个数组中NaN的个数
print(arr1 != arr1) # 将数组与自身比较, 如果遇到NaN就会返回True
# 返回结果
[[False False False False]
[False False True False]
[False False False False]
[False False False False]]
在上面的返回结果中,只有NaN显示为True,然后在Python中,True==1,False==0,因此可以通过np.count_nonzero()方法, 它可以计算出数组中非0的个数,
print(np.count_nonzero(arr1!=arr1))
# 返回结果
1
不过这里其实有个更直白的,在Numpy中有个np.isnan()方法, 它就是用来判断数组中的元素是否是NaN
print(np.isnan(arr1) # 判断数组中的元素是否是NaN
# 返回结果
[[False False False False]
[False False True False]
[False False False False]
[False False False False]]
# 然后配合使用np.count_nonzero()即可统计
np.count_nonzero(np.isnan(arr1)) # 统计NaN个数
# 返回结果
1
另外,NaN与任何数相加都是NaN
np.nan + 1
# 返回结果
nan
在Numpy中,为了避免处理后NaN的值会对整体的数值有较大的影响,通常我们会将其替换成中值或者均值即可。
# 读取每一列
for i in range(arr1.shape[1]): # 获取数组的形状,得到列数
# 取出每一列
arr_col = arr1[:, i]
# 获取每列的nan的个数
nan_num = np.count_nonzero(np.isnan(arr_col))
# 判断nan个数为0的, 不作处理; 取出不为0的
if nan_num != 0:
# 取出不是nan的值, 求其平均值
not_nan_col = arr_col[arr_col == arr_col]
# 计算平均值
col_mean = np.mean(not_nan_col)
# 给NaN复制
arr_col[arr_col != arr_col] = col_mean
print(arr1)
# 返回结果
[[ 0. 1. 2. 3. ]
[ 4. 5. 8.66666667 7. ]
[ 8. 9. 10. 11. ]
[12. 13. 14. 15. ]]
Numpy提供了np.loadtxt(fname) 方法, 可以读取本地文件,其参数如下:
"""获取文件中的最高价和最低价"""
import numpy as np
HighPrice, LowPrice = np.loadtxt("AAPL.csv", delimiter=",", usecols=(0, 1), unpack=True)
print(HighPrice) # 高高价列
print(LowPrice) # 最低价列
print(f"max={np.max(HighPrice)}") # 两年内最高价
print(f"min={np.min(LowPrice)}") # 两年内最低价
"""计算周一~周五的平均价格"""
# 由于文件中有日期, 无法转换为float类型, 因此需要用到converts参数, 创建一个函数并对数据进行预处理
import datetime
def datenum(s):
"""
创建函数, 将'%Y-%m-%d'格式的日期转换为周的天数,
但返回的数字是从0开始的, 因此0=>周一, 1=>周二
""""
return datetime.datetime.strptime(s, "%Y-%m-%d").weekday()
# print(datenum("2020-05-15")) # 返回结果:4, 对应就是周五
# 读取文件
date, closePrice = np.loadtxt("AAPL02.csv", delimiter=",", usecols=(0, -1), unpack=True, converters={0: datenum})
# print(date) # 打印周天数
# print(closePrice) # 打印价格
# 分组显示并且求平均值
for i in range(5):
print(closePrice[date==i].mean())