当我们使用 Python 读取数据文件时,首先推荐的就是通过 Pandas 完成,Pandas 几乎支持所有常见的数据文件格式。
数据类型 | 文件格式 | 读取方式 | 存储方式 |
---|---|---|---|
文本 | CSV | read_csv | to_csv |
文本 | JSON | read_json | to_json |
文本 | HTML | read_html | to_html |
文本 | 剪切板 | read_clipboard | to_clipboard |
二进制 | MS Excel | read_excel | to_excel |
二进制 | HDF5 格式 | read_hdf | to_hdf |
二进制 | Feather 格式 | read_feather | to_feather |
二进制 | Parquet 格式 | read_parquet | to_parquet |
二进制 | Msgpack | read_msgpack | to_msgpack |
二进制 | Stata | read_stata | to_stata |
二进制 | SAS | read_sas | to_sas |
二进制 | Python Pickle 格式 | read_pickle | to_pickle |
上面的表格中,相信你最熟悉的是 Excel 表格数据文件。由于 Excel 表格有最大的行数储存限制(16,384 列 × 1,048,576 行),所以更多时候我们会使用 CSV 来储存表格数据。
CSV 的英文是 Comma-Separated Values,其实就是通过字符分割数据并以纯文本形式存储。这里的分割字符我们一般会使用逗号,所以往往也称 CSV 文件为逗号分隔符文件。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据,也没有最大行数的储存限制。
下面,我们尝试读取 Excel 和 CSV 格式的示例数据文件。首先,我们需要生成不同类型的数据示例文件。下面这段代码直接点击运行即可,将会在目录下方生成两个最常用的数据文件 test.csv
和 test.xlsx
。
教学代码
In [1]:
import numpy as np
import pandas as pd
# 生成示例数据
df = pd.DataFrame({'A': np.random.randn(10), 'B': np.random.randn(10)})
# 写入数据文件
df.to_csv('test.csv', index=None) # CSV
df.to_excel('test.xlsx', index=None) # EXCEL
print("*****示例文件写入成功*****")
*****示例文件写入成功*****
# 在此import numpy as np
import pandas as pd
import numpy as np
# 生成示例数据
df = pd.DataFrame({'A': np.random.randn(10), 'B': np.random.randn(10)})
# 写入数据文件
df.to_csv('test.csv', index=None) # CSV
df.to_excel('test.xlsx', index=None) # EXCEL
print("*****示例文件写入成功*****")
*****示例文件写入成功*****
下面,我们学习使用 Pandas 读取文件的方法,直接运用上面表格中的 API 即可。CSV 文件读取是 read_csv
,而 Excel 文件读取是 read_excel
。
pfc=pd.read_csv("test.csv")
print(pfc)
A B
0 -0.631166 0.618370
1 0.830369 -1.100556
2 -1.705350 0.253452
3 0.569138 -0.809670
4 1.358868 -0.949296
5 0.873989 0.759465
6 -0.024066 0.893342
7 -0.056798 2.006965
8 0.294654 -0.904885
9 0.897250 -0.346867
pdd=pd.read_excel('test.xlsx')
print(pdd)
A B
0 -0.631166 0.618370
1 0.830369 -1.100556
2 -1.705350 0.253452
3 0.569138 -0.809670
4 1.358868 -0.949296
5 0.873989 0.759465
6 -0.024066 0.893342
7 -0.056798 2.006965
8 0.294654 -0.904885
9 0.897250 -0.346867
当你读取 Excel 文件时,首先需要安装 openpyxl
模块,不然就会报错。安装该模块的命令为:pip install openpyxl
。在线环境中,我们已经为你安装好了该模块。
pd.read_excel('test.xlsx')
A | B | |
---|---|---|
0 | -0.631166 | 0.618370 |
1 | 0.830369 | -1.100556 |
2 | -1.705350 | 0.253452 |
3 | 0.569138 | -0.809670 |
4 | 1.358868 | -0.949296 |
5 | 0.873989 | 0.759465 |
6 | -0.024066 | 0.893342 |
7 | -0.056798 | 2.006965 |
8 | 0.294654 | -0.904885 |
9 | 0.897250 | -0.346867 |
你可以发现,通过 Pandas 读取处理的数据会自动以表格样式呈现,这也就是 Pandas 特有的数据格式:DataFrame。在学习数据分析的生涯中,DataFrame 将会成为你最容易听到的名词之一。Pandas 的所有数据操作都是针对于 DataFrame 进行。
特别地,我们会将 Pandas 中的一维数据类型称之为 Series,三维数据称之为 Panel。但实际上,它们都可以看作是特殊的 DataFrame。
HDF(英语:Hierarchical Data Format)指一种为存储和处理大容量科学数据设计的文件格式及相应库文件。HDF5 格式的特点在于能存储多个数据集,并且支持 metadata
。
HDF5 文件包含两种基本数据对象:
群组和数据集都支持元数据 metadata
,用户可以自定义其属性,提供附加信息。元数据类似于「数据的数据」,它能够用来说明数据的特征和其他属性。
HDF5 的好处在于,你不仅可以使用 Python 存储和读取,目前还被 Java,MATLAB/Scilab,Octave,IDL,Julia, R 等语言或商业软件支持。
下面,我们同样尝试使用 Pandas 来存储和读取 HDF5 数据。和 Excel 文件读取相似,我们需要先安装一个依赖模块 PyTables,命令为:pip install tables
。
df1 = pd.DataFrame({'A': np.random.randn(10), 'B': np.random.randn(10)}) # 随机数据
df2 = pd.DataFrame({'C': np.random.randn(10), 'D': np.random.randn(10)}) # 随机数据
df1.to_hdf('test.h5', key='df1') # 存储 df1
df2.to_hdf('test.h5', key='df2', format='table') # 存储 df2
上面的代码中,我们通过指定 key
向 HDF 文件中存储了 2 个不同的数据集 df1
和 df2
。那么,接下来我们尝试读取。
pd.read_hdf('test.h5', key='df1') # 读取 df1
如果你仔细观察,你会发现上面我们在存储示例数据时,df2
后面指定了 format='table'
参数。这是因为,HDF 支持两种存储架构:fixed 和 table。默认为 fixed
,因为其读取速度更快,但是 table
却支持查询操作。
# 读取 df2 中 index < 5 的数据
pd.read_hdf('test.h5', key='df2', where=['index < 5'])
你可能会觉得,HDF5 既然支持存储多个数据集,是不是类似于数据库中的「表」呢?值得注意的是,HDF5 并不是数据库,如果多个使用者同时写入数据,数据文件会遭到破坏。
JSON(英文:JavaScript Object Notation)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管 JSON 是 JavaScript 的一个子集,但 JSON 是独立于语言的文本格式。
JSON 数据格式与语言无关,脱胎于 JavaScript,但目前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json
,文件扩展名是 .json
。
这里特别说到 JSON 格式,原因是其已经成为了 HTTP 请求过程中的标准数据格式。而后面的采集数据过程中,我们会学习到通过 API 请求数据,一般都会对 JSON 进行解析。所以,这里先行了解学习。
下面,我们给出一段 JSON 的示例数据:
obj = """
[
{
"aqi": 46,
"area": "成都",
"pm2_5": 32,
"pm2_5_24h": 33,
"position_name": "金泉两河",
"primary_pollutant": null,
"quality": "优",
"station_code": "1431A",
"time_point": "2018-09-05T09:00:00Z"
},
{
"aqi": 29,
"area": "成都",
"pm2_5": 20,
"pm2_5_24h": 26,
"position_name": "十里店",
"primary_pollutant": null,
"quality": "优",
"station_code": "1432A",
"time_point": "2018-09-05T09:00:00Z"
}
]
"""
JSON 数据中 key
必须是字符串类型,缺失值用 null
表示。其中还可能包含的基本类型有:字典,列表,字符串,数值,布尔值等。
Pandas 中的 read_json
往往能直接把 JSON 解析为 DataFrame。
pd.read_json(obj)
上面的结果是不是看起来非常舒服,DataFrame 的确是最佳的数据呈现格式。不过,由于 JSON 支持复杂的嵌套,有时候直接通过 read_json
读取到的 DataFrame 并不是我们想要的样子,例如某个键值是以字典或列表存在。此时,我们就会用其他的工具来解析 JSON 了。
Python 中有许多能够储存和解析 JSON 的库,这里推荐使用内建库 json
。上面给出的 obj
其实是字符串,如果想要将其转换为 Python 的数据类型(Python Object),那么就可以使用 json.loads(obj)
完成。
import json
obj = json.loads(obj)
obj
现在,你就可以使用 Python 对字典、列表等操作方法来对上面的 obj
进行处理了。例如,我们想读取「金泉两河」地名。
obj[0]['position_name']
除此之外,使用 json.dumps
可以把 Python Object 转换为 JSON 类型。
json.dumps(obj)
read_
操作参数详解Pandas 中的 read_
操作可不仅仅是加载数据文件这么简单,它带有的一些参数可以实现更加个性化的读取结果。我们以 pandas.read_csv()
的 API 为例。
pandas.read_csv(filepath_or_buffer, sep=', ', delimiter=None, header='infer', names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, iterator=False, chunksize=None, compression='infer', thousands=None, decimal=b'.', lineterminator=None, quotechar='"', quoting=0, escapechar=None, comment=None, encoding=None, dialect=None, tupleize_cols=None, error_bad_lines=True, warn_bad_lines=True, skipfooter=0, doublequote=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None)
上面的参数可能让你看到眼花缭乱,我们挑几个重要的介绍。
path
:路径不仅仅可以读取本地文件,还支持远程 URL 链接。sep
:支持按特定字符分割。header
:可以指定某一行为列名,默认是第一行。names
:自定义列名。skiprows
:指定忽略某些行。na_values
:对空值进行指定替换操作。parse_dates
:尝试将数据解析为日期。nrows
:读取指定行数的数据。chunksize
:指定分块读取数据大小。encoding
:指定文件编码。上面的这些参数使得 Pandas 的数据文件读取功能非常强大。例如,如果你的 CSV 文件是使用分号 ;
而不是逗号 ,
分割,那么就可以通过 sep=';'
让数据加载为正常的 DataFrame 格式。
除此之外,像 skiprows
非常常用,它可以指定忽略某些行。,使得在加载数据时就可以对数据实现过滤,面对庞大且加载较慢的数据文件时特别好用。我们拿上面的示例数据举例。
In [ ]:
pd.read_csv("test.csv", skiprows=range(1, 5)) # 忽略前 4 行的数据
这里,我们特别介绍一下分块读取的方法。在很多时候,手中的数据集都非常大。例如当我们直接读取一个 GB 级别的 CSV 文件时,不仅速度很慢,还有可能因为内存不足而报错。此时,通过分块读取的方式加载数据文件就非常方便了。
通过上面的 read_
参数可以看出,分块读取需要指定 chunksize
,也就是每一块的大小。究竟该怎么做,我们来试一下。
chunker = pd.read_csv("test.csv", chunksize=2)
chunker
chunker
返回的 pandas.io.parsers.TextFileReader
是一个可迭代对象。你可以通过 get_chunk()
逐次返回每一个块状数据的内容。你可以尝试多次运行下方单元格,以查看每次迭代的结果。
chunker.get_chunk() # 迭代返回分块数据内容
分块读取是解决大文件读取慢的有效手段,但需要注意 chunksize
并不是 Pandas 中每个 read_
操作都支持的参数,这需要你在使用时通过官方文档确认。