常见数据文件存储和读取

当我们使用 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 和 CSV 格式

上面的表格中,相信你最熟悉的是 Excel 表格数据文件。由于 Excel 表格有最大的行数储存限制(16,384 列 × 1,048,576 行),所以更多时候我们会使用 CSV 来储存表格数据。

CSV 的英文是 Comma-Separated Values,其实就是通过字符分割数据并以纯文本形式存储。这里的分割字符我们一般会使用逗号,所以往往也称 CSV 文件为逗号分隔符文件。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据,也没有最大行数的储存限制。

下面,我们尝试读取 Excel 和 CSV 格式的示例数据文件。首先,我们需要生成不同类型的数据示例文件。下面这段代码直接点击运行即可,将会在目录下方生成两个最常用的数据文件 test.csvtest.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。

HDF5 格式

HDF(英语:Hierarchical Data Format)指一种为存储和处理大容量科学数据设计的文件格式及相应库文件。HDF5 格式的特点在于能存储多个数据集,并且支持 metadata

HDF5 文件包含两种基本数据对象:

  • 群组(group):类似文件夹,可以包含多个数据集或下级群组。
  • 数据集(dataset):数据内容,可以是多维数组,也可以是更复杂的数据类型。

群组和数据集都支持元数据 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 个不同的数据集 df1df2。那么,接下来我们尝试读取。

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 格式

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_ 操作都支持的参数,这需要你在使用时通过官方文档确认。

你可能感兴趣的:(python)