a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
欢迎来到数据分析的世界!🌍 在我们从数据中解锁洞察力之前,我们需要先将数据导入到我们的 Python 环境中。本章重点关注这关键的第一步:数据加载。
可以这样理解:在你烹饪一道美味佳肴 🍳 之前,你首先需要收集你的食材 🍅🥕🥦。数据加载就像是为你的数据分析食谱收集食材。
我们将涵盖各种加载数据的方法,包括:
数据分析是对数据进行检查、清理、转换和建模的过程,以发现有用的信息、得出结论并支持决策。这就像成为一名侦探 🕵️♀️,但你不是在破案,而是在解决隐藏在数据中的难题。
机器学习是人工智能 (AI) 的一个子领域,专注于使计算机能够从数据中学习,而无需进行显式编程。可以把它想象成教计算机像孩子一样学习 👶,通过向它展示示例而不是给它严格的规则。
Python 是一种通用的高级编程语言,广泛用于数据分析和机器学习。它以其可读性和广泛的库而闻名,这使得执行复杂任务变得更加容易。这就像拥有一个数据分析的瑞士军刀 🛠️。
数据科学维恩图。来源:Drew Conway
pandas
库是你在 Python 中处理表格数据的最好朋友。它提供了 DataFrame
对象,这是一个用于存储和操作行和列中数据(如电子表格)的强大结构。pandas
提供了几个用于读取和写入各种格式数据的函数。
数据解析,通常称为数据加载,包括从文件或其他来源读取数据,并将其转换为可用的格式(如 DataFrame)。它通常还包括对数据中数据类型的初步解释。
pandas
数据加载函数 (1/2)下表列出了 pandas
中一些最常用的数据加载函数。在本节中,我们将重点关注 read_csv
。
函数 | 描述 |
---|---|
read_csv |
从文件、URL 或类文件对象加载分隔数据;默认使用逗号作为分隔符。 |
read_fwf |
读取固定宽度列格式的数据(即,没有分隔符)。 |
read_clipboard |
read_csv 的变体,从剪贴板读取数据;用于转换网页中的表格。 |
read_excel |
从 Excel XLS 或 XLSX 文件读取表格数据。 |
read_hdf |
读取由 pandas 写入的 HDF5 文件。 |
read_html |
读取给定 HTML 文档中的所有表格。 |
read_json |
从 JSON(JavaScript 对象表示法)字符串表示、文件、URL 或类文件对象读取数据。 |
pandas
数据加载函数 (2/2)函数 | 描述 |
---|---|
read_feather |
读取 Feather 二进制文件格式。 |
read_orc |
读取 Apache ORC 二进制文件格式。 |
read_parquet |
读取 Apache Parquet 二进制文件格式。 |
read_pickle |
读取使用 Python pickle 格式存储的 pandas 对象。 |
read_sas |
读取以 SAS 系统自定义格式之一存储的 SAS 数据集。 |
read_spss |
读取由 SPSS 创建的数据文件。 |
read_sql |
读取 SQL 查询的结果(使用 SQLAlchemy)。 |
read_sql_table |
读取整个 SQL 表(使用 SQLAlchemy)。 |
read_stata |
从 Stata 文件格式读取数据集。 |
read_xml |
从XML文件中读取数据表。 |
read_csv
read_csv
是处理逗号分隔值文件的基石,也是最常用的函数之一。
数据加载函数有许多可选参数来自定义加载过程。它们通常分为以下几类:
pandas
文档不要被吓倒!pandas
在线文档有很多很棒的例子。像 “pandas read_csv skip header” 这样的 Google 搜索通常会有帮助。
read_csv
读取 CSV 文件 - 基本示例让我们从读取逗号分隔值 (CSV) 文件开始。
a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
pd.read_csv()
检测标题行并使用逗号作为分隔符。索引是自动生成的。
有时,你的 CSV 文件可能没有标题行。
告诉 pandas
使用默认列名:
或者,提供你自己的列名:
使用 index_col
参数将一列用作索引:
# 使用 'message' 列作为索引
column_names = ["a", "b", "c", "d", "message"]
pd.read_csv("examples/ex2.csv", names=column_names, index_col="message")
a | b | c | d | |
---|---|---|---|---|
message | ||||
hello | 1 | 2 | 3 | 4 |
world | 5 | 6 | 7 | 8 |
foo | 9 | 10 | 11 | 12 |
现在行标签是 ‘hello’、‘world’ 和 ‘foo’。
通过指定多个列来创建分层索引:
value1 | value2 | ||
---|---|---|---|
key1 | key2 | ||
one | a | 1 | 2 |
b | 3 | 4 | |
c | 5 | 6 | |
d | 7 | 8 | |
two | a | 9 | 10 |
b | 11 | 12 | |
c | 13 | 14 | |
d | 15 | 16 |
分层索引对于更高维度的数据很有用。
文件有时使用逗号以外的分隔符。空格示例:
将 sep
参数与正则表达式一起使用:
A | B | C | |
---|---|---|---|
aaa | -0.264438 | -1.026059 | -0.619500 |
bbb | 0.927272 | 0.302904 | -0.032399 |
ccc | -0.264273 | -0.386314 | -0.217601 |
ddd | -0.871858 | -0.348382 | 1.100491 |
\s+
匹配一个或多个空格字符。pandas
推断索引。
使用 skiprows
忽略特定行:
缺失数据很常见。pandas
可以识别像 “NA” 这样的标记:
检查缺失值:
使用 na_values
指定其他缺失值字符串:
使用 keep_default_na=False
禁用默认的 NA 处理:
something | a | b | c | d | message | |
---|---|---|---|---|---|---|
0 | one | 1 | 2 | 3 | 4 | NA |
1 | two | 5 | 6 | 8 | world | |
2 | three | 9 | 10 | 11 | 12 | foo |
为每一列指定不同的 NA 值:
read_csv
/read_table
函数参数:摘要 (1/3)以下是关键参数的摘要:
参数 | 描述 |
---|---|
path |
字符串:文件路径、URL 或类文件对象。 |
sep 或 delimiter |
用于分隔字段的字符序列或正则表达式。 |
header |
列名的行号(默认为 0)。如果没有标题,则为 None 。 |
index_col |
用作行索引的列。 |
names |
如果没有标题,则为列名列表。 |
skiprows |
要跳过的行号列表。 |
read_csv
/read_table
函数参数:摘要 (2/3)参数 | 描述 |
---|---|
na_values |
要替换为 NaN 的值。 |
keep_default_na |
使用默认的 NaN 值(默认为 True )。 |
comment |
用于分割行尾注释的字符。 |
parse_dates |
尝试将数据解析为 datetime 。 |
keep_date_col |
如果连接列以解析日期,则保留连接的列。 |
converters |
将列号/名称映射到函数的字典。 |
read_csv
/read_table
函数参数:摘要 (3/3)参数 | 描述 |
---|---|
dayfirst |
解析有歧义的日期时,将其视为国际格式。 |
date_parser |
用于解析日期的函数。 |
nrows |
从头开始读取的行数。 |
iterator |
返回一个 TextFileReader 以进行分段读取。 |
chunksize |
对于迭代,文件块的大小。 |
skip_footer |
要忽略的末尾行数。 |
verbose |
打印解析信息。 |
encoding |
文本编码。 |
squeeze |
如果只有一列,则返回一个 Series。 |
thousands |
千位分隔符。 |
decimal |
小数点分隔符。 |
engine |
解析引擎: c , python , 或 pyarrow . |
nrows
对于大文件,读取一小部分或分块处理。
chunksize
使用 chunksize
分块读取文件:
chunker
是一个 TextFileReader
。遍历它:
# 逐块处理
chunker = pd.read_csv("examples/ex6.csv", chunksize=1000)
# 创建一个空的 Series 来存储结果, 指定数据类型为 int64
tot = pd.Series([], dtype='int64')
for piece in chunker:
# 统计每个数据块中 'key' 列的值,并将结果累加到 tot 中,缺失值填充为 0
tot = tot.add(piece["key"].value_counts(), fill_value=0)
# 对结果进行降序排序
tot = tot.sort_values(ascending=False)
# 显示前 10 个结果
tot[:10]
key
E 368.0
X 364.0
L 346.0
O 343.0
Q 340.0
M 338.0
J 337.0
F 335.0
K 334.0
H 330.0
dtype: float64
to_csv
将数据写入各种格式。to_csv
是 read_csv
的对应函数。
something | a | b | c | d | message | |
---|---|---|---|---|---|---|
0 | one | 1 | 2 | 3.0 | 4 | NaN |
1 | two | 5 | 6 | NaN | 8 | world |
2 | three | 9 | 10 | 11.0 | 12 | foo |
Unnamed: 0 | something | a | b | c | d | message | |
---|---|---|---|---|---|---|---|
0 | 0 | one | 1 | 2 | 3.0 | 4 | NaN |
1 | 1 | two | 5 | 6 | NaN | 8 | world |
2 | 2 | three | 9 | 10 | 11.0 | 12 | foo |
默认情况下会写入行和列标签。
指定不同的分隔符:
以不同的方式表示缺失值:
禁用行和列标签:
按特定顺序写入列的子集:
csv
模块对于单字符分隔符,使用 Python 的 csv
模块:
将数据处理成可用的形式:
# 打开 CSV 文件
with open("examples/ex7.csv") as f:
# 将 csv.reader 的结果转换为列表
lines = list(csv.reader(f))
# 将第一行作为标题,其余行作为值
header, values = lines[0], lines[1:]
# 创建一个数据列的字典
data_dict = {h: v for h, v in zip(header, zip(*values))}
data_dict
{'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}
对于复杂的文件,使用字符串操作或正则表达式。pandas.read_csv
通常就足够了。
csv
模块有方言选项来自定义解析:
参数 | 描述 |
---|---|
delimiter |
用于分隔字段的单字符字符串(默认为 ‘,’)。 |
lineterminator |
写入时的行终止符(默认为 ‘’)。读取器会忽略并识别跨平台。 |
quotechar |
包含特殊字符的字段的引用字符(默认为 ‘“’)。 |
quoting |
引用约定。 |
skipinitialspace |
忽略分隔符后的空格(默认为 False )。 |
doublequote |
处理字段内的引用字符。 |
escapechar |
如果 quoting 为 csv.QUOTE_NONE ,则用于转义分隔符的字符串。 |
定义一个自定义的方言子类:
或者直接传递方言选项:
JSON 是一种灵活的格式,用于在 Web 上进行数据交换。
JSON 接近有效的 Python 代码(例如,使用 null
而不是 None
)。
json.loads
和 json.dumps
{'name': 'Wes',
'cities_lived': ['Akron', 'Nashville', 'New York', 'San Francisco'],
'pet': None,
'siblings': [{'name': 'Scott', 'age': 34, 'hobbies': ['guitars', 'soccer']},
{'name': 'Katie', 'age': 42, 'hobbies': ['diving', 'art']}]}
从字典列表创建一个 DataFrame:
read_json
pandas.read_json
将 JSON 转换为 Series/DataFrame:
to_json
使用 to_json
从 pandas 导出到 JSON:
{"a":{"0":1,"1":4,"2":7},"b":{"0":2,"1":5,"2":8},"c":{"0":3,"1":6,"2":9}}
像 lxml
、Beautiful Soup
、html5lib
这样的库可以处理 HTML/XML。pandas
使用 read_html
来处理 HTML 表格。
安装:
因为 notebook 文件不能直接访问本地文件,所以上面这段代码在执行时会报错,但在实际情景中,是可以正常运行的。
这里我们抓取了网站内容,所以依然可以用这个网址做演示。
# 从 FDIC 网站读取 HTML 表格
tables = pd.read_html("https://www.fdic.gov/resources/resolutions/bank-failures/failed-bank-list/")
# 检查找到了多少个表格
len(tables)
# 获取第一个表格
failures = tables[0]
# 显示第一个表格的前几行
failures.head()
Bank Name | City | State | Cert | Acquiring Institution | Closing Date | Fund Sort ascending | |
---|---|---|---|---|---|---|---|
0 | Pulaski Savings Bank | Chicago | Illinois | 28611 | Millennium Bank | January 17, 2025 | 10548 |
1 | The First National Bank of Lindsay | Lindsay | Oklahoma | 4134 | First Bank & Trust Co., Duncan, OK | October 18, 2024 | 10547 |
2 | Republic First Bank dba Republic Bank | Philadelphia | Pennsylvania | 27332 | Fulton Bank, National Association | April 26, 2024 | 10546 |
3 | Citizens Bank | Sac City | Iowa | 8758 | Iowa Trust & Savings Bank | November 3, 2023 | 10545 |
4 | Heartland Tri-State Bank | Elkhart | Kansas | 25851 | Dream First Bank, N.A. | July 28, 2023 | 10544 |
清理和分析加载的数据:
lxml.objectify
解析 XMLXML 比 HTML 更通用。以 MTA 数据为例:
from lxml import objectify
# XML 文件路径
path = "datasets/mta_perf/Performance_MNR.xml"
# 打开文件并解析 XML
with open(path) as f:
parsed = objectify.parse(f)
# 获取根元素
root = parsed.getroot()
data = []
# 要跳过的字段
skip_fields = ["PARENT_SEQ", "INDICATOR_SEQ", "DESIRED_CHANGE", "DECIMAL_PLACES"]
# 遍历根元素的 INDICATOR 子元素
for elt in root.INDICATOR:
el_data = {}
# 遍历 INDICATOR 元素的子元素
for child in elt.getchildren():
# 跳过指定字段
if child.tag in skip_fields:
continue
# 将子元素的标签和值添加到字典中
el_data[child.tag] = child.pyval
# 将字典添加到列表中
data.append(el_data)
# 从列表创建 DataFrame
perf = pd.DataFrame(data)
perf.head()
因为 notebook 文件不能直接访问本地文件,所以上面这段代码在执行时会报错,但在实际情景中,是可以正常运行的。
pandas.read_xml
pandas
也有 read_xml
:
二进制格式可能比文本格式更有效。
Python 的 pickle
模块可以序列化/反序列化对象。使用 to_pickle
:
a | b | c | d | message | |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | hello |
1 | 5 | 6 | 7 | 8 | world |
2 | 9 | 10 | 11 | 12 | foo |
read_pickle
使用 pandas.read_pickle
读取 pickled 对象:
pickle
仅用于短期存储。
HDF5 存储大型数组,支持压缩,高效的子集。
安装 PyTables:
HDF5 存储多个带有元数据的数据集。HDFStore
就像一个字典:
“fixed”(默认)和 “table”。“table” 较慢,支持查询:
pandas.read_hdf
pandas.read_hdf
是一个快捷方式:
HDF5 不是数据库。一次写入,多次读取。并发写入会损坏数据。
pandas
使用 ExcelFile
或 read_excel
。需要 xlrd
、openpyxl
:
ExcelFile
因为 notebook 文件不能直接访问本地文件,所以上面这段代码在执行时会报错,但在实际情景中,是可以正常运行的。
read_excel
对于多个工作表,ExcelFile
更快。或者使用 read_excel
:
ExcelWriter
创建 ExcelWriter
,然后写入:
to_excel
或者,更简洁地:
网站通过 API 提供数据,通常是 JSON 格式。requests
库很方便。
安装:
requests
示例# 从问题数据创建 DataFrame,选择 'number'、'title'、'labels'、'state' 列
issues = pd.DataFrame(data, columns=["number", "title", "labels", "state"])
#显示数据的前几行
issues.head()
number | title | labels | state | |
---|---|---|---|---|
0 | 61216 | BUG: OverflowError when fillna on DataFrame wi... | [] | open |
1 | 61215 | DOC: Fix ES01 for pandas.api.extensions.Extens... | [] | open |
2 | 61214 | Restrict clipping of DataFrame.corr only when ... | [] | open |
3 | 61211 | BUG: Preserve extension dtypes in MultiIndex d... | [] | open |
4 | 61210 | ENH: Add ignore_empty and ignore_all_na argume... | [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=... | open |
构建更高级别的接口以返回 DataFrame。
SQL 数据库很常见。pandas
简化了从查询中加载数据的过程。
SQLite3 示例(内置):
SQLAlchemy 提供了更高级别的抽象。pandas
的 read_sql
函数可以使用它。
安装:
访问数据是第一步。本章介绍了加载/存储数据的工具:文本、二进制、数据库、API。下一步:清理、转换、分析。
pandas
是你的朋友: 用于读取/写入数据。read_csv
是关键: 用于逗号分隔值文件。requests
库。pandas
、SQLAlchemy。pandas
文档。