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 –




©著作权归作者所有