本博客为《利用Python进行数据分析》的读书笔记,请勿转载用于其他商业用途。
1. 分块读入文本文件
当处理大型文件或找出正确的参数集来正确处理大文件时,我们可能需要读入文件的一个小片段或者按小块遍历文件。
在尝试大文件之前,我们可以先对pandas的现实设置进行调整,使之更为紧凑:
pd.options.display.max_rows = 10
现在我们可以得到:
result = pd.read_csv('C:/ex6.csv')
print(result)
#
one two three four key
0 0.12 -0.34 0.56 -0.78 A
1 1.12 0.66 1.56 0.22 J
2 2.12 1.66 2.56 1.22 L
3 3.12 2.66 3.56 2.22 F
4 4.12 3.66 4.56 3.22 B
.. ... ... ... ... ..
94 94.12 93.66 94.56 93.22 T
95 95.12 94.66 95.56 94.22 R
96 96.12 95.66 96.56 95.22 E
97 97.12 96.66 97.56 96.22 W
98 98.12 97.66 98.56 97.22 Q
[99 rows x 5 columns]
如果你只想读取一小部分(避免读取整个文件),可以指明nrows
:
result = pd.read_csv('C:/ex6.csv', nrows=5)
print(result)
#
one two three four key
0 0.12 -0.34 0.56 -0.78 A
1 1.12 0.66 1.56 0.22 J
2 2.12 1.66 2.56 1.22 L
3 3.12 2.66 3.56 2.22 F
4 4.12 3.66 4.56 3.22 B
为了分块读入文件,可以指定chunksize作为每一块的行数:
chunker = pd.read_csv('ex6.csv', chunksize=50)
print(chunker)
#
<pandas.io.parsers.TextFileReader object at 0x02F6F8B0>
read_csv
返回的TextParser
对象允许你根据chunksize遍历文件。例如,我们可以遍历ex6.csv,并对’key’列聚合获得计数值:
chunker = pd.read_csv('ex6.csv', chunksize=50)
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])
#
L 13.0
R 11.0
E 11.0
Y 6.0
T 6.0
Q 6.0
W 6.0
I 5.0
C 5.0
G 5.0
dtype: float64
该代码的意思是,在key列中,以上字母共出现了多少次。TextParser
还具有get_chunk
方法,允许你按照任意大小读取数据块。
2. 将数据写入文本格式
数据可以导出为分隔的形式:
data = pd.read_csv('ex5.csv')
print(data)
#
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
使用DataFrame的to_csv
方法,我们可以将数据导出为逗号分隔的文件:
略。
当然,其他的分隔符也是可以的(写入到sys.stdout
时,控制台中打印机的文本结果):
import sys
result = data.to_csv(sys.stdout, sep='|')
print(result)
#
|Unnamed: 0|something|a|b|c|d|message
0|0|one|1|2|3.0|4|
1|1|two|5|6||8|world
2|2|three|9|10|11.0|12|foo
缺失值在输出时以空字符串出现。你也许想要用其他标识值对缺失值进行标注:
result = data.to_csv(sys.stdout, na_rep='NULL')
print(result)
#
,Unnamed: 0,something,a,b,c,d,message
0,0,one,1,2,3.0,4,NULL
1,1,two,5,6,NULL,8,world
2,2,three,9,10,11.0,12,foo
如果没有其他按选项被指定的话,行和列的标签都会被写入。不过二者也都可以禁止写入:
result = data.to_csv(sys.stdout, index=False, header=False)
print(result)
#
0,one,1,2,3.0,4,
1,two,5,6,,8,world
2,three,9,10,11.0,12,foo
None
你也可以仅写入列的子集,并且按照你选择的顺序写入:
result = data.to_csv(sys.stdout, index=False, columns=['a', 'b', 'c'])
print(result)
#
a,b,c
1,2,3.0
5,6,
9,10,11.0
None
3. 使用分隔格式
绝大多数的表型数据都可以使用函数pandas.read_table
从硬盘中读出。然而,在某些情况下,一些手动操作可能是必不可少的。接受一个带有一行或者多行错误的文件并不少见,read_table
也无法解决这种情况。为了介绍一些基础工具,考虑如下的小型csv文件:
对于任何带有单字符分隔符的文件,我们可以使用Python内置的内建csv模块。要使用它,需要将任一打开的文件或文件类型对象传给csv.reader
:
import csv
f = open('ex7.csv')
reader = csv.reader(f)
像遍历文件那样遍历reader会产生元组,元组的值为删除了引号的字符:
import csv
f = open('ex7.csv')
reader = csv.reader(f)
for line in reader:
print(line)
#
['"a"', '"b"', '"c"']
['"1"', '"2"', '"3"']
['"1"', '"2"', '"3"']
按照书中的操作,理论上应该得到去掉双引号的字符,然而事实并不是这样的……不管了,我们继续。
表:CSV方言选项
参数 | 描述 |
---|---|
delimiter | 一个用于分隔字段的字符,默认是‘,’ |
lineterminator | 行终止符,默认是‘\r\n’,读取器会忽略行终止符并识别跨平台行终止符 |
quotechar | 用在含有特殊字符字段中的引号,默认是’ " ’ |
quoting | 引用惯例。选项包括csv.QUOTE_ALL (引用所有的字段),cdv.QUOTE_MINIMAL (只使用特殊字符,如分隔符),csv.QUOTE_NONNUMERIC 和csv.QUOTE_NONE (不引用)。细节请参考Python的文档。默认是QUOTE_MINIMAL
|
skipinitialspace | 忽略每个分隔符后的空白,默认是False |
doublequote | 如何处理字段内部的引号。如果为True,则是双引号 |
escapechar | 当引用设置为csv.QUOTE_NONE 时用于转移分隔符的字符串,默认是禁用的 |
对于具有更复杂或固定的多字符分隔符的文件,你将无法使用csv模块。在此类情况下,你将不得不使用字符串的split
方法或正则表达式方法re.split
进行行拆分和其他清理工作。
需要手动写入被分隔的文件时,可以使用csv.writer
。这个函数接受一个已经打开的可写入文件对象以及和csv.reader
相同的CSV方言、格式选项:
with open('mydata.csv', 'w')as f:
writer = csv.writer(f, dialect=my_dialect)
writer.writerow(('one', 'two', 'three'))
writer.writerow(('1', '2', '3'))
writer.writerow(('4', '5', '6'))
writer.writerow(('7', '8', '9'))
4. JSON数据
JSON(JavaScript Object Notation)已经成为Web浏览器和其他应用间通过HTTP请求发送数据的标准格式。它是一种比CSV表格文本形式更为*的数据形式。请看下面的例子:
obj = """
{"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"]}]
}
"""
JSON非常接近有效的Python代码,除了它的值null
和一些其他的细微差别(例如不允许列表末尾的逗号)之外。基本类型是对象(字典)、数组(列表)、字符串、数字、布尔值和空值。对象中的所有键必须是字符串。有几个Python库用于读写JSON数据。我们将在这里使用json,因为它是内置在Python标准库中的。将JSON字符串转换为Python时,使用json.loads
方法:
import json
result = json.loads(obj)
print(result)
#
{'name': 'Wes', 'places_lived': ['United States', 'Spain', 'Germany'],
'pet': None, 'siblings': [{'name': 'Scott', 'age': 30, 'pets': ['Zeus', 'Zuko']},
{'name': 'Katie', 'age': 38, 'pets': ['Sixes', 'Stache', 'Cisco']}]}
另一方面,json.dumps
方法可以将Python对象转换为JSON:
asjson = json.dumps(result)
你将自行决定如何将JSON对象或对象列表转换为DataFrame或其他数据结构。比较方便的方式是将字典构成的列表(之前是JSON对象)传入DataFrame构造函数,并选出数据字段的子集:
siblings = pd.DataFrame(result['siblings'], columns=['name', 'age'])
print(siblings)
#
name age
0 Scott 30
1 Katie 38
pandas.read_json
可以自动将JSON数据集按照指定次序转换为Series或DataFrame。
首先我们创建一个JSON文件:pandas.read_json
的默认选项是假设JSON数组中的没个对象是表里的一行:
data = pd.read_csv('example.json')
print(data)
#
[{"a": 1 "b": 2 "c": 3} Unnamed: 3
0 {"a": 4 "b": 5 "c": 6} NaN
1 {"a": 7 "b": 8 "c": 9}] NaN
得到是这个鬼东西……跟书上的不一样啊……算了……
如果需要从pandas中将数据导出为JSON,一种办法是对Series和DataFrame使用to_json
方法:
print(data.to_json())
5. XML和HTML:网络抓取
Python拥有很多可以对HTML和XML格式进行读取、写入数据的库。例如lxml、Beautiful Soup和htmal5lib。尽管lxml是相对更快的库,但其他库可以更好地处理异常的HTML和XML文件。
pandas的内建函数read_hml
可以使用lxml和Beautiful Soup等库将HTML中的表自动解析为DataFrame对象。为了展示这个功能,我们从美国FDIC*机构下载了显示银行倒闭数据的HTML文件(在pandas文档中使用)。pandas.read_html
函数有很多选项,但是默认情况下,它会搜索并尝试解析所有包含在<table>
标签中的表格型数据,返回的结果是DataFrame对象的列表:
tables = pd.read_html('FDIC_ Failed Bank List.html')
print(len(tables))
#
1
failures = tables[0]
print(failures)
#
Bank Name ... Closing Date
0 City National Bank of New Jersey ... November 1, 2019
1 Resolute Bank ... October 25, 2019
2 Louisa Community Bank ... October 25, 2019
3 The Enloe State Bank ... May 31, 2019
4 Washington Federal Bank for Savings ... December 15, 2017
.. ... ... ...
554 Superior Bank, FSB ... July 27, 2001
555 Malta National Bank ... May 3, 2001
556 First Alliance Bank & Trust Co. ... February 2, 2001
557 National State Bank of Metropolis ... December 14, 2000
558 Bank of Honolulu ... October 13, 2000
[559 rows x 6 columns]
以上是Pycharm显示的结果,我们再看下Conda显示的结果:
我去,爱了爱了……
此处我们可以着手一些数据清理和分析工作,比如计算每年银行倒闭的数量:
close_timestamps = pd.to_datetime(failures['Closing Date'])
print(close_timestamps.dt.year.value_counts())
#
2010 157
2009 140
2011 92
2012 51
2008 25
2013 24
2014 18
2002 11
2015 8
2017 8
2016 5
2001 4
2019 4
2004 4
2003 3
2007 3
2000 2
Name: Closing Date, dtype: int64
Chrishany
发布了23 篇原创文章 · 获赞 6 · 访问量 496
私信
关注