补
Numpy是类似于Python list的数据结构
基本操作
创建变量
cars = np.array([ # 与list类似
[
[5, 10, 12, 6],
[5.1, 8.2, 11, 6.3],
[4.4, 9.1, 10, 6.6]
],
[
[6, 11, 13, 7],
[6.1, 9.2, 12, 7.3],
[5.4, 10.1, 11, 7.6]
],
])
print("总维度:", cars.ndim) # .ndim可以查询数据维度
print("场地 1 数据:\n", cars[0], "\n场地 1 维度:", cars[0].ndim)
print("场地 2 数据:\n", cars[1], "\n场地 2 维度:", cars[1].ndim)
数据类型
添加数据
对于一维的数据,直接进行合并
cars1 = np.array([5, 10, 12, 6])
cars2 = np.array([5.2, 4.2])
cars = np.concatenate([cars1, cars2])
#cars=[ 5. 10. 12. 6. 5.2 4.2]
若将数据扩大至二维
test1 = np.array([5, 10, 12, 6])
test2 = np.array([5.1, 8.2, 11, 6.3])
# 首先需要把它们都变成二维,下面这两种方法都可以加维度
test1 = np.expand_dims(test1, 0)
test2 = test2[np.newaxis, :]
# test1=[[ 5 10 12 6]]
# test2=[[ 5.1 8.2 11. 6.3]]
# 然后再在第一个维度上叠加
all_tests = np.concatenate([test1, test2])
# all= [[ 5. 10. 12. 6. ] [ 5.1 8.2 11. 6.3]]
在不同维度进行合并
# Take data 'all_tests' above for example
print("第一维度叠加:\n", np.concatenate([all_tests, all_tests], axis=0))
# 第一维度叠加:
# [[ 5. 10. 12. 6. ]
# [ 5.1 8.2 11. 6.3]
# [ 5. 10. 12. 6. ]
# [ 5.1 8.2 11. 6.3]]
print("第二维度叠加:\n", np.concatenate([all_tests, all_tests], axis=1))
# 第二维度叠加:
# [[ 5. 10. 12. 6. 5. 10. 12. 6. ]
# [ 5.1 8.2 11. 6.3 5.1 8.2 11. 6.3]]
# Not hard to understand
# 其实,只要维度能够对齐,你可以在任意维度上进行合并操作。注意,有些数据维度是对不齐的,这样没办法合并
a = np.array([
[1,2,3],
[4,5,6]
])
b = np.array([
[7,8],
[9,10]
])
print(np.concatenate([a,b], axis=1)) # 这个没问题
# [[ 1 2 3 7 8]
# [ 4 5 6 9 10]]
# print(np.concatenate([a,b], axis=0)) # 这个会报错:(
还有更加便捷的直接进行水平/垂直方向合并的指令np.vstack()
, np.hstack()
1 | 2 |
3 | 4 |
5 | 6 |
7 | 8 |
1 | 2 | 5 | 6 |
3 | 4 | 7 | 8 |
a = np.array([
[1,2],
[3,4]
])
b = np.array([
[5,6],
[7,8]
])
print("竖直合并\n", np.vstack([a, b]))
# 竖直合并
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
print("水平合并\n", np.hstack([a, b]))
# 水平合并
# [[1 2 5 6]
# [3 4 7 8]]
高级合并
列合并
feature_a = np.array([1,2,3,4,5,6])
feature_b = np.array([11,22,33,44,55,66])
c_stack = np.column_stack([feature_a, feature_b])
print(c_stack)
# [[ 1 11]
# [ 2 22]
# [ 3 33]
# [ 4 44]
# [ 5 55]
# [ 6 66]]
行合并
sample_a = np.array([0, 1.1])
sample_b = np.array([1, 2.2])
c_stack = np.row_stack([sample_a, sample_b])
print(c_stack)
# [[0. 1.1]
# [1. 2.2]]
拆解
横着切
a = np.array(
[[ 1, 11, 2, 22],
[ 3, 33, 4, 44],
[ 5, 55, 6, 66],
[ 7, 77, 8, 88]]
)
print(np.vsplit(a, indices_or_sections=2)) # 分成两段
print(np.vsplit(a, indices_or_sections=[2,3])) # 0~2 一段,2~3 一段,3~一段
# [array([[ 1, 11, 2, 22],
# [ 3, 33, 4, 44]]), array([[ 5, 55, 6, 66],
# [ 7, 77, 8, 88]])]
# [array([[ 1, 11, 2, 22],
# [ 3, 33, 4, 44]]), array([[ 5, 55, 6, 66]]), array([[ 7, 77, 8, 88]])]
竖着切
a = np.array(
[[ 1, 11, 2, 22],
[ 3, 33, 4, 44],
[ 5, 55, 6, 66],
[ 7, 77, 8, 88]]
)
print(np.split(a, indices_or_sections=2, axis=0)) # 分成两段
print(np.split(a, indices_or_sections=[2,3], axis=1)) # 在第二维度, 0~2 一段,2~3 一段,3~一段
# [array([[ 1, 11, 2, 22],
# [ 3, 33, 4, 44]]), array([[ 5, 55, 6, 66],
# [ 7, 77, 8, 88]])]
# [array([[ 1, 11],
# [ 3, 33],
# [ 5, 55],
# [ 7, 77]]), array([[2],
# [4],
# [6],
# [8]]), array([[22],
# [44],
# [66],
# [88]])]
其实是没啥大用
array形态改变
善用reshape
test1 = np.array([5, 10, 12, 6])
test1.reshape(4,-1) # 要求行数为4,列数不限,参数为-1时为不限
# test1=[[ 5] [10] [12] [ 6]]
test1.reshape(2,-1,1)
# test1=[[[ 5] [10]] [[12] [ 6]]]
# Attention:reshape参数中不可以出现两个及以上-1
利用shape
观察矩阵形态
test1 = np.array([5, 10, 12, 6])
test1.reshape(2,-1,1)
#test1.shape=(2,2,1)
数据选取
单个选取
和list一样,[x][y]=[x,y],代表选择第x行,第y列的元素
当然,也有比较刁钻的部分
b = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])
# 如果对应到数据,要竖着看,我也不知道为啥
# 第一个拿的是数据位是 [1,2]
# 第二个拿的是 [0,3]
print("b[[1,0],[2,3]]:\n",
b[[1,0],
[2,3]])
# [7 4]
切片选取
巧用:
# [x:y]代表数组中[x,y)范围的数字,若略去则代表首/尾,若x/y为负数,也不难理解嘛,就是倒着数呗
a = np.array([1, 2, 3])
print("a[0:-1]:\n", a[0:-1])
# [1 2]
print("a[1:]:\n", a[1:])
# [2 3]
print("a[-2:]:\n", a[-2:])
# [2 3]
# [x:y:z]代表[x,y)范围的数字,选取步长为z
a = np.arange(10)
b = a[2:7:2] # 从索引 2 开始到索引 7 停止,间隔为 2
print(b)
# [2 4 6]
多维亦然
b = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])
print("b[:2]:\n", b[:2]) #EZ
# [[1 2 3 4]
# [5 6 7 8]]
print("b[:2, :3]:\n", b[:2, :3]) # 行选取[0,2),列选择[0,3)
# [[1 2 3]
# [5 6 7]]
print("b[1:3, -2:]:\n", b[1:3, -2:])
# [[ 7 8]
# [11 12]]
也可以用这种方式对矩阵批量进行选取
a = np.arange(10)
s = slice(2,7,2) # 从索引 2 开始到索引 7 停止,间隔为2
print (a[s])
# 不难理解
条件筛选
基础操作,看码说话
a = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])
print(a[a>7])
# [ 8 9 10 11 12]
# 当然,也可以
condition = a > 7
print(condition)
# [[False False False False]
# [False False False True]
# [ True True True True]]
print(a[condition])
# [ 8 9 10 11 12]
有一个更厉害的函数专门用来进行数据筛选
这种筛选更强大,它还能做筛选结果的替换工作。 它可已将满足条件的位置变成你设定的数字。下面满足条件的,都改成 -1,不满足的,都还是 a 里面的数字。
condition = a > 7
print(np.where(condition, -1, a))
# [[ 1 2 3 4]
# [ 5 6 7 -1]
# [-1 -1 -1 -1]]
当然也可
condition = a > 7
print(np.where(condition, -1, 2))
# [[ 2 2 2 2]
# [ 2 2 2 -1]
# [-1 -1 -1 -1]]
甚至
condition = a > 7
b = -a - 1
print(np.where(condition, a, b))
# [[-2 -3 -4 -5]
# [-6 -7 -8 8]
# [ 9 10 11 12]]
基础运算
加减乘除,贼快贼牛逼
a = np.array([150, 166, 183, 170])
print(a + 3)
# [153 169 186 173]
# 我他妈连循环都不用,并行就加好了
矩阵运算
# 点乘
a = np.array([
[1, 2],
[3, 4]
])
b = np.array([
[5, 6],
[7, 8]
])
print(a.dot(b))
# [[19 22]
# [43 50]]
内积外积啥的就算了,我不懂,懒得学
数据分析
a.max(), a.min()
最大最小
a.sum(),a.prod()
累加累乘
a.size,np.count_nonzero(a)
总数和非零总数
np.mean(month_salary),np.median(month_salary)
平均数中位数
np.std(month_salary)
标准差
np.argmax(a),np.argmin(a)
最高最矮的索引
np.floor(a)),np.ceil(a))
抹零还是进位
a.clip(x, y)
将a中的元素限定在x和y之间,多砍少补
数据的保存和读取
数据的读取
使用 np.loadtxt()
功能,我们就能自定义地从文件中读取出数据
data = np.loadtxt("data/data.csv", delimiter=",", skiprows=1, dtype=np.int)
# delimiter参数指该文件中数据的分隔符,skiprows指跳过的行,一般跳过表头
print(data)
从字符串中读出数据
row_string = "20131, 10, 67, 20132, 11, 88, 20133, 12, 98, 20134, 8, 100, 20135, 9, 75, 20136, 12, 78"
data = np.fromstring(row_string, dtype=np.int, sep=",")
data = data.reshape(6, 3)
print(data)
# [[20131 10 67]
# [20132 11 88]
# [20133 12 98]
# [20134 8 100]
# [20135 9 75]
# [20136 12 78]]
Numpy并不能读取xls格式的数据,废物。
数据的保存
np.savetxt("data/save_data.csv", data, delimiter=",", fmt='%s')
# 保存为csv格式,其他人可查看,还可以用这种方法保存为txt格式
np.save("data/save_data.npy", data)
# 保存为二进制格式,其他人不可以查看
你甚至可以在一个npz格式文件中分别存储两个array,分别读取
train_data = np.array([1,2,3])
test_data = np.array([11,22,33])
np.savez("data/save_data.npz", train=train_data, test=test_data)
# train,test标签可以替换为别的,作为之后读取该组数据的索引
npz_data = np.load("data/save_data.npz")
print("train:", npz_data["train"])
# train: [1 2 3]
print("test:", npz_data["test"])
# test: [11 22 33]
标准数据的生成
填零填一填万物
zeros = np.zeros([2, 3]) # 需要指定shape
print("zeros:\n", zeros)
# [[0. 0. 0.]
# [0. 0. 0.]]
ones = np.ones([3, 2])
print("\nones:\n", ones)
# [[1. 1.]
# [1. 1.]
# [1. 1.]]
nines = np.full([2,3], 9)
print(nines)
# [[9 9 9]
# [9 9 9]]
创建规则数据
arange=range,好用
print("numpy arange:", np.arange(5))
# numpy arange: [0 1 2 3 4]
print("numpy arange:", np.arange(3, 10, 2)) # [3,10),步进2
# [3 5 7 9]
# 还有一个很好用的,平分区间的工具
print("linspace:", np.linspace(-1, 1, 6)) # [-1,1],画六个点
# [-1. -0.6 -0.2 0.2 0.6 1. ]
print("5 segments:", np.linspace(-1, 1, 5, endpoint=False)) # [-1,1],分成五段
# [-1. -0.6 -0.2 0.2 0.6]
一些没用的小技巧
data = np.array([
[1,2,3],
[4,5,6]
], dtype=np.int)
ones_like = np.ones_like(data)
# [[1 1 1]
# [1 1 1]]
print(np.zeros_like(data))
# [[0 0 0]
# [0 0 0]]
print(np.full_like(data, 6))
# [[6 6 6]
# [6 6 6]]
随机数据的生成
# 随机生成 [0, 1) 之间的数
dim1, dim2 = 3, 2
print(np.random.rand(dim1, dim2)) # 你还能继续添加 dim3 或更多,相当于传入了一个shape
# 会生成一个(3,2)形状的随机数矩阵
print(np.random.randn(dim1, dim2)) # 随机生成正态分布
print(np.random.randint(low=-3, high=6, size=10)) # 随即生成[low,high)范围内的整数
可以对已有的数据进行随机化处理
data = np.array([2,1,3,4,6])
print("选一个:", np.random.choice(data))
print("选多个:", np.random.choice(data, size=3))
print("不重复地选多个(不放回):", np.random.choice(data, size=3, replace=False))
print("带权重地选择:", np.random.choice(data, size=10, p=[0,0,0,0.2,0.8]))
np.random.shuffle(data) # 对数据进行重新随机排序
data = np.arange(12).reshape([6,2])
print("多维数据在第一维度上乱序:", np.random.permutation(data))
# [[ 6 7]
# [10 11]
# [ 8 9]
# [ 2 3]
# [ 4 5]
# [ 0 1]]
其他概率分布
# (均值,方差,size)
print("正态分布:", np.random.normal(1, 0.2, 10)) # 按照正态分布概率取值
# (最低,最高,size)
print("均匀分布:", np.random.uniform(-1, 1, 10)) # 按照均值概率分布取值
随机种子
在机器学习中,我们要对比两种随机初始化模型的优劣,或者在强化学习中要固定随机环境的随机序列,用于复现当前配置的情况,我们通常要做的事情就是伪随机。 简单说,就是每次都是一组随机,但是我可以后续再完整运行一遍一模一样的随机效果。比如生成两遍一模一样的随机序列。
为了达到这个目的,我们要了解 Numpy 中的 random seed 概念,随机种子。当我们把种子固定的时候(用一个数字),同一个种子(数字)产生的随机序列就会一样,类似于Minecraft中的map seed。
# seed(1) 代表的就是 1 号随机序列
np.random.seed(1)
print(np.random.rand(2,3)) # 这样每次生成的随机数据矩阵都是一模一样的
– end –
©著作权归作者所有