Python交互式学习-Numpy(基本操作)

目录

Numpy简介

Numpy安装:cmd:pip install numpy 

Numpy 和 Python List 的差别 

一、numpy维度

 代码示例讲解

总结

二、数据选择

 代码示例讲解

总结

三、基础运算

代码示例解析 

总结

四、数据形态

代码示例解析

总结 


Numpy简介

Numpy 这个名字(Number + Python)体现了它在数学计算,科学计算方面突出的贡献。

让我想要使用 Numpy 的场景:

  1. 需要批量处理数据的时候

  2. 机器学习,人工智能这些需要进行海量数据运算处理的地方

  3. 写游戏里面的物体运行逻辑时,经常涉及到矩阵、向量运算

  4. 机器人模拟环境,背后的环境反馈信息,全是靠批量数据算出来的

  5. 任何需要做统计的时候(爬虫爬完了信息后)

  6. 画图表之前,要对数据做一轮批量处理

  7. Blah blah

Numpy安装:cmd:pip install numpy 

当你安装好了,你就可以在自己的文件中写 Numpy 代码了。一般的流程是你先 import numpy。为了后续调用 numpy 更方便,我们通常在 import 完之后, 还给它一个缩写形式,as np。接下来你就能用 np.xxx 写 numpy 的代码了,在下面尝试一下吧。 

# my_numpy_test.py
import numpy as np

print(np.array([1, 2, 3]))

Numpy 和 Python List 的差别 

其实提到 Numpy,我建议你多做一些和 Python 原生 List 的对比, 因为它们从结构和形式上来说,是十分类似的。而且从一个你熟悉的 List 来类比学习 Numpy 也是一件简单的事情。

Numpy Array

在 Numpy 中,我们会一直使用到它的一种 Array 数据。

你只需要懂得如何 import numpy,并定义一个 array 就好了。

Numpy的核心优势:运算快。用专业的语言描述的话,Numpy 喜欢用电脑内存中连续的一块物理地址存储数据,因为都是连号的嘛,找到前后的号,不用跑很远, 非常迅速。而 Python 的 List 并不是连续存储的,它的数据是分散在不同的物理空间,在批量计算的时候,连号的肯定比不连号的算起来更快。因为找他们的时间更少了。

Numpy Array 存储的数据格式也有限制,尽量都是同一种数据格式,这样也有利于批量的数据计算。 所以只要是处理大规模数据的批量计算,Numpy 肯定会比 Python 的原生 List 要快。

import time

t0 = time.time()
# python list
l = list(range(100))
for _ in range(10000):
    for i in range(len(l)):
        l[i] += 1

t1 = time.time()
# numpy array
a = np.array(l)
for _ in range(10000):
    a += 1

print("Python list spend {:.3f}s".format(t1-t0))
print("Numpy array spend {:.3f}s".format(time.time()-t1))

运行结果如下 

 

一、numpy维度

 代码示例讲解

# ndim 是 NumPy 数组的一个属性,用于获取数组的维度数(即数组的阶数或维数)。
# 在 NumPy 中,每个数组(numpy.ndarray 对象)都有一个 ndim 属性,它返回一个整数,表示数组的维度数。
# 一维数组
# array1d = np.array([1, 2, 3, 4, 5])
# print(array1d.ndim)  # 输出: 1
# 二维数组
# array2d = np.array([[1, 2, 3], [4, 5, 6]])
# print(array2d.ndim)  # 输出: 2
# 三维数组
# array3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

# 创建一维数据
cars = np.array([5, 10, 12, 6])
print("数据:", cars, "\n维度:", cars.ndim)

# 创建二维数据。
cars = np.array([
 [5, 10, 12, 6],
 [5.1, 8.2, 11, 6.3],
 [4.4, 9.1, 10, 6.6]
])
print("数据:\n", cars, "\n维度:", cars.ndim)

# 创建三维数据
cars = np.array([
[
    [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)
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])
print(cars)
# 二维
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, :]

print("test1加维度后 ", test1)
print("test2加维度后 ", test2)

# 然后再在第一个维度上叠加
all_tests = np.concatenate([test1, test2])
print("括展后\n", all_tests)

# 合并数据
print("第一维度叠加:\n", np.concatenate([all_tests, all_tests], axis=0))
print("第二维度叠加:\n", np.concatenate([all_tests, all_tests], axis=1))

a = np.array([
[1,2,3],
[4,5,6]
])
b = np.array([
[7,8],
[9,10]
])

print(np.concatenate([a,b], axis=1))  # 这个没问题
# print(np.concatenate([a,b], axis=0))  # 这个会报错

# 横向合并竖向合并
a = np.array([
[1,2],
[3,4]
])
b = np.array([
[5,6],
[7,8]
])
print("竖直合并\n", np.vstack([a, b]))
print("水平合并\n", np.hstack([a, b]))

# 观察形态
cars = np.array([
[5, 10, 12, 6],
[5.1, 8.2, 11, 6.3],
[4.4, 9.1, 10, 6.6]
])

# count = 0
# for i in range(len(cars)):
#   for j in range(len(cars[i])):
#        count += 1
# print("总共多少测试数据:", count)
print("总共多少测试数据:", cars.size)
# 行列数
print("第一个维度:", cars.shape[0])
print("第二个维度:", cars.shape[1])
print("所有维度:", cars.shape)

总结

数据是多样的,有时候会跨越很多个维度。所以理解维度,理解形态对于科学计算中,数据的理解,都是十分重要的。 

二、数据选择

 代码示例讲解

# 数据选择
# 单个选择
a = np.array([1, 2, 3])
print("a[0]:", a[0])
print("a[1]:", a[1])

print("a[[0,1]]:\n", a[[0,1]])
print("a[[1,1,0]]:\n", a[[1,1,0]])
# 多维
b = np.array([
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
])
# 选第 2 行所有数
print("b[1]:\n", b[1])
# 选第 2 行,第 1 列的数
print("b[1,0]:\n", b[1, 0])
# 第一个拿的是数据位是 [1,2]
# 第二个拿的是 [0,3]
print("b[[1,0],[2,3]]:\n", b[[1, 0], [2, 3]])

#  切片划分
a = np.array([1, 2, 3])
print("a[0:2]:\n", a[0:2])
print("a[1:]:\n", a[1:])
print("a[-2:]:\n", a[-2:])
# 多维
b = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])

print("b[:2]:\n", b[:2])
print("b[:2, :3]:\n", b[:2, :3])
print("b[1:3, -2:]:\n", b[1:3, -2:])

# 条件筛选
# 上面选择一部分数据的方式比较没有选择性。什么叫有选择性呢?其实就是按照一定的筛选逻辑进行过滤,留下那些在数值上符合条件的数据。 而上面的方式,只能从位置上选择。举个例子你可能比较明白一些。
# 按位置选:请这队同学中,第 2 号到第 6 号的同学出列
# 按数条件:请这队同学中,身高高于 1.5 米的同学出列
# 两种方法不分好坏,区别在于你当前的使用场景。用合适的方法筛选数据就行。
a = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])
print(a[a> 7])
# 上面选取的是 a 数据中,大于 7 的数据。我们再拆开来看,a[a>7] 这里面究竟发生了什么。
condition = a > 7
print(condition)
print(a[condition])

# 条件筛选
# 上面选择一部分数据的方式比较没有选择性。什么叫有选择性呢?其实就是按照一定的筛选逻辑进行过滤,留下那些在数值上符合条件的数据。 而上面的方式,只能从位置上选择。举个例子你可能比较明白一些。
# 按位置选:请这队同学中,第 2 号到第 6 号的同学出列
# 按数条件:请这队同学中,身高高于 1.5 米的同学出列
# 两种方法不分好坏,区别在于你当前的使用场景。用合适的方法筛选数据就行
a = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])

print(a[a> 7])
# 上面选取的是 a 数据中,大于 7 的数据。拆开来看,a[a>7] 这里面是什么
condition = a > 7
print(condition)
print(a[condition])
# 既然 condition 是一种 True/False, 那么只要我们得到一个 True/False 数据,我都能做筛选。这才是它筛选的底层逻辑了
condition = (a > 7) & (a != 10)
print(a[condition])
# 除了这种直接用[]的形式,在 Numpy 中,还有一个专用的函数来做数据筛选
# 这种筛选更强大,它还能做筛选结果的替换工作。 它可已将满足条件的位置变成你设定的数字。下面满足条件的,都改成 -1,不满足的,都还是 a 里面的数字
condition = a > 7
print(np.where(condition, -1, a))
# 或者,不仅是满足条件的 condition,不满足条件的,也能变成你期望的数字
condition = a > 7
print(np.where(condition, -1, 2))
# 不光是数字,我还能让它和另外一个数据做条件上的整合
# 比如下面这样。如果满足 condition 要求,那么就会在对应的 True 位置放上 a 里的值
# 如果不满足 condition 要求,也就是在 condition 为 False 的地方放上 b 里对应位置的值。
condition = a > 7
b = -a - 1
print(np.where(condition, a, b))
# 所以 np.where() 函数真的十分强大,当我想要按条件选择、替换数据的时候,都是 np.where() 

总结

数据虽然有格式,但是如果要把数据用起来,还是得学会挑选和筛选。而今天介绍的单个、分段、条件筛选,都是数据工程师必备的一项技能。也是后续数据分析和机器学习的基石。

三、基础运算

代码示例解析 

# 基础运算
# 加减乘除
a = np.array([150, 166, 183, 170])
print("a + 3:", a + 3)
print("a - 3:", a - 3)
print("a * 3:", a * 3)
print("a / 3:", a / 3)
# 矩阵点积
a = np.array([
[1, 2],
[3, 4]
])
b = np.array([
[5, 6],
[7, 8]
])

print(a.dot(b))
print(np.dot(a, b))
# 矩阵还有很多其他的计算,比如 np.outer() 矩阵外积
# np.inner() 矩阵内积 (和 np.dot() 的用法稍稍有些不同
# 可以理解成 np.dot(a, b)= np.inner(a, b.T), 把 b 做一次转置

#  数据统计分析
a = np.array([150, 166, 183, 170])
print("最大:", np.max(a))
print("最小:", a.min())
print(a.sum())
print("累乘:", a.prod())
print("总数:", a.size)
a = np.array([0, 1, 2, 3])
print("非零总数:", np.count_nonzero(a))
month_salary = [1.2, 20, 0.5, 0.3, 2.1]
print("平均工资:", np.mean(month_salary))
print("工资中位数:", np.median(month_salary))
# 在统计数据分布的时候,还有一个值也比较重要
# standard deviation 标准差,用来描述正态分布
# 这个在机器学习中,特别是深度神经网络中也非常重要,特别用于权重的生成原则
month_salary = [1.2, 20, 0.5, 0.3, 2.1]
print("标准差:", np.std(month_salary))

# 特殊运算
a = np.array([150, 166, 183, 170])
name = ["小米", "OPPO", "Huawei", "诺基亚"]
high_idx = np.argmax(a)
low_idx = np.argmin(a)
print("{} 最高".format(name[high_idx]))
print("{} 最矮".format(name[low_idx]))
a = np.array([150.1, 166.4, 183.7, 170.8])
print("ceil:", np.ceil(a))
print("floor:", np.floor(a))
a = np.array([150.1, 166.4, 183.7, 170.8])
print("clip:", a.clip(160, 180))       # 自由取值界限

总结

其实 Numpy 中做数据运算的功能,比我这里列举的要多很多,我只是列举了一些我在数据分析和人工智能算法中,经常会使用到的一些功能。 还有更多的功能,可以在他的官方网站查找哦。 

四、数据形态

  • 改变形态
    • array[np.newaxis, :]
    • array.reshape()
    • array.ravel(), array.flatten()
    • array.transpose()
  • 合并
    • np.column_stack(), np.row_stack()
    • np.vstack(), np.hstack(), np.stack()
    • np.concatenate()
  • 拆解
    • np.vsplit(), np.hsplit(), np.split()

代码示例解析

# 数据形态
a = np.array([1,2,3,4,5,6])
a_2d = a[np.newaxis, :]
print(a.shape, a_2d.shape)
a = np.array([1,2,3,4,5,6])
a_none = a[:, None]
a_expand = np.expand_dims(a, axis=1)
print(a_none.shape, a_expand.shape)
a_squeeze = np.squeeze(a_expand)
a_squeeze_axis = a_expand.squeeze(axis=1)
print(a_squeeze.shape)
print(a_squeeze_axis.shape)
# 上述方法都是添加维度的方式,但是,在机器学习中,我们还有一个更常见的操作
# 是要改变 shape。维度的添加减少,只能添加减少一个维度,数据结构是不变的。
# 但是 np.reshape() 可以改变数据结构。 举个例子,a[None, :] 之后,a.shape 会在第一个维度上多一个 1
# 而 a.reshape([2,3]) 则可以更加自定义的将维度内的个数进行修改。 从而达到改变维度及尺寸
a = np.array([1,2,3,4,5,6])
a1 = a.reshape([2, 3])
a2 = a.reshape([3,1,2])
print("a1 shape:", a1.shape)
print(a1)
print("a2 shape:", a2.shape)
print(a2)
# 其实还有更多的改变形态的方法,比如让数据变直、展平 的 np.ravel(), np.flatten(),这两个比较特殊, 我会在 对速度有洁癖 这节的时候详细说明。
# 而在矩阵运算的时候,也有一种形态的转化,叫做矩阵转置,np.transpose(), 在机器学习中也用得很多
a = np.array([1,2,3,4,5,6]).reshape([2, 3])
aT1 = a.T
aT2 = np.transpose(a)
print(aT1)
print(aT2)
# 合并
# 一般来说,在数据分析统计,机器学习中的数据,都是以二维来存储的。
# 行是数据样本(第一维度),列是特征(第二维度)。 所以我们可以组合特征和组合样本。
# 比如将列column合并,特征 a 的数据和特征 b 的数据合并。
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)
# 一条条的数据 sample 合并
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)
# 上面的两种方法 np.column_stack() 和 np.row_stack() 和后面的 np.vstack()、np.hstack() 相比,
# 有些特殊之处,我们先看看使用 vstack 和 hstack 的案例,再说说不同处吧
feature_a = np.array([1,2,3,4,5,6])[:, None]
feature_b = np.array([11,22,33,44,55,66])[:, None]
c_stack = np.hstack([feature_a, feature_b])
print(c_stack)

sample_a = np.array([0, 1.1])[None, :]
sample_b = np.array([1, 2.2])[None, :]
c_stack = np.vstack([sample_a, sample_b])
print(c_stack)
# 用 column_stack 和 row_stack() 的时候,Numpy 自动帮你处理的维度信息,而用 vstack 和 hstack 的时候,你需要先确保维度信息是正确的,然后再合并。
# 有时候,你想要用统一的方法来处理各种不同情况的合并,np.concatenate() 是我最喜欢的方法,管它什么 vstack hstack 甚至是在更高维度上要合并, 我们都可以用 concatenate() 一个功能实现
a = np.array([
[1,2],
[3,4]
])
b = np.array([
[5,6],
[7,8]
])

print(np.concatenate([a, b], axis=0))
print(np.concatenate([a, b], axis=1))
# 拆解
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]))  # 分片成 [:2],[2:3], [3:]
# np.vsplit 是拿着刀沿着横向切分,那么 np.hsplit 就是沿纵向切分
# np.split() 能选择要切分的维度来自定义切分
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))  # 在第二维度,分片成 [:2],[2:3],[3:]

1
a = np.array(
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))  # 在第二维度,分片成 [:2],[2:3],[3:]

总结 

形态变化和合并拆解都是十分有用的功能,我们介绍了很多种实用的方法来完成这些事, 而懂了这些之后,数据分析和机器学习才算是真正迈入入圈的第一步。

  • 21
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值