【Python数据科学快速入门系列 | 03】玩转数据摘取:Numpy的索引与切片

这是机器未来的第41篇文章

原文首发地址:https://blog.csdn.net/RobotFutures/article/details/126176343

1. 索引与切片

numpy数据容器ndarray和list一样,同样支持索引和切片访问和修改。更多索引和切片基础知识详见之前的博文【Python数据容器之序列】

在这里,我们使用sklearn自带的数据集——鸢尾花数据集来举例。

# 导入鸢尾花数据集
import numpy as np

data = []
with open(file='iris.txt',mode='r') as f:
    # 打印标题行
    print(f"title:{f.readline()}")

    # f.readlines()读取文件所有行
    for line in f.readlines():  # 每次取一行数据
        data.append(line.strip().split(','))
title:sepal_length,sepal_width,petal_length,petal_width,target_names
# 从上面代码的执行结果可以看到,数据集有5个标题,对应5列数据
# 前4列为鸢尾花的特征,最后1列为鸢尾花的分类
# sepal_length - 花萼长度
# sepal_width - 花萼宽度
# petal_length - 花瓣长度
# petal_width - 花萼宽度
# target_names - 目标名称

# 取2行数据,看一下数据值与类型
data[:2]
[['5.1', '3.5', '1.4', '0.2', '0'], ['4.9', '3.0', '1.4', '0.2', '0']]
# 从上面列表提取的前2行数据可以看到,它的数据类型为字符串,在将data从list转换为ndarray数组时,直接做数据类型转换,转换为float
data = np.array(data, dtype=float)

# 和列表一样,ndarray对象也可以使用切片的方式访问数组
# 这里提取前4行数据查看一下数据值的范围及数据类型
data[:4]  
array([[5.1, 3.5, 1.4, 0.2, 0. ],
       [4.9, 3. , 1.4, 0.2, 0. ],
       [4.7, 3.2, 1.3, 0.2, 0. ],
       [4.6, 3.1, 1.5, 0.2, 0. ]])

1.1 如何提取指定列的数据

思考:在做数据预处理时可能会分析特征数据与标签数据的相关性,我们需要提取指定列的数据与标签数据做分析,那么如何提取某一列数据呢?
使用切片来提取。先看一下数据的shape

data.shape
(150, 5)

可以看到是150行,5列,现在需要提取第3列数据,可以这样操作

# 逗号前的:表示提取全部行,逗号后的2表示提取第3列
data[:,2]
array([1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.6, 1.4,
       1.1, 1.2, 1.5, 1.3, 1.4, 1.7, 1.5, 1.7, 1.5, 1. , 1.7, 1.9, 1.6,
       1.6, 1.5, 1.4, 1.6, 1.6, 1.5, 1.5, 1.4, 1.5, 1.2, 1.3, 1.4, 1.3,
       1.5, 1.3, 1.3, 1.3, 1.6, 1.9, 1.4, 1.6, 1.4, 1.5, 1.4, 4.7, 4.5,
       4.9, 4. , 4.6, 4.5, 4.7, 3.3, 4.6, 3.9, 3.5, 4.2, 4. , 4.7, 3.6,
       4.4, 4.5, 4.1, 4.5, 3.9, 4.8, 4. , 4.9, 4.7, 4.3, 4.4, 4.8, 5. ,
       4.5, 3.5, 3.8, 3.7, 3.9, 5.1, 4.5, 4.5, 4.7, 4.4, 4.1, 4. , 4.4,
       4.6, 4. , 3.3, 4.2, 4.2, 4.2, 4.3, 3. , 4.1, 6. , 5.1, 5.9, 5.6,
       5.8, 6.6, 4.5, 6.3, 5.8, 6.1, 5.1, 5.3, 5.5, 5. , 5.1, 5.3, 5.5,
       6.7, 6.9, 5. , 5.7, 4.9, 6.7, 4.9, 5.7, 6. , 4.8, 4.9, 5.6, 5.8,
       6.1, 6.4, 5.6, 5.1, 5.6, 6.1, 5.6, 5.5, 4.8, 5.4, 5.6, 5.1, 5.1,
       5.9, 5.7, 5.2, 5. , 5.2, 5.4, 5.1])

1.2 如何分离特征数据和标签数据

思考:现在我们已经加入了数据集,为了训练模型,我们需要将特征数据(即输入)和标签数据(即结果)分离,使用特征输入训练后获得训练的标签结果,然后再与标签数据(实际结果)比对。该如何分离呢?

# 使用切片提取前4列数据作为特征数据
X_data = data[:, :4]  # 或者 X_data = data[:, :-1]

# 使用切片提取最后1列数据作为标签数据
y_data = data[:, -1]

data.shape, X_data.shape, y_data.shape
((150, 5), (150, 4), (150,))
# 查看未分割的数据集的前5个样本
data[:5]
array([[5.1, 3.5, 1.4, 0.2, 0. ],
       [4.9, 3. , 1.4, 0.2, 0. ],
       [4.7, 3.2, 1.3, 0.2, 0. ],
       [4.6, 3.1, 1.5, 0.2, 0. ],
       [5. , 3.6, 1.4, 0.2, 0. ]])
# 查看特征数据前5个样本
X_data[:5]
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2]])
# 查看标签数据前5个样本
y_data[:5]
array([0., 0., 0., 0., 0.])

从结果可以看到,我们已经特征数据和标签数据已经分割开了。

1.3 如何小尺寸的动态加载样本,而不是一下子加载全部数据集呢?

思考:遇到数据集非常大,数据样本数非常多,需要分批次加载数据,每次批次的样本数为32,那么如何提取呢?

动态加载批尺寸数据,使用了生成器的内容,如果不太了解,可以阅读博主之前写的文章:如何优雅地加载海量数据

# 首先验证一下提取前32个样本,
X_data[:32,:]
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2],
       [5.4, 3.9, 1.7, 0.4],
       [4.6, 3.4, 1.4, 0.3],
       [5. , 3.4, 1.5, 0.2],
       [4.4, 2.9, 1.4, 0.2],
       [4.9, 3.1, 1.5, 0.1],
       [5.4, 3.7, 1.5, 0.2],
       [4.8, 3.4, 1.6, 0.2],
       [4.8, 3. , 1.4, 0.1],
       [4.3, 3. , 1.1, 0.1],
       [5.8, 4. , 1.2, 0.2],
       [5.7, 4.4, 1.5, 0.4],
       [5.4, 3.9, 1.3, 0.4],
       [5.1, 3.5, 1.4, 0.3],
       [5.7, 3.8, 1.7, 0.3],
       [5.1, 3.8, 1.5, 0.3],
       [5.4, 3.4, 1.7, 0.2],
       [5.1, 3.7, 1.5, 0.4],
       [4.6, 3.6, 1. , 0.2],
       [5.1, 3.3, 1.7, 0.5],
       [4.8, 3.4, 1.9, 0.2],
       [5. , 3. , 1.6, 0.2],
       [5. , 3.4, 1.6, 0.4],
       [5.2, 3.5, 1.5, 0.2],
       [5.2, 3.4, 1.4, 0.2],
       [4.7, 3.2, 1.6, 0.2],
       [4.8, 3.1, 1.6, 0.2],
       [5.4, 3.4, 1.5, 0.4]])
# 增加一个自增的索引即可滑动提取32个样本:X_data[32*i:32*(i+1),:]

# 定义一个生成器,动态提取批尺寸样本
def get_data(X_data):
    # len(X_data)//32,最后不够32个一组的样本丢弃
    for i in range(len(X_data)//32):
        yield X_data[32*i:32*(i+1),:]

f_batch_data = get_data(X_data=X_data)
print(next(f_batch_data))

[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]
 [5.4 3.9 1.7 0.4]
 [4.6 3.4 1.4 0.3]
 [5.  3.4 1.5 0.2]
 [4.4 2.9 1.4 0.2]
 [4.9 3.1 1.5 0.1]
 [5.4 3.7 1.5 0.2]
 [4.8 3.4 1.6 0.2]
 [4.8 3.  1.4 0.1]
 [4.3 3.  1.1 0.1]
 [5.8 4.  1.2 0.2]
 [5.7 4.4 1.5 0.4]
 [5.4 3.9 1.3 0.4]
 [5.1 3.5 1.4 0.3]
 [5.7 3.8 1.7 0.3]
 [5.1 3.8 1.5 0.3]
 [5.4 3.4 1.7 0.2]
 [5.1 3.7 1.5 0.4]
 [4.6 3.6 1.  0.2]
 [5.1 3.3 1.7 0.5]
 [4.8 3.4 1.9 0.2]
 [5.  3.  1.6 0.2]
 [5.  3.4 1.6 0.4]
 [5.2 3.5 1.5 0.2]
 [5.2 3.4 1.4 0.2]
 [4.7 3.2 1.6 0.2]
 [4.8 3.1 1.6 0.2]
 [5.4 3.4 1.5 0.4]]

2. 高级索引

numpy的ndarray对象支持数组索引、布尔索引和花式索引。

2.1 数组索引

例如下面这个代码,[0,4,7],[0, 1, 2]提取的数据样本实际是(0,0),(4,1),(7,2),其实就是对位取数

X_data[[0,4,7],[0, 1, 2]]
array([5.1, 3.6, 1.5])
X_data[:7,:]
array([[5.1, 3.5, 1.4, 0.2],
       [4.9, 3. , 1.4, 0.2],
       [4.7, 3.2, 1.3, 0.2],
       [4.6, 3.1, 1.5, 0.2],
       [5. , 3.6, 1.4, 0.2],
       [5.4, 3.9, 1.7, 0.4],
       [4.6, 3.4, 1.4, 0.3]])

可以和X_data原始特征数据比对一下,发现与描述一致。

2.2 布尔索引

布尔索引在机器学习和深度学习时被大量使用,在过滤数据时非常有用。
其格式为X[条件表达式]

思考:现在我需要分析花萼宽度>4.5的样本在整个样本中的比例是多少,该如何处理呢?

# 索引的第一个值为样本行数,选择所有,第二个值为指定的第一列

X_data_column0 = X_data[X_data[:,0]>4.5]
percent = len(X_data_column0)/len(X_data)
percent
0.9666666666666667

可以看到花萼宽度>4.5的样本占比非常高。

2.3 花式索引

将来再研究。

写在末尾:

  • 博客简介:专注AIoT领域,追逐未来时代的脉搏,记录路途中的技术成长!
  • 专栏简介:从0到1掌握数据科学常用库Numpy、Matploblib、Pandas。
  • 面向人群:AI初级学习者
  • 专栏计划:接下来会逐步发布跨入人工智能的系列博文,敬请期待

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

机器未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值