1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 数据载入 存储及文件格式——《利用python数据分析》第六章学习

数据载入 存储及文件格式——《利用python数据分析》第六章学习

时间:2024-06-04 07:45:57

相关推荐

数据载入 存储及文件格式——《利用python数据分析》第六章学习

数据载入、存储及文件格式——《利用python数据分析》第六章学习

前言

这次带来第六章的学习笔记,希望这次效率高点,快点写完。

代码环境这次小升级,Pycharm .3 + Anaconda3, 另外用到了Windows的 cmd

访问数据是使用该书中各类工具的必需的第一步,重点关注利用pandas进行数据输如和输出。

输入和输出通常有以下集中类型:读取文本文件及硬盘上其他更高效的格式文件、从数据库载入数据、与网络资源进行交互,如WebAPI。

一 文本格式数据的读写

将表格型数据读取为DataFrame 对象是 pandas 的重要特性。 表 6-1 总结了部分实现该功能的函数,有兴趣的可以参考。read_csv 和 read_table 是书中使用的最多函数, 而 read_excel 则是我推荐的, 用来处理excel 文件。

先打开cmd, 切到指定文件目录,然后先创建一个csv文件,命令为

type nul>ex1.csv

这是创建一个新的空文件的意思,然后可以找到该文件,使用任意编辑软件,这里我使用win10自带的记事本编写下该文件的内容,便于后续的读取操作。(其实创建文件也可以直接使用记事本,不需要cmd)

a,b,c,d,message

1,2,3,4,hello

5,6,7,8,world

9,10,11,12,foo

接下来,开始我们熟悉的python操作了

由于该文件是逗号分隔的,可以使用read_csv将它读入一个DataFrame

也可以使用read_table ,需要改下分隔符

在创建一个新的文件, 内容如下

1,2,3,4,hello5,6,7,8,world9,10,11,12,foo

要读取该文件,需要选择一些选项,可以允许pandas自动分配默认列名,也可以自己指定

假设想要message 列成为 返回DataFrame的索引,可以指定位置4的列为缩影,或将 ‘message’ 传给参数index_col

当想要从多个列中形成一个分层索引,需要传入一个包含列序号或列名的列表,先写一个csv文件,内容如下:

key1,key2,value1,value2one,a,1,2one,b,3,4one,c,5,6one,d,7,8two,a,9,10two,b,11,12two,c,13,14two,d,15,16

并命名为csv_mindex.csv

key1,key2则是实现了分层索引

当字段是以多种不同数量的空格分开时,可以使用read_table,传入一个正则表达式作为分隔符

可以使用skiprows来跳过一些不想读取的行数

默认情况下,pandas 使用一些插件的表示,例如NA和NULL显示缺失值

na_values 选项可以传入一个列表或一组字符串来处理缺失值,在字典中,每列可以指定不同的缺失值标识

import pandas as pdimport numpy as np# 使用read_csv, 默认',' 作为分隔符df = pd.read_csv('ex1.csv')print(df)print('-------------------------')# 默认'\t', 可以指定分隔符print(pd.read_table('ex1.csv', sep=','))print('-------------------------')print(pd.read_csv('ex2.csv', header=None))print('-------------------------')print(pd.read_csv('ex2.csv', names=['a', 'b', 'c', 'd', 'message']))print('-------------------------')names = ['a', 'b', 'c', 'd', 'message']print(pd.read_csv('ex2.csv', names=names, index_col='message'))print('-------------------------')parsed = pd.read_csv('csv_mindex.csv',index_col=['key1', 'key2'])print(parsed)print('-------------------------')print(list(open('ex3.txt')))print('-------------------------')result = pd.read_table('ex3.txt', sep='\s+')print(result)print('-------------------------')# 忽略行print(pd.read_csv('ex4.csv', skiprows=[0, 2, 3]))print('-------------------------')# 缺失值显示result = pd.read_csv('ex5.csv')print(result)print('-------------------------')# 是否是缺失值print(pd.isnull(result))print('-------------------------')result = pd.read_csv('ex5.csv', na_values=['NULL'])print(result)print('-------------------------')sentinels = {'message': ['foo', 'NA'], 'something': ['two']}print(pd.read_csv('ex5.csv', na_values=sentinels))print('-------------------------')

表6-2 列举了这两个解析函数常用的选项

1. 分块读入文本文件

当处理大型文件或找出正确的参数集来正确处理大文件时,可能需要读入文件的一个小片段或按小块遍历文件。这里为了方便,可以从本书提供的github地址仓库,获取数据,这里提供ex6.csv文件的地址pydata-book/ex6.csv at 2nd-edition · wesm/pydata-book ()

在尝试大文件之前按,可以先对pandas的显示设置进行调整,使之更为紧凑

如果指向读取一小部分行,可以指明nrows

为了分块读入文件,可以指定chunksize作为每一块的行数,read_csv 返回的 TextParser 对象允许你根据 chunksize 遍历文件。

TextParser 还具有get_chunk方法,允许你按任意大小读取数据块

import pandas as pdimport numpy as nppd.options.display.max_rows = 10result = pd.read_csv('ex6.csv')print(result)print('-----------------------------')print(pd.read_csv('ex6.csv', nrows=5))print('-----------------------------')chunker = pd.read_csv('ex6.csv', chunksize=1000)print(chunker)print('-----------------------------')tot = pd.Series([])for piece in chunker:tot = tot.add(piece['key'].value_counts(), fill_value=0)tot = tot.sort_values(ascending=False)print(tot[:10])

2. 将数据写入文本格式

数据可以导出为分隔的形式, 使用DataFrame 的 to_csv 方法,可以将数据导出为逗号分隔的文件

其他的分隔符也是可以的,写入到sys.stdout 时,控制台打印的文本结果

输出值在输出时,以空字符串出现,可以时na_rep 参数对缺失值进行标注

也可以仅写入列的子集,并且按选择的顺序写入

Series 也有 to_csv 方法

import pandas as pdimport numpy as npimport sysdata = pd.read_csv('ex5.csv')print(data)print('-----------------------')data.to_csv('out.csv')print(pd.read_csv('out.csv'))print('-----------------------')data.to_csv(sys.stdout, sep='|')print('-----------------------')data.to_csv(sys.stdout, na_rep='NULL')print('-----------------------')data.to_csv(sys.stdout, index=False, header=False)print('-----------------------')data.to_csv(sys.stdout, index=False, columns=['a', 'b', 'c'])print('-----------------------')dates = pd.date_range('1/1/2000', periods=7)ts = pd.Series(np.arange(7), index=dates)ts.to_csv('tseries.csv')print(pd.read_csv('tseries.csv'))

3. 使用分隔格式

绝大多数的表格型数据都可以使用read_table从硬盘中读取,然而,在某些情况下,一些手动操作可能是必不可少的。接收一个带有一行或多行错误的文件并不少见,在该节有一些基础工具可以用于应对这些情况。

先从github仓库中获取ex7.csv文件

对于任何带有单字符分隔符的文件,可以使用Python的内建csv模块。要使用它,需要将任一打开的文件或文件型对象传给csv.reader。像遍历文件那样遍历reader会产生元组,元组的值为了删除引号的字符。

之后可以自行做一些必要处理,以将数据整理为需要的形式。

csv文件有多种不同的风格,如需根据不同的分隔符、字符串引用约定或行终止符定义一种新的格式时,可以使用csv.Dialect 定义一个简单的子类

需要手动写入被分隔的文件时,可以使用csv.writer,接收一个已经打开的可写入文件对象以及和csv.reader相同的csv方言,格式选项。

import pandas as pdimport numpy as npimport sysimport csvf = open('ex7.csv')reader = csv.reader(f)for line in reader:print(line)print('-------------------------------')# 先将文件读取为行的列表with open('ex7.csv') as f:lines = list (csv.reader(f))# 将数据拆分为列名行和数据行header, values = lines[0], lines[1:]# 生成一个包含数据列的字典,字典中行转置为列data_dict = {h: v for h, v in zip(header, zip(*values))}print(data_dict)print('---------------------------------')class my_dialect(csv.Dialect):lineterminator = '\n'delimiter = ';'quotechar = '"'quoting = csv.QUOTE_MINIMAL

表6-3 提供了CSV发言选项 作为参考

4. JSON 数据

JSON(JavaScript Object Notation),已经成为Web浏览器和其他应用间通过HTTP请求发送数据的标准格式。它是一种比CSV等表格文本形式更为自由的数据形式。

JSON 非常接近有效的Python代码,除了它的空值null和一些其他细微差别(例如,不允许列表末尾的逗号)之外。基本类型就是对象(字典)、数组(列表)、字符串、数字、布尔值和空值。对象中的所有键都必须是字符串。有几个Python库用于读写JSON数据。json 内置在 Python 标准库中,将JSON字符串转换为Python形式时,使用json.loads方法

另一方面json.dumps 可以将 Python对象转换回JSON

我们可以决定如何将JSON对象 或对象列表转换为DataFrame或其他数据结构,比较方便的方式是将字典构成的列表(之前是JSON对象)传入DataFrame构造函数,选出数据字段子集

pandas.read_json 可以自动将jason数据集 按照规定次序转换为 Series 或 DataFrame

从pandas 中数据导出为JSON,一种办法是对 Series 和 DataFrame 使用to_json方法

import pandas as pdimport numpy as npimport jsonobj = """{"name": "Wes","places_lived": ["United States", "Spain", "Germany"],"pet": null,"siblings": [{"name": "Scott", "age": 30, "pets": ["Zeus", "Zuko"]},{"name": "Katie", "age": 38,"pets": ["Sixes", "Stache", "Cisco"]}]}"""result = json.loads(obj)print(result)print('-------------------------------')asjson = json.dumps(result)print(asjson)print('-------------------------------')siblings = pd.DataFrame(result['siblings'], columns=['name', 'age'])print(siblings)print('-------------------------------')data = pd.read_json('example.json')print(data)print('-------------------------------')print(data.to_json())print('-------------------------------')print(data.to_json(orient='records'))

5. XML 和 HTML:网络抓取

python 拥有很多对 HTML 和 XML 格式进行读取、写入数据的库。

pandas 的内建read_html 可以使用 lxml 和 Beautiful Soup 等库将 HTML 中的表自动解析为 DataFrame 对象。

先安装read_html所使用的附加库,在Anaconda Prompt 下键入如下命令:

conda install lxmlpip install beautifulsoup4 html5lib

read_html 函数有很多选项,默认情况下,它会搜索并尝试解析所有包含在

标签中的表格型数据,返回的是DataFrame 对象的列表

import pandas as pdimport numpy as npimport jsontables = pd.read_html('fdic_failed_bank_list.html')print(len(tables))failures = tables[0]print(failures.head())print('----------------------------------------')close_timestamps = pd.to_datetime(failures['Closing Date'])print(close_timestamps.dt.year.value_counts())

5.1 使用 lxml.objectify 解析 XML

XML(eXtensible Markup Language)是另一种常用的结构化数据格式,使用元数据支持分层、嵌套数据。

先从github仓库中下载xml文件Performance_MNR.xml

使用lxml.objectify, 我们可以解析这个文件,并用getroot来获得对XML文件的根节点的引用

root.INDICATOR 返回一个生成器,可以产生每一个XML 元素。对于每条记录,我们可以将标签名称的字典填充为数据值。

XML 数据可以更复杂,每个标签也可以包含元数据。

import pandas as pdimport numpy as npimport jsonfrom lxml import objectifypath = 'Performance_MNR.xml'parsed = objectify.parse(open(path))root = parsed.getroot()data = []skip_fields = ['PARENT_SEQ', 'INDICATOR_SEQ', 'DESIRED_CHANGE', 'DECIMAL_PLACES']# for elt in root.INDICATOR:#el_data = {}#for child in elt.getchildren():# if child.tag in skip_fields:# continue# el_data[child.tag] = child.pyval#data.append(el_data)perf = pd.DataFrame(data)print(perf.head())from io import StringIOtag = '<a href="">Google</a>'root = objectify.parse(StringIO(tag)).getroot()print(root)print(root.get('href'))print(root.text)

二 二进制格式

使用Python 内建的 pickle 序列化模块进行二进制格式操作是存储数据(也称为序列化)最高效、最方便的方式之一。pandas对象的to_pickle方法就是如此。

可以使用内建的pickle读取文件中“pickle化” 对象,或更方便地使用pandas.read_pickle 做上述操作

pickle 仅被推荐为短期的存储格式。问题在于pickle很难确保格式地长期有效性;一个今天被pickle化的对象可能明天会因为库的新版本而无法序列化。

pandas 内建支持其他两个二进制格式 HDF5 和 MessagePack。pandas或NumPy 其他的存储格式包括:bcolz,Feather

import sysimport pandas as pdimport numpy as npframe = pd.read_csv('ex1.csv')print(frame)print('------------------------------')frame.to_pickle('frame_pickle')print(pd.read_pickle('frame_pickle'))print('------------------------------')

1. 使用HDF5格式

HDF5是一个备受好评的文件格式,用于存储大量的科学数组数据。以C库的形式提供,并且具有许多语言的接口,HDF5中的 “HDF” 表示分层数据格式。每个HDF5文件可以存储多个数据集并且支持元数据,支持多种压缩模式的即时压缩,可以高效地存储重复模式的数据,适用于处理不适合在内存中存储的超大型数据,方便我们高效地读写大型数组的一小块。

pandas提供了一个HDF5的高阶接口,可以简化Series和DataFrame的存储。HDFStore类像字典一样工作并处理低级别的细节

包含在HDF5文件中的对象可以使用相同的字典型API进行检索

HDFStore 支持两种存储格式, ‘fixed’ 和 ‘table’。 后者速度更慢,但支持一种特殊语法的查询操作

put 是 store[‘obj2’] = frame 方法的显示版本,但允许我们设置其他选项,比如存储格式

pandas.read_hdf 函数是这些工具的快捷方法

如果你处理存储在远程服务器上的数据时,比如Amazon S3 或 HDFS, 使用其他专门为分布式存储而设计的二进制格式更为合适,比如Apache Parquet。 Paequet 和其他类似的存储格式仍然在发展中。

如果是在本地处理大量数据,书中推荐尝试 PyTables 和 h5py,看看它们是否符合需求。由于很多数据分析的困难在于I/O密集,使用像HDF5 这样的工具可以大大加速应用。

HDF5 并不是数据库,而是一种适合一次写入多次读取的数据集。尽管数据可以在任何时间添加到文件中,但如果是多个写入者持续写入,文件可能会损坏。

import pandas as pdimport numpy as npframe = pd.DataFrame({'a': np.random.randn(100)})store = pd.HDFStore('mydata.h5')store['obj1'] = framestore['obj_col'] = frame['a']print(store)print('-------------------')print(store['obj1'])print('-------------------')store.put('obj2', frame, format='table')print(store.select('obj2', where=['index >= 10 and index <= 15']))store.close()print('-------------------')frame.to_hdf('mydata.h5', 'obj3', format='table')print(pd.read_hdf('mydata.h5', 'obj3', where=['index < 5']))

2. 读取Microsoft Excel 文件

pandas 也支持通过ExcelFile 类或pandas.read_excel 函数来读取存储在Excel 或者更高版本的表格型数据,这些工具内部是使用附加包xlrd和openpyxl 来分别读取XLS 和 XLSX 文件的。

这些附加包需要安装,可以参考下列命令

conda install xlrdconda install openpyxl

之后运行下述代码会出现一个问题

import numpy as npimport pandas as pdxlsx = pd.ExcelFile('examples/ex1.xlsx')

或者是让你指定一个egine, 或者是上面的问题,可能的原因有多种,我看了相关的blog最后才发现和那些blog说的指定egine或者没安装相关包无关,而是文件损坏,重新写下文件就好了。

如果读取含多个表的文件,生成ExcelFile 更快,但也可以更简洁地将文件名传入read_excel

如果需要将数据写入到Excel格式中,必须先生成一个ExcelWriter,然后使用pandas对象地to_excel 方法

也可以将文件路径传给to_excel,避免直接使用ExcelWriter

import numpy as npimport pandas as pdxlsx = pd.ExcelFile('examples/ex2.xlsx')print(pd.read_excel(xlsx, 'Sheet1'))print('----------------------------------------')frame = pd.read_excel('examples/ex2.xlsx', 'Sheet1')print(frame)print('----------------------------------------')writer = pd.ExcelWriter('examples/ex3.xlsx')frame.to_excel(writer, 'Sheet1')writer.save()frame.to_excel('examples/ex3.xlsx')print(pd.read_excel('examples/ex3.xlsx'))

三 与Web API交互

很多网站都有公开API, 通过JSON 或其他格式提供数据服务,很多方式可以利用Python来访问API,书的作者推荐使用requests包。

Response 对象地json方法 将返回 一个包含解析为 本地 Python 对象地 JSON 地字典

import numpy as npimport pandas as pdimport requestsurl = '/repos/pandas-dev/pandas/issues'rep = requests.get(url)print(rep)print('-------------------------')data = rep.json()print(data[0]['title'])print('-------------------------')issues = pd.DataFrame(data, columns=['number', 'title', 'labels', 'states'])print(issues)

四 与数据库交互

在业务场景中,大部分数据并不是在文件或Excel文件中的。基于SQL的关系型数据库(例如SQL Server、 PostgreSQL和 MySQL)使用广泛,很多小众数据库也变得越发流行。数据库的选择通常取决于性能、数据完整性以及应用的可伸缩性需求。

从SQL中将数据读取为DataFrame是简单直接的,pandas 有很多方法可以简化这个过程。作为例子,我将使用Python内建的squlite3驱动来生成一个SQLite数据库

import numpy as npimport pandas as pdimport sqlite3query = """CREATE TABLE test(a VARCHAR(20), b VARCHAR(20),c REAL, d INTEGER);"""con = sqlite3.connect('mydata.sqlite')print('----------------------------')mit()data = [('Atlanta', 'Georgia', 1.25, 6),('Tallahassee', 'Florida', 2.6, 3),('Sacramento', 'California', 1.7, 5)]stmt = "INSERT INTO test VALUES(?, ?, ?, ?)"print(con.executemany(stmt, data))mit()cursor = con.execute('select * from test')rows = cursor.fetchall()print('----------------------------')print(rows)print('----------------------------')print(cursor.description)print('----------------------------')print(pd.DataFrame(rows, columns=[x[0] for x in cursor.description]))print('----------------------------')import sqlalchemy as sqladb = sqla.create_engine('sqlite:///mydata.sqlite')print(pd.read_sql('select * from test', db))

小结 后话

访问数据是第一步,接下来会继续学习数据处理、可视化、时间序列分析和其他主题。

今天又寄了,但是程璐赢了,我可以开摆了。

it()

cursor = con.execute(‘select * from test’)

rows = cursor.fetchall()

print(’----------------------------’)

print(rows)

print(’----------------------------’)

print(cursor.description)

print(’----------------------------’)

print(pd.DataFrame(rows, columns=[x[0] for x in cursor.description]))

print(’----------------------------’)

import sqlalchemy as sqla

db = sqla.create_engine(‘sqlite:///mydata.sqlite’)

print(pd.read_sql(‘select * from test’, db))

## 小结 后话访问数据是第一步,接下来会继续学习数据处理、可视化、时间序列分析和其他主题。今天又寄了,但是程璐赢了,我可以开摆了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。