目录
4.2.8 t1[[0, 2, 2], [0, 1, 3]]
5.4.1 np.where(t1 < 15000, 0, 10)
10.1 需求:统计行均值时,出现nan,如何处理nan的值?
10.2 需求:绘制出youybe的数据,制出评论数量的直方图
# 开篇
参考:
-
numpy:用来处理数值型的数据;
-
pandas:用来处理数值,以及字符串,字典、列表等数据的;
# 补充
zeros & ones
np.zeros((t2.shape[0], 1)) & ones_data = np.ones((t2.shape[0], 1)) :构造全为0的数据,构造全为1的数据:
zeros_data = np.zeros((t2.shape[0], 1)) # 创建一个3行1列的数组,全为0
ones_data = np.ones((t2.shape[0], 1)) # 创建一个3行1列的数组,全为1
t2 = np.arange(12, 24).reshape(3, 4)
print(t2)
print("*" * 100)
zeros_data = np.zeros((t2.shape[0], 1)) # 创建一个3行1列的数组,全为0
print(zeros_data)
print("*" * 100)
ones_data = np.ones((t2.shape[0], 1)) # 创建一个3行1列的数组,全为1
print(ones_data)
eye
np.eye(3) # 创建一个3行3列的对角矩阵:
t2 = np.eye(3) # 创建一个3行3列的对角矩阵
print(t2)
1. numpy数组的创建
1.1 array
np.array([1,2,3]) :创建numpy数组
import numpy as np
t1 = np.array([1, 2, 3])
print(t1)
print(type(t1))
1.2 range
range(10) :生成0-9的数组
# 默认生成0到9,十个数字
t2 = np.array(range(10))
print(t2)
1.3 arange
np.arange(4, 10, 2) :取4-10区间,步长为2
t3 = np.arange(4, 10, 2)
print(t3)
np.array(range(1, 4), dtype=float) :指定返回的类型为浮点数
t4 = np.array(range(1, 4), dtype=float)
print(t4)
print(t4.dtype)
1.4 常见的数据类型
类型 | 类型代码 | 说明 |
---|---|---|
int8, uint8 | i1, u1 | 有符号和无符号的8位(1个字节)整数 |
int16, uint16 | i2, u2 | 有符号和无符号的16位(2个字节)整数 |
int32, uint32 | i4, u4 | 有符号和无符号的32位(4个字节)整数 |
int64, uint64 | i8, u8 | 有符号和无符号的64位(8个字节)整数 |
float16 | f2 | 半精度浮点数 |
float32 | f4或f | 标准的单精度浮点数。与C的float兼容 |
float64 | f8或d | 标准的双精度浮点数。与C的double和Python的float对象兼容 |
float128 | f16或g | 扩展精度浮点数 |
complex64, complex128 | c8, c16 | 分别用两个32位、64位或128位浮点数表示的复数 |
complex256 | c32 | |
bool | ? | 存储True和False值的布尔类型 |
1.5 astype
np.astype("int8") :调整数据类型
# numpy中的bool类型
t5 = np.array([1, 1, 0, 1, 0, 1], dtype=bool)
print(t5)
print(t5.dtype)
# 调整数据类型
t6 = t5.astype("int8")
print(t6)
print(t6.dtype)
1.6 random.random() & round
random.random() & np.round(t7, 2) :随机生成小数 & 保留后两位小数
# 随机生成10个小数
t7 = np.array([random.random() for i in range(10)])
print(t7)
print(t7.dtype)
# 执行后两位小数
t8 = np.round(t7, 2)
print("*" * 100)
print(t8)
2. numpy数组计算和数组计算
2.1 reshape
np.arange(100, 124).reshape(4, 6) :默认生成100, 124区间数字,形成一个4行6列的数组
t6 = np.arange(100, 124).reshape(4, 6)
print(t6)
2.2 shape
np.shape :返回数组的元组
t1 = np.arange(12)
print(t1)
print(t1.shape) # (12,) 用元组返回数组的行数
print("*" * 100)
t2 = np.array([[1, 2, 3], [4, 5, 6]])
print(t2)
print(t2.shape) # (2, 3) 用元组返回数组的行数2,返回3数组的列数
print("*" * 100)
t3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(t3)
print(t3.shape) # (2, 2, 2) 第一个2代表数组有两个块,每块有2行,每行有2列
2.3 将一维数组变成多维数组
np.reshape(3, 4) :将一维数组变成多维数组
t4 = np.arange(12)
print(t4)
print("*" * 100)
print(t4.reshape((3, 4))) # 将t4一维数组变成3行4列的数组
print("*" * 100)
print(t4.reshape((3, 5))) # 3行5列的数组,报错
2.4 指定一维数组成为多维数组
np.arange(24).reshape((2, 3, 4)) :指定一维数组成为多维数组
# 指定一维数组成为多维数组
t5 = np.arange(24).reshape((2, 3, 4)) # 2个块,每块3行,每行4列
print(t5)
注:有返回值,但是不会对自身数据进行修改;
可以使用:变量 = 变量
方式赋值;
# 指定一维数组成为多维数组
t5 = np.arange(24).reshape((2, 3, 4)) # 2个块,每块3行,每行4列
print(t5)
print("*" * 100)
print(t5.reshape((4, 6)))
print("*" * 100)
print(t5) # 改变数组形状,不会改变数组内容
2.5 使用代表24行,仅1列
np.reshape(24, 1) :使用代表24行,仅有1列
注意:np.reshape(x, xx)
前面参数代表行,后面参数代表列;
t5 = np.arange(24)
print(t5.reshape(24, 1)) # 24行1列
2.6 将数组变成一维数组
np.reshape((t5.shape[0] * t5.shape[1],)) :将数组变成一维数组
t5.shape[0]
代表行;
t5.shape[1]
代表列;
相乘就是一个首元素等于24元组;
t5 = np.arange(24).reshape((4, 6))
print(t5)
print("*" * 100)
t6 = t5.reshape((t5.shape[0] * t5.shape[1],)) # 将数组变成一维数组
print(t6)
2.7 flatten
np.flatten() :快速的帮我们把数组变成一维数组;
t5 = np.arange(24).reshape((4, 6))
print(t5)
print("*" * 100)
print(t5.flatten()) # 将数组变成一维数组
2.8 数组和数组计算
np+2 :2加到数组中每个元素上
就是当numpy用于与树脂进行计算的时候,这个计算会被用于每一个数字;
t5 = np.arange(24).reshape((4, 6))
print(t5)
print("*" * 100)
print(t5 + 2) # 2加到数组中每个元素上
print("*" * 100)
print(t5 / 2) # 2除到数组中每个元素上
print("*" * 100)
print(t5 / 0) # 0除到数组中每个元素上
2.9 广播原则
问题:
- 数组形状为 (3, 3, 3) 能否与形状为 (3, 2) 的数组进行计算?不可以
- 数组形状为 (3, 3, 2) 能否与形状为 (3, 2) 的数组进行计算?可以
关键点:
- 维度对齐:可以将维度指的是
shape
所对应的数字个数。 - 例子:每列的数据减去每列的平均值的结果。
理解:
- 广播机制:NumPy 的广播机制允许形状不同的数组进行某些操作,但要求在维度和形状上能够相互兼容。一般情况下,计算中维度要么完全匹配,要么其中一个数组的维度为 1,以便进行广播。
举例:
- 形状为 (3, 3, 3) 的数组与形状为 (3, 2) 的数组进行操作时,必须要满足特定的维度对齐规则。
- 在这个例子中,可以考虑每列的数据减去每列的平均值的操作,即通过对齐和广播,使得形状不同的数组能够进行兼容操作。
总结:
- 检查数组的形状是否兼容,利用广播机制处理不同形状的数组。
- 实际操作时,需要考虑每个维度是否可以通过扩展或对齐使得操作合法。
2.9.1 数组t5 和数组t6 相加
t5 = np.arange(24).reshape((4, 6))
t6 = np.arange(100, 124).reshape((4, 6))
print(t5)
print("*" * 100)
print(t6)
print("*" * 100)
print(t5 + t6) # 两个数组相加
2.9.2 数组t5 和数组t8 相减
在数组运算中,不同的列,但是相同的行,是可以进行运算的;
t5 = np.arange(24).reshape((4, 6))
print(t5)
print("*" * 100)
t8 = np.arange(4).reshape(4, 1)
print(t8)
print("*" * 100)
print(t5 - t8) # 两个数组相减, 会在每一列上都减去相同维度的数组
t5 = np.arange(24).reshape((4, 6))
print(t5)
print("*" * 100)
t9 = np.arange(10)
print(t9)
print("*" * 100)
print(t5 - t9) # 在数组元素对应不上的时候,是无法进行运算
在元素对应不上的时候,是无法进行运算;
2.10 NumPy 中轴( axis )的概念及其应用
轴(axis)
在 NumPy 中,轴可以理解为方向,使用 0, 1, 2, ...
数字表示:
- 对于一维数组,只有一个
0
轴。 - 对于二维数组(如
shape=(2,2)
),有0
轴和1
轴。 - 对于三维数组(如
shape=(2,2,3)
),有0, 1, 2
轴。
计算应用
有了轴的概念后,计算会更加方便。例如:
- 计算一个二维数组的平均值,必须指定是计算哪个方向上的数字的平均值。
实例问题
在前面的知识中,轴在哪里?
import numpy as np
np.arange(0, 10).reshape((2, 5))
- 在
reshape
中,2
表示0
轴长度(包含数据的条数),5
表示1
轴长度(包含数据的条数)。因此,数组变成2x5
,共 10 个数据。
关键点总结
- 轴的编号:在 NumPy 中,从
0
开始编号,0
轴表示第一个维度,以此类推。 - 应用场景:在进行计算(如求和、平均等)时,需要明确指定计算的轴。
- 多维数组:多维数组中的轴编号根据数组的维度递增。
2.11 transpose
np.transpose(t2) :数组转置
行列转置,将行转置为列;
t2 = np.arange(12).reshape(3, 4)
print(t2)
print("*" * 100)
t3 = np.transpose(t2) # 转置
print(t3)
2.12 swapaxes
np.swapaxes(x, 0, 1) :0, 1 表示交换第一维和第二维
x = np.array([[1, 2, 3]])
print(x)
print("*" * 100)
y = np.swapaxes(x, 0, 1) # 0, 1 表示交换第一维和第二维
print(y)
np.swapaxes(x, 0, 2) :0, 2 表示交换第一维和第三维
x = np.array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]])
print(x)
print("*" * 100)
y = np.swapaxes(x, 0, 2) # 0, 2 表示交换第一维和第三维
print(y)
3. numpy读取本地数据
预备知识:
热门YouTube视频统计和评论:Trending YouTube Video Statistics and Comments (kaggle.com)
-
数据来源:
Kaggle 是一个国际知名的数据科学竞赛平台;
数据来自 Kaggle:https://www.kaggle.com/datasnaek/youtube/data
-
处理后的数据:
-
3.1 如何使用 NumPy 读取 CSV 文件
NumPy
提供了 np.loadtxt
函数用于读取 CSV 文件。它是一个多功能工具,可以读取文本文件中的数据,并将其转换为 NumPy
数组。
使用 np.loadtxt 的基本语法:
np.loadtxt(
frame,
dtype=float,
delimiter=',',
skiprows=0,
usecols=None,
unpack=False
)
参数 | 解释 | 示例 |
---|---|---|
fname | 文件名或文件路径。可以是字符串、生成器、.gz 或 .bz2 压缩文件 | 'data.csv' |
dtype | 数据类型,决定读取的数据类型。默认是 np.float | dtype=int |
delimiter | 分隔符,用于分隔 CSV 文件中的列。默认是空白字符 | delimiter=',' |
skiprows | 跳过文件开头的几行。通常用来跳过表头。 | skiprows=1 |
usecols | 指定要读取的列。可以是索引或元组类型。 | usecols=(0, 1, 2, 3) |
unpack | 如果为 True ,数据将会分解到不同的数组变量中。为 False 时,数据会读入一个数组 | unpack=True |
3.2 示例:读取 YouTube 视频数据
假设你有一个包含 YouTube 视频点击、喜欢、不喜欢、评论数量的 CSV 文件 youtube_data.csv
,其数据如下:
views,likes,dislikes,comment_count
1234567,12345,234,5678
2345678,23456,345,6789
...
可以按照以下步骤读取并处理这个数据:
import numpy as np
# 读取CSV数据
data = np.loadtxt(
'youtube_data.csv', # 文件名
dtype=float, # 数据类型
delimiter=',', # 分隔符
skiprows=1, # 跳过第一行(表头)
usecols=(0, 1, 2, 3) # 读取指定的列
)
# 分别获取不同列的数据
views, likes, dislikes, comment_count = data.T # 转置使数据分别赋值给变量
# 打印数据
print("Views:", views)
print("Likes:", likes)
print("Dislikes:", dislikes)
print("Comment Count:", comment_count)
重要提示:
- 数据来源:要确保你的 CSV 文件路径正确,并且格式与代码中的
delimiter
一致。 - 数据类型:根据你的数据情况选择合适的
dtype
。 - 列选择:如果你只需要特定列,可以使用
usecols
进行选择。
3.3 loadtxt
np.loadtxt() :文件读取
# coding: utf-8
import numpy as np
us_file_path = "../youyube_video_data/GBvideos-numpy.csv"
t1 = np.loadtxt(us_file_path, delimiter=',', dtype="int", encoding='utf-8')
print(t1)
4. numpy中的索引和切片
4.1 行切片
4.1.1 t1[2:]
t1[2:] :从第二行开始到最后一行进行切片
print(t1[2:]) # 2:表示从第3行开始
4.1.2 t1[[2, 8, 10]]
t1[[2, 8, 10]] :指定行切片
print(t1[[2, 8, 10]]) # 2,8,10表示第3,9,11行
4.1.3 取不连续的多行
t1[1, :] & t1[2:, :] & t1[[2, 10, 3], :] :取不连续的多行
t1[x, :]
:x代表行,在逗号后面,
代表着列,x, :
代表返回所有的列;t1[1, :]
:指定行取值,并展示所有的列;t1[2:, :]
:从第三行开始取值,并展示所有的列;t1[[2, 10, 3], :]
:指定行取值,并展示所有的列;
print(t1)
print("*" * 100)
print(t1[1, :]) # 1表示第2行
print("*" * 100)
print(t1[2:, :]) # 2:表示从第3行开始
print("*" * 100)
print(t1[[2, 10, 3], :]) # 2,10,3表示第3,11,4行
4.2 列切片
4.2.1 t1[:, 0]
t1[:, 0] :指定第0列切片
print(t1[:, 0]) # 0表示第1列
4.2.2 t1[:, 2:]
t1[:, 2:] :取连续的多列
print(t1[:, 2:]) # 2:表示从第3列开始
4.2.3 t1[:, [0, 2]]
t1[:, [0, 2]] :指定第0,2列切片
print(t1[:, [0, 2]]) # 0,2表示第1,3列
4.2.4 t1[2, 3]
t2 = t1[2, 3] :指定行、指定列切片
print(t1)
print("*" * 100)
t2 = t1[2, 3] # 2表示第3行,3表示第4列
print(t2)
print(type(t2))
4.2.5 t1[2:5, 1:4]
t2 = t1[2:5, 1:4] :指定多行、指定多列切片
取第3行到第5行,第2列到第4列的结果;
print(t1)
print("*" * 100)
t2 = t1[2:5, 1:4] # 2:5表示从第3行开始,1:4表示从第2列开始
print(t2)
4.2.6 t1[[0, 2], [0, 1]]
t2 = t1[[0, 2], [0, 1]] :高级索引取多个不同相邻的点
print(t1)
print("*" * 100)
t2 = t1[[0, 2], [0, 1]]
print(t2)
4.2.7 numpy高级索引方式
在 t2 = t1[[0, 2], [0, 1]]
中,[0, 1]
表示索引的位置,并不是代表具体的列,而是用于与 [0, 2]
组合来定位具体的元素。具体来说,这里 numpy
是采用了高级索引方式来处理这个表达式。
numpy
** 的高级索引会将索引对 (i, j)
视为独立的一对对待,而不是作为行列索引的组合。**
让我们详细解释这段代码的含义:
t2 = t1[[0, 2], [0, 1]]
t1[[0, 2], [0, 1]]
表示从t1
中获取索引(0, 0)
和(2, 1)
的元素。t1[[0, 2]]
选取了第1行和第3行:即[7426393, 78240, 13548, 705]
和[142819, 13119, 151, 1141]
t1[[0, 2], [0, 1]]
会将上述行中对应索引的元素取出,即(0, 0)
和(2, 1)
的元素。
简而言之,这段代码是取 t1
中 (0, 0)
位置的元素和 (2, 1)
位置的元素。因此,结果是 [7426393, 13119]
。
4.2.8 t1[[0, 2, 2], [0, 1, 3]]
t2 = t1[[0, 2, 2], [0, 1, 3]] :高级索引取多个不同相邻的点
print(t1)
print("*" * 100)
t2 = t1[[0, 2, 2], [0, 1, 3]]
print(t2)
5. numpy中更多的索引方式
5.1 t1[:, 2:4] = 0
t1[:, 2:4] = 0 :将所有行的3到4列都赋值为0
print(t1)
print("*" * 100)
t1[:, 2:4] = 0 # 2:4表示所有行从第3列开始都是0
print(t1)
5.2 t1 < 15000
t1 < 15000 :返回数组中小于15000的布尔值
print(t1)
print("*" * 100)
print(t1 < 15000) # 返回小于15000的布尔值
5.3 t1[t1 < 15000] = 10000
t1[t1 < 15000] = 10000 :小于15000的赋值为10000
print(t1)
print("*" * 100)
t1[t1 < 15000] = 10000 # 小于15000的赋值为10000
print(t1)
5.4 numpy中的三元运算符
5.4.1 np.where(t1 < 15000, 0, 10)
t2 = np.where(t1 < 15000, 0, 10) :小于15000的赋值为0,大于等于15000的赋值为10
(numpy的三元运算符)
print(t1)
print("*" * 100)
t2 = np.where(t1 < 15000, 0, 10) # 小于15000的赋值为0,大于等于15000的赋值为10
print(t2)
5.5 numpy中的clip裁剪
5.5.1 clip
t2 = t1.clip(15000, 50000) :小于15000的赋值为15000,大于等于50000的赋值为50000
print(t1)
print("*" * 100)
t2 = t1.clip(15000, 50000) # 小于15000的赋值为15000,大于等于50000的赋值为50000
print(t2)
6. numpy数据的拼接
-
数组的拼装:
-
注意:
竖直拼接的时候:每一列代表的意义都必须相同;
如果每一列的意义不同,这时候应该交换某一组数的列,让其和另外一类相同;
np.vstack((t1,t2))
:竖直拼接;将第二个数组拼接在第一个数组的最后行后面np.hstack((t1,t2))
:水平拼接;将第二个数组的列拼接到一个数组每一个最后列后面 -
6.1 vstack & hstack
np.vstack((t1,t2)) & np.hstack((t1,t2))
t2 = np.arange(12).reshape(2, 6)
print(t2)
print("*" * 100)
t3 = np.arange(12, 24).reshape(2, 6)
print(t3)
print("*" * 100)
t4 = np.vstack((t2, t3)) # 纵向堆叠
print(t4)
print("*" * 100)
t5 = np.hstack((t2, t3)) # 横向堆叠
print(t5)
6.2 数组的行列交换
-
数组的行列交换:
t[[1, 2], :] = t[[2, 1], :] # 行1和2交换
t[:, [0, 2]] = t[:, [2, 0]] # 列0和2交换
- 示例:
t = np.arange(12, 24).reshape(3, 4) print(t) print("*" * 100) t[[1, 2], :] = t[[2, 1], :] # 行1和2交换 print(t) print("*" * 100) t[:, [0, 2]] = t[:, [2, 0]] # 列0和2交换 print(t)
6.3 将两组数据拼接在一起进行科学计算
t2 = np.arange(12, 24).reshape(3, 4)
print(t2)
print("*" * 100)
zeros_data = np.zeros((t2.shape[0], 1)) # 创建一个3行1列的数组,全为0
print(zeros_data)
print("*" * 100)
ones_data = np.ones((t2.shape[0], 1)) # 创建一个3行1列的数组,全为1
print(ones_data)
print("*" * 100)
us = np.hstack((t2, zeros_data)) # 分别添加0和1的列
uk = np.hstack((t2, ones_data)) # 分别添加0和1的列
print(us)
print("*" * 100)
print(uk)
print("*" * 100)
final_data = np.vstack((us, uk))
print(final_data)
7. numoy中的随机方法
7.1 argmax
np.argmax(t, axis=0) :获取最大值的位置
np.argmax
用于返回数组中最大值的索引。axis=0
表示沿数组的第0轴(即列)进行操作。- 获取数组
t
沿指定轴的最大值位置:
np.argmax(t, axis=0)
7.2 获取最小值的位置
np.argmin(t, axis=1) :获取最小值的位置
np.argmin
用于返回数组中最小值的索引。axis=1
表示沿数组的第1轴(即行)进行操作。- 获取数组
t
沿指定轴的最小值位置:
np.argmin(t, axis=1)
7.3 np.zeros((3, 4))
np.zeros((3, 4)) :创建一个全0的数组
np.zeros
创建一个指定形状的全0数组。- 这里创建的数组形状为
(3, 4)
,即3行4列的数组。 - 创建一个形状为
(3, 4)
的全0数组:
np.zeros((3, 4))
7.4 np.ones((3, 4))
np.ones((3, 4)) :创建一个全1的数组
np.ones
创建一个指定形状的全1数组。- 这里创建的数组形状为
(3, 4)
,即3行4列的数组。 - 创建一个形状为
(3, 4)
的全1数组:
np.ones((3, 4))
7.5 eye
np.eye(3):创建一个对角线为1的正方形数组(方阵)
np.eye
创建一个单位矩阵,即对角线为1,其他元素为0的矩阵。- 这里创建的单位矩阵是一个3x3的方阵。
- 创建一个形状为
(3, 3)
的单位矩阵:
np.eye(3)
7.6 案例
7.6.1 获取最大值的位置
np.argmax(t, axis=0) :获取最大值的位置
t = np.eye(4)
print(t)
print("*" * 100)
print(np.argmax(t, axis=0))
7.6.2 获取最小值的位置
np.argmax(t, axis=1) :获取最小值的位置
t = np.eye(4)
print(t)
print("*" * 100)
print(np.argmax(t, axis=0)) # 求最大下标的索引值
t[t == 1] = -1 # 将1替换为-1
print("*" * 100)
print(t)
print("*" * 100)
print(np.argmin(t, axis=1)) # 求最小下标的索引值
7.7 numpy生成随机数
-
分布的补充:
1.均匀分布:在相同的大小范围内的出现概率是等可能的;
2.正态分布:呈钟型,两头低,中间高,左右对称;
7.8 生成二维均匀分布的随机数组
np.random.rand(2, 3) :生成二维均匀分布的随机数组
函数: np.random.rand(d0, d1, ..., dn)
;
参数描述: d0, d1, ..., dn
维度的均匀分布的随机数组;
解释:创建 d0
到 dn
维度的浮点数随机数组,范围从 0 到 1;
import numpy as np
array_rand = np.random.rand(2, 3)
print(array_rand)
# 输出示例:[[0.17678197 0.83879827 0.59548066]
# [0.00811262 0.05331716 0.16584186]]
7.9 生成二维标准正态分布随机数组
np.random.randn(2, 3) :生成二维标准正态分布随机数组
函数:np.random.randn(d0, d1, ..., dn)
参数描述: d0, d1, ..., dn
维度的标准正态分布随机数组
解释:创建 d0
到 dn
维度的标准正态分布随机数组,均值 0,标准差 1;
array_randn = np.random.randn(2, 3)
print(array_randn)
# 输出示例:[[-0.56922926 -0.46477167 1.53166647]
# [ 0.51248294 1.61693618 -1.09743841]]
7.10 生成二维整数随机数组
np.random.randint(0, 10, (2, 3)) :生成二维整数随机数组
函数:np.random.randint(low, high, size)
参数描述: low
: 起始值、 high
: 结束值、 size
: 形状
解释:从 low
到 high
之间生成随机整数,形状由 size
指定;
array_randint = np.random.randint(0, 10, (2, 3))
print(array_randint)
# 输出示例:[[7 4 2]
# [0 8 4]]
7.11 生成二维均匀分布的随机数组
np.random.uniform(0, 1, (2, 3)) :生成二维均匀分布的随机数组
函数:np.random.uniform(low, high, size)
参数描述: low
: 起始值、 high
: 结束值、 size
: 形状
解释:产生具有均匀分布的随机数数组,范围从 low
到 high
;
array_uniform = np.random.uniform(0, 1, (2, 3))
print(array_uniform)
# 输出示例:[[0.38019132 0.8574209 0.34507822]
# [0.28912108 0.95612227 0.33245865]]
7.12 生成二维正态分布随机数组
np.random.normal(0, 1, (2, 3)) :生成二维正态分布随机数组
函数:np.random.normal(loc, scale, size)
参数描述:loc
: 均值、 scale
: 标准差、 size
: 形状
解释:从正态分布中抽取随机样本,均值为 loc
,标准差为 scale
;
array_normal = np.random.normal(0, 1, (2, 3))
print(array_normal)
# 输出示例:[[ 0.32859216 -0.89933692 0.53515463]
# [ 0.89322116 -0.13982256 -1.05578878]]
7.13 设置随机数种子
np.random.seed(42) :设置随机数种子
函数:np.random.seed(s)
参数描述:s
: 随机数种子
解释:设置随机数种子,可以确保生成的随机数相同;
np.random.seed(42)
array_seed = np.random.rand(2, 3)
print(array_seed)
# 输出示例:[[0.37454012 0.95071431 0.73199394]
# [0.59865848 0.15601864 0.15599452]]
8. numpy中的nan和inf
8.1 np.nan 和np.inf
NaN
用于表示一个未定义或不可表示的值:- 从文件读取数据时,如果有缺失值,将其表示为
NaN
。 - 进行不合理的计算时,例如 0 除以 0,结果会是
NaN
。
- 从文件读取数据时,如果有缺失值,将其表示为
import numpy as np
nan_value = np.nan
print(nan_value) # 输出: nan
print(type(nan_value)) # 输出: <class 'float'>
-
Inf
表示正无穷大,-Inf
表示负无穷大。它们通常出现在以下情况中:- 进行无穷大的计算时,例如除数为 0。
- 超过数值范围时,例如超出浮点数表示范围的结果。
生成
Inf
和-Inf
:
import numpy as np
inf_value = np.inf
neg_inf_value = -np.inf
print(inf_value) # 输出: inf
print(type(inf_value)) # 输出: <class 'float'>
print(neg_inf_value) # 输出: -inf
print(type(neg_inf_value)) # 输出: <class 'float'>
- 使用
NaN
和Inf
的案例:
- 读取文件中的缺失值
import numpy as np data = np.genfromtxt('data.csv', delimiter=',') # 如果文件中某些数据缺失,它们会被读取为 NaN
- 处理无效计算
result = np.log(-1) print(result) # 输出: nan
- 处理无穷大
result = 1.0 / 0.0 print(result) # 输出: inf
8.2 count_nonzero & isnan
np.nan 和np.inf 的注意点 & np.count_nonzero(t != t) & np.isnan(t)
两个nan是不相等的:np.nan == np.nan # False
;
- np.nan != np.nan:
np.nan != np,nan # True
; - nan和任何值计算都为nan;
可以利用以上的特性,判断数组中nan的个数:
t = np.array([1., 2., np.nan, np.nan])
print(t)
print("*" * 100)
t2 = np.count_nonzero(t != t) # 判断t中为nan的个数
print(t2)
由于2,那么如何判断一个数字是否为nan呢:
- 通过
np.isnan(a)
来判断,返回bool类型,比如希望把nan替换为0;
t = np.array([1., 2., np.nan, np.nan])
print(t)
print("*" * 100)
t[np.isnan(t)] = 0 # 将nan替换为0
print(t)
np.isnan(t) :
9. numpy常用统计方法
- 标准差:当值越小,数值越聚集,当值越大,数值越离散;
9.1 sum
np.sum(t3, axis=0) :统计行或列的结果
t3 = np.arange(12).reshape(3, 4)
print(t3)
print("*" * 100)
t4 = np.sum(t3, axis=0) # 统计每行全部列的结果
print(t4)
print("*" * 100)
t5 = np.sum(t3, axis=1) # 统计每行全部行的结果
print(t5)
9.2 nan与任何值计算都是nan
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
t3[2, 3] = np.nan # 给浮点数组赋值 NaN
print(t3)
print("*" * 100)
print(np.sum(t3, axis=0))
print("*" * 100)
print(np.nansum(t3, axis=0)) # 使用 np.nansum 忽略 NaN 进行求和
9.3 numpy中的nan的注意点
nan处理会存在的情况:
在计算统计中,如果把nan的值替换为0进行统计,这样并不合适,替换之前的平均值如果大于0,替换之后均值肯定会变小;
所以一般的方式是把缺失的数值替换为均值(中值)或者是直接删除缺失值的一行:
9.4 axis 参数
axis=None
: 默认值,对整个数组进行操作。
axis=0
: 沿垂直方向(列)操作。
axis=1
: 沿水平方向(行)操作。
9.5 sum 求和
求和: np.sum(t3, axis=None)
- 计算数组元素的总和。
axis=None
表示对整个数组进行求和;指定轴(0 或 1)时对特定轴进行求和。
9.6 mean 均值
均值: np.mean(t3, axis=None)
- 计算数组元素的均值(平均值)。
axis=None
表示对整个数组计算均值;指定轴(0 或 1)时对特定轴计算均值。
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
print(np.mean(t3, axis=None)) # 统计全部元素的均值
9.7 median 中值
中值: np.median(t, axis=None)
- 计算数组元素的中位数。
axis=None
表示对整个数组计算中位数;指定轴(0 或 1)时对特定轴计算中位数。
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
print(np.median(t3, axis=None)) # 统计全部元素的中值
9.8 max 最大值
最大值: np.max(t3, axis=None)
- 返回数组中的最大值。
axis=None
表示返回整个数组中的最大值;指定轴(0 或 1)时对特定轴返回最大值。
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
print(np.max(t3, axis=None)) # 统计全部元素的最大值
9.9 min 最小值
最小值: np.min(t3, axis=None)
- 返回数组中的最小值。
axis=None
表示返回整个数组中的最小值;指定轴(0 或 1)时对特定轴返回最小值。
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
print(np.min(t3, axis=None)) # 统计全部元素的最小值
9.10 ptp 极值范围
极值范围: np.ptp(t3, axis=None)
极值 是指数组中最大值与最小值之间的差值,即 max - min。极值的计算函数是 numpy.ptp()(ptp 意为 "peak to peak")。
公式:
函数: t.ptp(axis=None)
- 计算数组中最大值和最小值之差。
axis=None
表示对整个数组计算极值范围;指定轴(0 或 1)时对特定轴计算极值范围。
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
print(np.ptp(t3, axis=None)) # 统计全部元素的极值范围
9.11 std 标准差
标准差: np.std(t3, axis=None)
- 标准差用于衡量数据集中的值偏离均值的程度。标准差越大,表示数据点离均值越远;标准差越小,表示数据点更集中于均值附近。
- 计算数组元素的标准差。
axis=None
表示对整个数组计算标准差;指定轴(0 或 1)时对特定轴计算标准差。
t3 = np.arange(12, dtype=float).reshape(3, 4)
print(t3)
print("*" * 100)
print(np.std(t3, axis=None)) # 统计全部元素的标准差
10. numpy中填充nan和youtube数据的练习
10.1 需求:统计行均值时,出现nan,如何处理nan的值?
将统计除nan列的均值,再将均值赋值给当前列的nan值上;
10.1.1 模拟nan数据
t2 = np.arange(12).reshape((3, 4)).astype("float")
print(t2)
print("*" * 100)
t2[1, 2:] = np.nan # 给浮点数组赋值 NaN
print(t2)
10.1.2 实现
def fill_ndarray(t2):
for i in range(t2.shape[1]): # 遍历每一列
temp_col = t2[:, i] # 当前列
nan_num = np.count_nonzero(temp_col != temp_col) # 当前列中NaN的个数
if nan_num != 0:
temp_not_nan_col = temp_col[temp_col == temp_col] # 当前列中非NaN的列
temp_col[np.isnan(temp_col)] = temp_not_nan_col.mean() # 将NaN替换为当前列中非NaN的平均值
return t2
if __name__ == '__main__':
t2 = np.arange(12).reshape((3, 4)).astype("float")
t2[1, 2:] = np.nan # 给浮点数组赋值 NaN
print(t2)
print("*" * 100)
t3 = fill_ndarray(t2)
print(t3)
10.1.3 分析
统计存在有nan的列,将nan的列中其它不等于nan的值进行mean求出均值,
在把均值赋值给当前列中所有等于nan的值,
再return返回给t2;
10.2 需求:绘制出youybe的数据,制出评论数量的直方图
10.2.1 数据获取
import numpy as np
us_file_path = "../youyube_video_data/GBvideos-numpy.csv"
t1 = np.loadtxt(us_file_path, delimiter=',', dtype="int", encoding='utf-8')
print(t1)
print("*" * 100)
# 取评论的数据
t_us_comments = t1[:-1]
print(t_us_comments.max(), t_us_comments.min())
print("*" * 100)
# 选择比500万评论数小的数据
t_us_comments = t_us_comments[t_us_comments < 5000000]
print(t_us_comments.max(), t_us_comments.min())
10.2.2 直方图
import numpy as np
from pyecharts.charts import Bar
from pyecharts import options as opts
us_file_path = "../youyube_video_data/GBvideos-numpy.csv"
t1 = np.loadtxt(us_file_path, delimiter=',', dtype="int", encoding='utf-8')
t_us_comments = t1[:-1] # 获取最后一列评论数
# 过滤掉评论数小于等于0的数据
t_us_comments = t_us_comments[t_us_comments > 0]
# 过滤掉评论数超过5万的数据
t_us_comments = t_us_comments[t_us_comments < 50000]
# 数据分组:选择合适的分组区间
bins = np.linspace(t_us_comments.min(), t_us_comments.max(), 100)
hist, bin_edges = np.histogram(t_us_comments, bins=bins) # 计算直方图
bar = Bar()
# 设置 x 轴和 y 轴的值
# 构造 x 轴的数据,按照固定间隔
x_labels = [f"{i * 1000}" for i in range(len(bin_edges))]
bar.add_xaxis(x_labels[:-1]) # 只保留到倒数第二个标签,避免过多重复
bar.add_yaxis("评论数", hist.tolist(), label_opts=opts.LabelOpts(is_show=False)) # 设置 label_opts,is_show=False 表示不显示标签
# 设置图表的标题和坐标轴
bar.set_global_opts(
title_opts=opts.TitleOpts(title="视频评论数直方图"),
xaxis_opts=opts.AxisOpts(name="评论数区间", axislabel_opts={"rotate": 1000}),
yaxis_opts=opts.AxisOpts(name="频次", type_="log", max_=50000) # 使用对数刻度
)
# 渲染图表并保存
bar.render("comments_histogram.html")
print("直方图已保存为 'comments_histogram.html'")