在将数据用于训练机器学习模型之前,您必须知道如何加载数据。
刚开始时,最好使用逗号分隔值(.csv)等标准文件格式的小型内存数据集。
在本教程中,您将学习如何从头开始在 Python 中加载数据,包括:
- 如何加载 CSV 文件。
- 如何将文件中的字符串转换为浮点数。
- 如何将文件中的类别值转换为整数。
通过我的新书《从零开始的机器学习算法》启动您的项目,其中包括分步教程和所有示例的 Python 源代码文件。
让我们开始吧。
- 2016 年 11 月更新:添加了一个改进的数据加载函数以跳过空行。
- 2018 年 8 月更新:测试并更新以与 Python 3.6 配合使用。

如何在 Python 中从头开始加载机器学习数据
图片作者:Amanda B,保留部分权利。
描述
逗号分隔值
小型数据集的标准文件格式是逗号分隔值(CSV)。
最简单的形式是,CSV 文件由数据行组成。每行都使用逗号(“,”)分隔成列。
您可以在 RFC 4180:逗号分隔值(CSV)文件的通用格式和 MIME 类型 中了解有关 CSV 文件格式的更多信息。
在本教程中,我们将练习加载两种不同的标准机器学习数据集,格式为 CSV。
Pima 印第安人糖尿病数据集
第一个是 Pima 印第安人糖尿病数据集。它包含 768 行和 9 列。
文件中的所有值都是数字,特别是浮点值。我们将首先学习如何加载文件,然后学习如何将加载的字符串转换为数字值。
鸢尾花物种数据集
我们将处理的第二个数据集是鸢尾花数据集。
它包含 150 行和 4 列。前 3 列是数字。不同之处在于,类别值(最后一列)是一个字符串,表示花的物种。我们将学习如何将数字列从字符串转换为数字,以及如何将花卉物种字符串转换为我们可以始终如一使用的整数。
教程
本教程分为3个部分:
- 加载文件。
- 加载文件并将字符串转换为浮点数。
- 加载文件并将字符串转换为整数。
这些步骤将为您处理加载自己的数据提供所需的基础。
1. 加载 CSV 文件
第一步是加载 CSV 文件。
我们将使用标准库中的 csv 模块。
csv 模块中的 reader() 函数接受文件作为参数。
我们将创建一个名为 load_csv() 的函数来封装此行为,该函数将接受文件名并返回我们的数据集。我们将加载的数据集表示为列表的列表。第一个列表是观测值或行的列表,第二个列表是给定行的列值列表。
下面是加载 CSV 文件的完整函数。
1 2 3 4 5 6 7 8 |
from csv import reader # 加载 CSV 文件 def load_csv(filename): file = open(filename, "r") lines = reader(file) dataset = list(lines) return dataset |
我们可以通过加载 Pima 印第安人数据集来测试此函数。下载数据集并将其放在当前工作目录中,名称为 pima-indians-diabetes.csv。打开文件并删除底部的任何空行。
查看原始数据文件的前 5 行,我们可以看到以下内容:
1 2 3 4 5 |
6,148,72,35,0,33.6,0.627,50,1 1,85,66,29,0,26.6,0.351,31,0 8,183,64,0,0,23.3,0.672,32,1 1,89,66,23,94,28.1,0.167,21,0 0,137,40,35,168,43.1,2.288,33,1 |
数据是数字的,并用逗号分隔,我们可以预期整个文件都符合这个期望。
让我们使用新函数并加载数据集。加载后,我们可以报告一些简单的详细信息,例如加载的行数和列数。
将所有这些放在一起,我们得到以下结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from csv import reader # 加载 CSV 文件 def load_csv(filename): file = open(filename, "r") lines = reader(file) dataset = list(lines) return dataset # 加载数据集 filename = 'pima-indians-diabetes.csv' dataset = load_csv(filename) print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0])) |
运行此示例,我们看到:
1 |
Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns |
此函数的一个限制是它会从数据文件中加载空行并将它们添加到我们的行列表中。我们可以通过一次将数据行添加到我们的数据集中并跳过空行来克服此问题。
下面是使用这个改进的 load_csv() 函数的新版本示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# Example of loading Pima Indians CSV dataset from csv import reader # 加载 CSV 文件 def load_csv(filename): dataset = list() with open(filename, 'r') as file: csv_reader = reader(file) for row in csv_reader: if not row: continue dataset.append(row) return dataset # 加载数据集 filename = 'pima-indians-diabetes.csv' dataset = load_csv(filename) print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0])) |
运行此示例,我们看到:
1 |
Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns |
2. 将字符串转换为浮点数
大多数(如果不是所有)机器学习算法都更喜欢使用数字。
具体来说,浮点数是首选。
我们加载 CSV 文件的代码以列表的列表形式返回数据集,但每个值都是字符串。如果我们打印数据集中的一条记录,我们可以看到这一点:
1 |
print(dataset[0]) |
这会产生如下输出:
1 |
['6', '148', '72', '35', '0', '33.6', '0.627', '50', '1'] |
我们可以编写一个小型函数,将加载数据集中特定列转换为浮点值。
下面是名为 str_column_to_float() 的函数。它将数据集中的给定列转换为浮点值,并小心地在进行转换之前从值中去除任何空白字符。
1 2 3 |
def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) |
我们可以通过将其与上面的加载 CSV 函数结合,并将 Pima 印第安人数据集中的所有数字数据转换为浮点值来测试此函数。
完整的示例如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
from csv import reader # 加载 CSV 文件 def load_csv(filename): file = open(filename, "rb") lines = reader(file) dataset = list(lines) return dataset # 将字符串列转换为浮点数 def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # 加载 pima-indians-diabetes 数据集 filename = 'pima-indians-diabetes.csv' dataset = load_csv(filename) print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0])) print(dataset[0]) # 将字符串列转换为浮点数 for i in range(len(dataset[0])): str_column_to_float(dataset, i) print(dataset[0]) |
运行此示例,我们看到数据集的第一行在转换前后都已打印出来。我们可以看到每列中的值已从字符串转换为数字。
1 2 3 |
Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns ['6', '148', '72', '35', '0', '33.6', '0.627', '50', '1'] [6.0, 148.0, 72.0, 35.0, 0.0, 33.6, 0.627, 50.0, 1.0] |
3. 将字符串转换为整数
鸢尾花数据集与 Pima 印第安人数据集类似,因为列中包含数值数据。
不同之处在于最后一列,传统上用于保存给定行的结果或要预测的值。鸢尾花数据中的最后一列是鸢尾花物种的字符串。
下载数据集并将其放置在当前工作目录中,文件名为 iris.csv。打开文件并删除底部的任何空行。
例如,下面是原始数据集的前 5 行。
1 2 3 4 5 |
5.1,3.5,1.4,0.2,Iris-setosa 4.9,3.0,1.4,0.2,Iris-setosa 4.7,3.2,1.3,0.2,Iris-setosa 4.6,3.1,1.5,0.2,Iris-setosa 5.0,3.6,1.4,0.2,Iris-setosa |
一些机器学习算法希望所有值都是数字,包括结果或预测值。
我们可以通过创建映射将鸢尾花数据集中的类别值转换为整数。
- 首先,我们找到所有唯一的类别值,它们是:Iris-setosa、Iris-versicolor 和 Iris-virginica。
- 接下来,我们为每个值分配一个整数值,例如:0、1 和 2。
- 最后,我们将所有出现的类别字符串值替换为相应的整数值。
下面是一个名为 str_column_to_int() 的函数,它正是这样做的。与之前介绍的 str_column_to_float() 一样,它对数据集中的单个列进行操作。
1 2 3 4 5 6 7 8 9 10 |
# 将字符串列转换为整数 def str_column_to_int(dataset, column): class_values = [row[column] for row in dataset] unique = set(class_values) lookup = dict() for i, value in enumerate(unique): lookup[value] = i for row in dataset: row[column] = lookup[row[column]] return lookup |
我们可以测试这个新函数,以及前面介绍的两个函数,用于加载 CSV 文件并将列转换为浮点值。它还返回类别值到整数值的字典映射,以防下游用户希望将预测再次转换回字符串值。
下面的示例加载 iris 数据集,然后将前 3 列转换为浮点数,将最后一列转换为整数值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
from csv import reader # 加载 CSV 文件 def load_csv(filename): file = open(filename, "rb") lines = reader(file) dataset = list(lines) return dataset # 将字符串列转换为浮点数 def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # 将字符串列转换为整数 def str_column_to_int(dataset, column): class_values = [row[column] for row in dataset] unique = set(class_values) lookup = dict() for i, value in enumerate(unique): lookup[value] = i for row in dataset: row[column] = lookup[row[column]] return lookup # 加载 iris 数据集 filename = 'iris.csv' dataset = load_csv(filename) print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0])) print(dataset[0]) # 将字符串列转换为浮点数 for i in range(4): str_column_to_float(dataset, i) # 将类别列转换为整数 lookup = str_column_to_int(dataset, 4) print(dataset[0]) print(lookup) |
运行此示例会产生以下输出。
我们可以看到数据集的第一行在数据类型转换前后。我们还可以看到类别值到整数的字典映射。
1 2 3 4 |
Loaded data file iris.csv with 150 rows and 5 columns ['5.1', '3.5', '1.4', '0.2', 'Iris-setosa'] [5.1, 3.5, 1.4, 0.2, 1] {'Iris-virginica': 0, 'Iris-setosa': 1, 'Iris-versicolor': 2} |
扩展
您学习了如何加载 CSV 文件并执行基本数据转换。
考虑到不同问题可能需要各种数据清洗和转换,数据加载可能是一项艰巨的任务。
您可以进行许多扩展,使这些示例对新的和不同的数据文件更健壮。下面是您可以考虑自己研究和实现的一些想法:
- 检测并删除文件顶部或底部的空行。
- 检测并处理列中的缺失值。
- 检测并处理与文件其余部分不符的行。
- 支持其他分隔符,例如“|”(管道)或空格。
- 支持更高效的数据结构,例如数组。
在实践中,您可能希望使用 NumPy 和 Pandas 这两个库来加载 CSV 数据。
NumPy 提供了 loadtxt() 函数,用于将数据文件加载为 NumPy 数组。Pandas 提供了 read_csv() 函数,该函数在数据类型、文件头等方面提供了很大的灵活性。
回顾
在本教程中,您了解了如何在 Python 中从头开始加载机器学习数据。
具体来说,你学到了:
- 如何将 CSV 文件加载到内存中。
- 如何将字符串值转换为浮点值。
- 如何将字符串类别值转换为整数编码。
您对加载机器学习数据或此帖子有任何疑问吗?
在评论中提出您的问题,我会尽力回答。
非常感谢,您能告诉我们如何将 numpy 数组和 pandas 数据保存为 csv 文件的最佳方法吗?
抱歉,我没有将数据保存到 CSV 的示例。
您能向我们展示如何加载自己的图像数据以替换您的《Python 深度学习》中用于卷积神经网络的 mnist 数据吗?
嗨,哈罗德,好问题。我很快会抽时间准备一个示例。
非常感谢。
Jason,我有一个问题。如果数据集没有像 Iris 和 Pima D.S. 那样很好地组织成列和行,而是一堆随机的字符串,我该如何转换数据集,以便机器学习算法能够识别它?例如,我正在尝试使用机器学习算法对不同的恶意软件日志文件进行分类。但是,日志文件包含大量字符串、符号以及数字。它们通常是随机查询(字符串)的杂乱集合,无法组织成“萼片长度”或“类别”等列,就像上面那样。您有什么建议吗?我不知道还能问谁……谢谢您的时间。
嗨 Matt,好问题。
也许您可以使用特征工程来提取详细信息,并使用一行二进制或其他变量来表示每个观察值。
https://machinelearning.org.cn/discover-feature-engineering-how-to-engineer-features-and-how-to-get-good-at-it/
也许您可以使用自然语言处理方法直接或以投影形式处理文本。
希望这些能作为一个开始有所帮助。
不客气,Matt。
嗨 Jason
谢谢您的示例。
您能帮我解决这个问题吗?
当我运行这部分代码时:
# 将字符串列转换为浮点数
for i in range(4)
str_column_to_float(dataset, i)
# 将类别列转换为整数
lookup = str_column_to_int(dataset, 4)
print(dataset[0])
print(lookup)
我收到此错误:
IndexError Traceback (最近一次调用)
in ()
1 # 将字符串列转换为浮点数
2 for i in range(4)
—-> 3 str_column_to_float(dataset, i)
4 # 将类别列转换为整数
5 lookup = str_column_to_int(dataset, 4)
在 str_column_to_float(dataset, column)中
2 def str_column_to_float(dataset, column)
3 for row in dataset
—-> 4 row[column] = float(row[column].strip())
IndexError: 列表索引超出范围
我该如何修复?
谢谢
您正在使用 Python 2.7 吗?
不,我使用的是 Python 3.5
这个示例是为 Python 2.7 开发的,我希望很快能更新到 Python 3。
谢谢
我会继续尝试解决它。
嗨,Jason,
我定义了一个 load_csv 函数并输入了以下语句,
filename = ‘pima-indians-diabetes.csv’
dataset = load_csv(filename)
我收到以下错误,请帮帮我。
Syntax Error: invalid syntax
听起来是您的代码有问题。
也许您有多余的空格?
尝试直接在 Python 解释器上运行代码。
python2 import1.py
[‘5.1’, ‘3.5’, ‘1.4’, ‘0.2’, ‘Iris-setosa’]
回溯(最近一次调用)
文件“import1.py”,第 32 行,在
str_column_to_float(dataset, i)
文件“import1.py”,第 12 行,在 str_column_to_float
row[column] = float(row[column].strip())
IndexError: 列表索引超出范围
为什么即使我使用 python2 也会出现此错误?
也许再次检查您是否完整复制了所有代码而没有错误?
嗨,Jason,
感谢您精彩的帖子!总是让我惊叹不已🙂
无论如何,我在转换包含数字和字符串值的数据集时遇到了麻烦。
我的数据集看起来像这样
时间戳 ID 长度 数据
0.0000022 02a1 8 05 20 ea 0a 20 1a 00 7f
这是无监督学习,并计划采用 LSTM 序列分类来检测数据集中的异常。没有目标变量。所以当我想将它们转换为浮点数时,我收到了这个错误
“ValueError: 无法将字符串转换为浮点数: ’05 20 ea 0a 20 1a 00 7f'”
是因为它们之间有空格吗?甚至“ID”行也没有转换为浮点数。我使用的是 Keras,我的脚本看起来像这样:
>>> dataset = data.values
>>> dataset = dataset.astype(
>>> dataset = dataset.astype(‘float32’)
谢谢您,我是机器学习的新手。期待您的回复,Jason。
您需要将文本编码为数字。您可以将整数编码器和/或独热编码器用于标签数据,或者将词袋或词嵌入用于真实文本数据。
我的博客上有很多这些示例,您可以先尝试搜索一下。
感谢 Jason 的快速回复。我在这篇博客中找到了您关于转换为浮点数等内容的几个主题。它工作后我会告诉您的。
谢谢!
不客气。
嗨,Jason,
运行此代码时出现错误
row[column] = float(row[column].strip())
ValueError: 无法将字符串转换为浮点数:'7;0.27;0.36;20.7;0.045;45;170;1.001;3;0.45;8.8;6'
您能告诉我确切的问题以及如何纠正这个问题吗。
看起来您的分隔符是分号而不是预期的逗号。
也许您应该仔细检查您的数据文件是否正确?
顺便说一下,在打印 CSV 读取结果时,命令应该是
print(‘Loaded data file {0} with {1} rows and {2} columns’.format(filename, len(dataset), len(dataset[0])))
而不是
print(‘Loaded data file {0} with {1} rows and {2} columns’).format(filename, len(dataset), len(dataset[0]))
.format() 适用于字符串,而不是 print() 函数。
谢谢。
我按如下操作并将数据从字符串转换。但当我应用第一个教程页面中提到的其他函数,例如 dataset.describe 和 dataset.head 时,它说列表是对象,不能被调用。
我该如何处理这个问题?
谢谢
如果您是 Python 新手,也许可以从 scikit-learn 和 Pandas 开始,而不是从头编写算法。
这里是一个很好的起点:
https://machinelearning.org.cn/start-here/#python
你好 Jason,
很棒的教程!
当我运行将字符串转换为浮点数的脚本时,我收到错误消息
错误:迭代器应该返回字符串,而不是字节(您是否以文本模式打开文件?)
我做错了什么吗?
希望能收到您的来信,谢谢!
此致,Rutger
也许尝试在您的系统上以文本模式打开文件?
https://docs.pythonlang.cn/3/library/functions.html#open
你好,Jason!
这种转换(例如,字符串到整数)之后,数据是否已经准备好用于快速检查算法等等,还是没有?
在转换之前或之后我还需要做些什么吗?例如独热编码……
请注意,我有一个类似于 iris 数据集的数据集,但带有一个整数列和三个字符串列。
提前谢谢您!
这取决于数据。例如,某些数据可能需要您先编码分类变量,并且除了算法之外,您可能还需要对数据准备方法进行抽查。
大家好!
我有一个数据集,包含 3991 行和 8 列,数据类型如下:
15; 1215; FALSE; feed; 1; TRUE; TRUE; monument; attraction (CSV 示例)
当我运行代码转换它们时,我得到以下结果:
加载数据文件 INSTA POSTS.csv,包含 3991 行和 1 列。
为什么它只显示 1 列,而它有 8 列?
我多次使用您的代码,它在类似的数据集上运行得很好!
我现在不明白发生了什么!
有什么想法吗?
提前谢谢您!
Faiy
CSV 代表逗号分隔值——您不应该使用分号