数据加载、存储与文件格式

数据加载、存储与文件格式

读写文本格式的数据

pandas中的文本和二进制数据的加载函数:

  • read_csv:从文件、URL、文件型对象中加载带分隔符的数据,默认分隔符为逗号
  • read_fwf:读取特定宽度列格式的数据(无分隔符)
  • read_clipboard:读取剪贴板中的数据,可以看作read_table的剪贴板版,在将网页转换为表格时很有用
  • read_excel:从Excel XLS或XLSX文件中读取表格数据
  • read_hdf:读取pandas存储的HDF5文件
  • read_html:读取HTML文档中的所有表格
  • read_json:读取JSON字符串、文件、URL或文件型对象中的数据
  • read_feather:读取Feather二进制文件格式
  • read_orc:读取Apache ORC二进制文件格式
  • read_parquet:读取Apache Parquet二进制文件格式
  • read_pickle:读取pandas使用Python pickle格式存储的对象
  • read_sas:读取存储于SAS系统的自定义存储格式的SAS数据集
  • read_spss:读取SPSS创建的数据文件
  • read_sql:读取SQL查询的结果(使用SQLAlchemy)
  • read_sql_table:读取整个SQL表(使用SQLAlchemy),等价于使用read_sql读取表中的所有数据
  • read_stata:读取Stata文件格式的数据集
  • read_xml:读取XML文件中的数据表格

首先我们来看一个小型的逗号分隔值(CSV)文本文件:

  • 文件内容如下图:

[图片上传失败...(image-75f7fd-1745280165549)]

df = pd.read_csv("001.csv")
#    a   b   c   d message
# 0  1   2   3   4   hello
# 1  5   6   7   8   world
# 2  9  10  11  12     foo

# 忽略表头
df1 = pd.read_csv("001.csv",header=None)
#    0   1   2   3        4
# 0  a   b   c   d  message
# 1  1   2   3   4    hello
# 2  5   6   7   8    world
# 3  9  10  11  12      foo

# 指定列名
df2 = pd.read_csv("001.csv",names=["aa","bb","cc","dd","ee"])
#   aa  bb  cc  dd       ee
# 0  a   b   c   d  message
# 1  1   2   3   4    hello
# 2  5   6   7   8    world
# 3  9  10  11  12      foo

# 假如你想用message列来作为返回的DataFrame的索引,既可以指明索引为4的列,也可以使用index_col参数指明使用"message"
names=["a","b","c","d","message"]
df3 = pd.read_csv("001.csv",names=names,index_col="message")
#          a   b   c   d
# message
# message  a   b   c   d
# hello    1   2   3   4
# world    5   6   7   8
# foo      9  10  11  12

如果希望将多列做成层次化索引(将在8.1节中介绍),只需传入由列编号或列名组成的列表即可:

[图片上传失败...(image-c0ea-1745280165550)]

parsed = pd.read_csv("002.csv",index_col=["key1","key2"])
#            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

在某些情况下,有些表格使用的可能不是固定的分隔符,而是用空白符或其他方式分隔字段:

[图片上传失败...(image-e223c5-1745280165550)]

# 可以传入一个正则表达式作为pandas.read_csv的分隔符。正则表达式可以是\s+,于是有
result = pd.read_csv("003.txt",sep="\s+") # 由于列名的数量比数据的行数少一个,所以pandas.read_csv推断第一列作为DataFrame的索引。
#                 A             B             C
# aaa -2.644380e-01 -1.026059e+00 -6.193000e-01
# bbb  9.323230e-01  2.342340e-01  2.323434e+07
# ccc  1.111111e+07  2.222222e+07  3.333333e+07
# ddd  4.444444e+07  5.555556e+07  6.666667e+07
# skiprows跳过文件的第一行、第三行和第四行
pd.read_csv("001.csv",skiprows=[0,2,3])
# 设置缺失值的默认值。  默认为 NaN或NULL
result=pd.read_csv("001.csv",na_values=["null"])
# pandas.read_csv有多种默认的NA标记值,可以用选项keep_default_na使其失效
result2 = pd.read_csv("001.csv",keep_default_na=False,na_values=["NA"])

# 对于字典中的各列,可以指定不同的缺失值标识
sentinels = {"message":["foo","NA"],"something":["two"]}
pd.read_csv("001.csv",na_values=sentinels,keep_default_na=False)

pandas.read_csv的部分函数参数:

  • path:表示文件系统位置、URL、文件型对象的字符串
  • sep或delimiter:用于对行中各字段进行拆分的字符序列或正则表达式
  • header:用作列名的行号。默认为0(第一行),如果没有表头则为None
  • index_col:用作结果中行索引的列编号或列名。可以是单个名称或数字,也可以是名称或数字组成的列表,用于层次化索引
  • names:用于结果的列名列表
  • skiprows:从文件开始处算起,需要忽略的行数或需要跳过的行数列表(从0开始)
  • na_values:一组用于替换NA的值序列。将其添加到默认列表,如果keep_default_na=False,则不添加
  • keep_default_na:是否使用默认的NA值列表(默认为True)
  • comment:用于在行尾分隔注释的字符(一个或多个)
  • parse_dates:尝试将数据解析为datetime,默认为False。如果为True,则尝试解析所有列。此外,还可以指定需要解析的一组列号或列名的列表。如果列表的元素为列表或元组,就会将多个列组合到一起再进行日期解析(例如,日期或时间分别位于两列中)
  • keep_date_col:如果连接多列来解析日期,则保留已连接的列。默认为False
  • converters:由列号或列名与函数之间的映射关系组成的字典(例如,[foo”:f}会对foo列的所有值应用函数f)
  • dayfirst:当解析有歧义的日期时,将其按国际格式处理(例如,7/6/2012处理为June7,2012)。默认为False
  • date_parser:用于解析日期的函数
  • nrows:从文件开始处算起,需要读取的行数(不包括表头)
  • iterator:返回一个TextFileReader,用于逐块读取文件。该对象还可以用于with语句
  • chunksize:用于送代的文件块的大小
  • skip footer:文件末尾处需要忽略的行数
  • verbose:打印各种解析器输出信息,比如文件转换每个阶段的用时和内存使用信息
  • encoding:用于unicodc的文本编码格式。例如,“utf-8”表示用UTF-8编码的文本
  • squeeze:如果数据经解析后仅含一列,则返回Scrics
  • thousands:千分位分隔符,如“,”或“,”,默认没有分隔符
  • decimal:小数点分隔符,如“,”或“.”,默认是“.”
  • engine:用于解析和转换CSV文件的引|擎,可以是“c”“python”“pyarrow”其中之一。默认引l擎是“c”,但“pyarrow”对某些文件的转换速度更快。“python”稍慢,但支持另外两种引擎没有的功能

逐块读取文本文件

# 在查看大文件之前,我们先设置pandas,使显示更加紧凑
pd.options.display.max_rows=10  # 显示最开始5条和最后5条数据,中间……
result = pd.read_csv("xxx.csv")
# 只读取几行
pd.read_csv("xxx.csv",nrows=5)

# pandas.read_csv所返回的TextFileReader对象可以根据chunksize对文件进行逐块迭代。比如说,我们可以迭代处理ex6.csv,连接"key"列中的值
# TextFileReader还有一个get_chunk方法,用于读取任意大小的数据块。
chunker = pd.read_csv("001.csv", chunksize=1000)
tot=pd.Series([],dtype='int64')
for piece in chunker:
    tot = tot.add(piece["key"].value_counts(),fill_value=0)
tot = tot.sort_values(ascending=False)

将数据写入文本格式

# DataFrame的to_csv方法,可以将数据导出到逗号分隔的文件中
data = pd.read_csv("001.csv")
data.to_csv("001_copy.csv")
# 指定分隔符
data.to_csv(sys.stdout,sep="|")
# 缺失值设置
data.to_csv(sys.stdout,na_rep="NULL")
# 禁用行和列标签
data.to_csv(sys.stdout,index=False,header=False)
# 只输出列的一部分,并以指定的顺序排
data.to_csv(sys.stdout,index=False,columns=["a","b","c"])

JSON数据

import json

obj = """
{ "name":"wes",
  "cities_lives:["Akron","Nashville","New York","San Francisco"],
  "pet":null,
  "siblings":[{"name":"Scott","age":34,"hobbies":["guitars","soccer"]},
              {"name":"Katie","age":42,"hobbies":["diving","art"]}]
}
"""
result = json.loads(obj) # json.loads即可将JSON字符串转换成Python形式
# 将json对象转为json字符串
asjson = json.dumps(result)

siblings = pd.DataFrame(result["siblings"],columns=["name","age"])
#     name  age
# 0  Scott   34
# 1  Katie   42

读取json文件:

[图片上传失败...(image-1861a9-1745280165550)]

data = pd.read_json("005.json")
#    a  b  c
# 0  1  2  3
# 1  4  5  6
# 2  7  8  9

# 将数据从pandas输出到JSON,可以对Series和DataFrame使用to_json方法
data.to_json()

XML和HTML:网络抓取

Python有许多可以读写常见的HTML和XML格式数据的库,包括lxml、Beautiful Soup和html5lib。lxml的速度相对较快,但其他的库处理有误的HTML或XML文件更好。

pandas有一个内置函数pandas.read_html,可以使用所有这些解析库自动将HTML文件中的表格解析为DataFrame对象。

二进制数据格式

使用Python内置的pickle模块,能便捷地将数据存储(或序列化)为二进制格式。所有pandas对象都有一个to_pickle方法,可以将数据以pickle格式保存到磁盘上:

frame = pd.read_csv("001.csv")
frame.to_pickle("005")
# pickle文件只对Python是可读的.
# 通过内置的pickle可以直接读取序列化数据,或者使用更为便捷的pandas.read_pickle
pd.read_pickle("005")

读取Microsoft Excel文件

使用pandas.ExcelFile类或pandas.read_excel函数,pandas还支持读取存储于Excel 2003(以及更高版本)文件中的表格型数据。在这些工具内部,它们分别使用附加组件包xlrd和openpyxl读取旧格式的XLS文件和新格式的XLSX文件

# 安装两个包
pip install openpyxl xlrd
# 要使用pandas.ExcelFile,传入xls或xlsx文件的路径
xlsx = pd.ExcelFile("006.xlsx")
# 列表的形式展示文件中的工作表名称
xlsx.sheet_names
# parse将工作表中的数据读取到DataFrame中
xlsx.parse(sheet_name="Sheet1")
# 参数index_col指定索引列
xlsx.parse(sheet_name="Sheet1",index_col=0)
# 如果要从文件读取多张工作表,这样一次性创建pandas.ExcelFile比较快,另外也可以将文件名传给pandas.read_exce
frame = pd.read_excel("006.xlsx",sheet_name="Sheet1")

# pandas数据写入Excel格式
writer = pd.ExcelWriter("007.xlsx")
frame.to_excel(writer,"Sheet1")
writer.save()
# 如果不想使用ExcelWriter,可以将文件路径直接传递给to_excel
frame.to_excel("007.xlsx")

使用HDF5格式

HDF5是一种备受好评的文件格式,用于存储大规模科学数组数据。它以C标准库的形式存在,并带有许多其他语言的接口,包括Java、Julia、MATLAB和Python等。HDF5中的“HDF”指的是层次型数据格式(hierarchical data format)。每个HDF5文件能够存储多个数据集并支持元数据。与更简单的格式相比,HDF5支持多种压缩模式的即时压缩,还能更高效地存储重复模式数据。对于那些大到无法放入内存的数据集,HDF5是不错的选择,因为它可以高效读写大型数组中的一小部分。

# 安装pytables包(注意,在PyPI中,PyTables的包名是“tables”。所以,用pip安装的话,命令是pip install tables。)
conda install pytables

# 虽然可以用PyTables或h5py库直接访问HDF5文件,但是pandas提供了更为高级的接口,可以简化存储Series和DataFrame对象。
# HDFStore类可以像字典一样处理底层细节
frame = pd.DataFrame({"a":np.random.standard_normal(100)})
store = pd.HDFStore("006.h5")
store["obj1"]=frame
store["obj1_col"]=frame["a"]

# HDFStore支持两种存储模式:"fixed"和"table"("fixed"是默认模式)。后者通常更慢,但支持使用特殊语法进行查询操作
store.put("obj2",frame,format="table")
store.select("obj2",where=["index>=10 and index<=15"])

# put是store["obj2"]=frame方法的显示版本,允许我们设置其他的选项,比如存储格式。
# pandas.read_hdf函数可以快捷使用这些工具
frame.to_hdf("007.h5","obj3",format="table")
pd.read_hdf("007.h5","obj3",where=["index<5"])

# 删除HDF5文件
import os
os.remove("007.h5")

如果你要处理的数据位于远程服务器,比如Amazon S3或HDFS,使用专门为分布式存储(比如Apache Parquet)设计的二进制格式也许更加合适。

如果需要在本地处理海量数据,建议读者好好研究一下PyTables和h5py,看看它们是否满足你的需求。由于大量数据分析问题都是IO密集型(而不是CPU密集型)问题,利用HDF5这样的工具能显著提升应用程序的效率。

HDF5不是数据库。它最适合用作“一次写多次读”的数据集。虽然数据可以在任何时候被添加到文件中,但如果同时发生多个写操作,文件就可能会受到破坏。

与Web API交互

# 通过pip或conda安装requests包
pip install requests

import requests
# 获取GitHub上关于pandas的30个最新问题
url = "https://api.github.com/repos/pandas-dev/pandas/issues"
resp = requests.get(url)
# 每次使用requests.get之后,最好都调用raise_for_status检查HTTP的错误
resp.raise_for_status()
# 解析为json
data = resp.json()
# 将data传递给pandas.DataFrame,并提取感兴趣的字段
issues = pd.DataFrame(data,columns=["number","title","labels","state"])

与数据库交互

pip install sqlalchemy

import sqlalchemy as sqla
db = sqla.create_engine("sqlite://mydata.sqlite")
pd.read_sql("select * from test",db)
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容