使用 Genfromtxt 导入数据

NumPyBeginner
立即练习

介绍

在本实验中,你将学习如何使用 numpy.genfromtxt 函数从文本文件中导入表格数据。NumPy (Numerical Python) 是 Python 中科学计算的基础库,它提供了强大的数据结构和函数来处理数值数据。其核心数据结构是NumPy 数组——一种快速、内存高效的方式来存储和操作大型数据集。

numpy.genfromtxt 函数是 Python 数据分析的基石,它允许你读取结构化数据并将其转换为 NumPy 数组。我们将从基础导入开始,并逐步添加选项来处理常见的实际场景,例如标题行、不同的列分隔符、缺失值以及选择特定的数据列。所有操作都将在 WebIDE 中通过编写和执行 Python 脚本来完成。

使用 genfromtxt 进行基本数据加载

首先,让我们熟悉一下环境。在左侧的文件浏览器中,你将看到两个文件:main.pymy_data.csv。我们将在 main.py 中编写 Python 代码来加载 my_data.csv 中的数据。

numpy.genfromtxt 函数最基本的使用需要一个参数:数据源的路径。让我们尝试使用默认设置加载数据文件。

打开 main.py 文件并在其中添加以下代码:

import numpy as np  ## 这会导入 NumPy 并为其指定别名 'np' 以方便使用

## 从 CSV 文件加载数据
## 相对路径会导致验证失败,请在实验中使用绝对路径
data = np.genfromtxt('/home/labex/project/my_data.csv')

## 打印结果数组
print(data)

现在,保存文件并从 IDE 底部的终端运行它。

python main.py

你将看到以下输出:

[nan nan nan nan]

这个输出可能会让你感到意外。结果是一个包含 nan (Not a Number) 值的数组。NaN 是一个特殊的浮点数值,表示未定义或不可表示的数值结果——这是 NumPy 表示无法正确转换为数字的值的方式。之所以出现这种情况,是因为 genfromtxt 默认会尝试按空格分割行,并将所有内容解释为浮点数。我们的 my_data.csv 文件使用逗号作为分隔符,并且包含一个非数字的标题行,这导致默认导入失败。在下一步中,我们将解决这个问题。

指定分隔符和跳过标题

为了正确解析我们的 my_data.csv 文件,我们需要告知 genfromtxt 两件事:

  1. 数据由逗号分隔。
  2. 第一行是标题行,应该被忽略。

我们可以使用 delimiterskip_header 参数来实现这一点。

  • delimiter=',': 这告诉函数使用逗号来分隔值。
  • skip_header=1: 这告诉函数忽略文件的第一行。

使用更新后的代码修改你的 main.py 文件:

import numpy as np  ## 导入 NumPy 库

## 加载数据,指定分隔符并跳过标题行
data = np.genfromtxt('/home/labex/project/my_data.csv', delimiter=',', skip_header=1)

## 打印结果数组
print(data)

保存文件并在终端中再次运行它:

python main.py

输出现在看起来好多了:

[[ 1.   22.5  45. ]
 [ 2.   23.1  48. ]
 [ 3.    nan  46. ]
 [ 4.   23.5  52. ]]

如你所见,数据现在被结构化为一个二维数组 (two-dimensional array)。你可以将其想象成一个带有行和列的表格或电子表格——我们的数组有 4 行(对应每个传感器读数)和 3 列(传感器 ID、温度、湿度)。数字被正确解析为浮点数 (floats),即可以表示 22.5 这样小数的数值。然而,请注意第三行中的 nan。这是因为我们的源文件使用文本 NA 来表示缺失的温度读数,而 genfromtxt 无法将其识别为数字。我们将在下一步中解决这个问题。

处理缺失值

真实世界的数据集通常是不完整的。genfromtxt 提供了一种使用 missing_valuesfilling_values 参数来干净地处理这种情况的方法。

  • missing_values: 应被解释为缺失数据的字符串或字符串列表。
  • filling_values: 用于替换任何缺失条目的值。

在我们的数据中,缺失值由 NA 表示。让我们告诉 genfromtxt 识别 NA 为缺失值,并用 -99 替换它,以便于识别。

按如下方式更新你的 main.py 文件:

import numpy as np  ## 导入 NumPy 库

## 处理缺失值
data = np.genfromtxt('/home/labex/project/my_data.csv', delimiter=',', skip_header=1,
                     missing_values='NA', filling_values=-99)

## 打印结果数组
print(data)

保存文件并执行它:

python main.py

输出现在显示了一个完整的数值数组,缺失值已被替换:

[[  1.    22.5   45.  ]
 [  2.    23.1   48.  ]
 [  3.   -99.    46.  ]
 [  4.    23.5   52.  ]]

现在我们的数据是干净且完全数值化的,可以进行计算了。

选择列和设置数据类型

有时,你只需要一部分数据。usecols 参数允许你指定要导入的列。它接受一个元组 (tuple),即一个不可变的数值序列,例如 (1, 2),其中包含列的索引(从 0 开始)。例如,usecols=(1, 2) 表示“仅导入第 1 列和第 2 列”。

此外,你可以使用 dtype 参数为所有导入的数据强制指定一种特定的数据类型 (data type)。在编程中,数据类型决定了值的存储方式以及可以对其执行的操作。例如,dtype=int 会将所有值转换为整数(whole numbers),dtype=float 确保它们保持为浮点数(decimals),而 dtype=str 则将它们视为文本。请注意,dtype=int 会截断任何小数部分(22.5 会变成 22)。

让我们修改脚本,仅导入 Temperature(第 1 列)和 Humidity(第 2 列),并确保它们被视为浮点数。

最后一次更新 main.py

import numpy as np  ## 导入 NumPy 库

## 选择特定列并设置数据类型
data = np.genfromtxt('/home/labex/project/my_data.csv', delimiter=',', skip_header=1,
                     missing_values='NA', filling_values=0,
                     usecols=(1, 2), dtype=float)

## 打印结果数组
print(data)

注意:在此示例中,我们将 filling_values 改为了 0

保存文件并在终端中运行它:

python main.py

最终输出将是一个只包含温度和湿度数据的二维数组:

[[22.5 45. ]
 [23.1 48. ]
 [ 0.  46. ]
 [23.5 52. ]]

你已成功导入并清理了一个数据集,只选择了相关的列,并在此过程中处理了所有数据不一致的问题。

总结

在本实验中,你学会了如何有效地使用 numpy.genfromtxt 将文本文件中的数据导入 NumPy 数组。你练习使用了几个关键参数来应对真实世界的数据挑战:

  • delimiter: 用于指定列的分隔方式。
  • skip_header: 用于忽略数据文件中的标题行。
  • missing_values: 用于识别代表缺失数据的自定义字符串。
  • filling_values: 用于将缺失数据替换为特定值。
  • usecols: 用于仅导入特定列的子集。
  • dtype: 用于控制结果数组的数据类型。

掌握 genfromtxt 是任何使用 Python 和 NumPy 的数据科学家或工程师的一项基本技能。