ch6_01 Pandas 数据加载、存储&文件格式

Jupyter notebook给你不一样的阅读体验!

  • 输入输出通常分为以下几大类:读取文本文件和其他的更高效的磁盘存储格式、加载数据库中的数据、利用Web API操作网络资源

6.1读写文本格式的数据

  • pandas提供了一些用于将表格型数据读取为DataFrame对象的函数。下表进行了总结,其中用的比较多的就是read_csv和read_table

6.1

import pandas as pd
df = pd.read_csv('data/ex1.csv')
df
abcdmessage
01234hello
15678world
29101112foo
  • 虽然是.csv文件,但是可以使用read_table来读取,但是需要指定分隔符为“,”
pd.read_table('data/ex1.csv',sep=',')
d:\program filles\python\lib\site-packages\ipykernel_launcher.py:1: ParserWarning: Falling back to the 'python' engine because the separator encoded in utf-8 is > 1 char long, and the 'c' engine does not support such separators; you can avoid this warning by specifying engine='python'.
  """Entry point for launching an IPython kernel.
a,b,c,d,message
01,2,3,4,hello
15,6,7,8,world
29,10,11,12,foo
  • 并不是所有的文件都有标题行,读入文件时可以使用默认的列名,也可以自己定义
pd.read_csv('data/ex2.csv',header=None)
01234
01234hello
15678world
29101112foo
pd.read_csv('data/ex2.csv',names=['A','B','C','D','message'])
ABCDmessage
01234hello
15678world
29101112foo
  • 如果想要明确的将该列放到索引4的位置上可以通过index_col指定message
names = ['a','b','c','d','message']
pd.read_csv('data/ex2.csv',names=names, index_col='message')
abcd
message
hello1234
world5678
foo9101112
  • 如果想要将多个列做成一个层次化索引,只需传入由列编号或列名组成的列表即可
parsed = pd.read_csv('data/csv_mindex.csv',index_col=['key1','key2'])
parsed
value1value2
key1key2
onea12
b34
c56
d78
twoa910
b1112
c1314
d1516
  • 还有一些文件含有不需要的数据,可以使用skiprows参数 跳过指定的行
result = pd.read_csv('data/ex4.csv',skiprows=[0,2,3])
result
abcdmessage
01234hello
15678world
29101112foo
  • 缺失数据经常是要么没有(空字符串),要么用某个标记值表示。默认情况下,pandas会用一组经常出现的标记值进行识别,比如NA及NULL:
result = pd.read_csv('data/ex5.csv')
result
somethingabcdmessage
0one123.04NaN
1two56NaN8world
2three91011.012foo
pd.isnull(result)
somethingabcdmessage
0FalseFalseFalseFalseFalseTrue
1FalseFalseFalseTrueFalseFalse
2FalseFalseFalseFalseFalseFalse
  • 参数na_values可以使用一个列表或者集合的字符串表示缺失值
result = pd.read_csv('data/ex5.csv',na_values=['NULL'])
result
somethingabcdmessage
0one123.04NaN
1two56NaN8world
2three91011.012foo
  • 字典的各列可以使用不同的NA标记值
sentinels = {'message':['foo','NA'],'something':['two']}
pd.read_csv('data/ex5.csv',na_values=sentinels)
somethingabcdmessage
0one123.04NaN
1NaN56NaN8world
2three91011.012NaN
  • read_csv和read_table 一些常用的参数
    参数列表
    参数列表
    参数列表

逐块读取文本文件

  • 在处理很大的文件时,或找出大文件中的参数集以便于后续处理时,你可能只想读取文件的一小部分或逐块对文件进行迭代。
  • 在看大文件之前,需要先设置pandas的一些参数
pd.options.display.max_rows = 8
result = pd.read_csv('data/examples/ex6.csv')
result
onetwothreefourkey
00.467976-0.038649-0.295344-1.824726L
1-0.3588931.4044530.704965-0.200638B
2-0.5018400.659254-0.421691-0.057688G
30.2048861.0741341.388361-0.982404R
..................
9996-0.479893-0.6504190.745152-0.646038E
99970.5233310.7871120.4860661.093156K
9998-0.3625590.598894-1.8432010.887292G
9999-0.096376-1.012999-0.657431-0.5733150

10000 rows × 5 columns

  • 如果之想读取几行,可以通过nrows进行指定即可:
pd.read_csv('data/examples/ex6.csv',nrows=5)
onetwothreefourkey
00.467976-0.038649-0.295344-1.824726L
1-0.3588931.4044530.704965-0.200638B
2-0.5018400.659254-0.421691-0.057688G
30.2048861.0741341.388361-0.982404R
40.354628-0.1331160.283763-0.837063Q
  • 如果要逐块的读取文件,可以指定chunksize(行数)
chunker = pd.read_csv('data/examples/ex6.csv',chunksize=1000)
chunker
<pandas.io.parsers.TextFileReader at 0xed5ed0>
  • read_csv所返回的这个TextParser对象使你可以根据chunksize对文件进行逐块迭代。比如说,我们可以迭代处理ex6.csv,将值计数聚合到"key"列中,如下所示:
tot = pd.Series([])
for piece in chunker:
    tot = tot.add(piece['key'].value_counts(),fill_value=0)
tot = tot.sort_values(ascending=False)
tot[:10]
E    368.0
X    364.0
L    346.0
O    343.0
     ...  
J    337.0
F    335.0
K    334.0
H    330.0
Length: 10, dtype: float64

将数据写出到文本格式

  • 数据也可以被输出为分隔符格式的文本
data = pd.read_csv('data/examples/ex5.csv')
data
somethingabcdmessage
0one123.04NaN
1two56NaN8world
2three91011.012foo
data.to_csv('data/out.csv')# 也可以传入一个sep参数,指定分隔符
  • 缺失值在输出结果中会被表示为空字符串。也可将其表示为别的标记值
import sys
data.to_csv(sys.stdout,na_rep='NULL')
,something,a,b,c,d,message
0,one,1,2,3.0,4,NULL
1,two,5,6,NULL,8,world
2,three,9,10,11.0,12,foo
  • 如果没有设置其他参数,则默认列出行和列的标签。也可以不列出:
data.to_csv(sys.stdout,index=False,header=False)
one,1,2,3.0,4,
two,5,6,,8,world
three,9,10,11.0,12,foo
  • 也可以只列出一部分列,并指定输出的顺序
data.to_csv(sys.stdout,index=False,columns=['a','c','b'])
a,c,b
1,3.0,2
5,,6
9,11.0,10
  • Series也有一个to_csv 的方法
import numpy as np
dates = pd.date_range('1/1/2000',periods=7)
ts = pd.Series(np.arange(7),index = dates)
ts.to_csv('data/tseries.csv')
pd.read_csv('data/tseries.csv')
2000-01-010
02000-01-021
12000-01-032
22000-01-043
32000-01-054
42000-01-065
52000-01-076

处理分隔符格式

  • 大部分存储在磁盘上的表格型数据都可以使用pandas.read_csv进行加载。但有时候需要做一些手工处理
import pandas as pd
import csv
f = open("data/examples/ex7.csv")
reader = csv.reader(f)
#对这个reader进行迭代将会为每行产生一个元组(并移除了所有的引号):
for line in reader:
    print(line)
['a', 'b', 'c']
['1', '2', '3']
['1', '2', '3']
  • 为了让数据格式符合要求,需要做以下工作。首先读取文件到一个多行的列表中:
with open("data/examples/ex7.csv") as f:
    lines = list(csv.reader(f))
     #然后将这些行分为标题行和数据行
    header, values = lines[0], lines[1:]
    #然后,我们可以用字典构造式和zip(*values),后者将行转置为列,创建数据列的字典:
    data_dict = {h:v for h,v in zip(header,zip(*values))}
 data_dict
{'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}
  • CSV文件的形式有很多。只需定义csv.Dialect的一个子类即可定义出新格式(如专门的分隔符、字符串引用约定、行结束符等):
class my_dialect(csv.Dialect):
    lineterminator = '\n'
    delimiter = '|'
    quotechar = '"'
    quoting = csv.QUOTE_MINIMAL

with open("data/examples/ex7.csv") as f:
    reader = csv.reader(f,dialect=my_dialect)
    print(reader)
<_csv.reader object at 0x07025DB0>
  • 各个CSV语支的参数也可以用关键字的形式提供给csv.reader,而无需定义子类:
with open("data/examples/ex7.csv") as f:
    reader = csv.reader(f,delimiter='|')
    print(reader)
<_csv.reader object at 0x07025D30>
  • 可用的选项(csv.Dialect的属性)及其功能如表6-3所示

  • 要手工输出分隔符文件,你可以使用csv.writer。它接受一个已打开且可写的文件对象以及跟csv.reader相同的那些语支和格式化选项:

with open('data/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'))

JSON 文件

  • JSON(JavaScript Object Notation的简称)已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。它是一种比表格型文本格式(如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"]}]
}
"""
  • 除其空值null和一些其他的细微差别(如列表末尾不允许存在多余的逗号)之外,
    JSON非常接近于有效的Python代码。基本类型有对象(字典)、数组(列表)、字符串、数值、布尔值以及null。
    对象中所有的键都必须是字符串。许多Python库都可以读写JSON数据。我将使用json,因为它是构建于Python标准库中的。通过json.loads即可将JSON字符串转换成Python形式:
import json
result = json.loads(obj)
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)
asjson
'{"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对象转换为DataFrame最简单方便的方式是:向DataFrame构造器传入一个字典的列表(就是原先的JSON对象),并选取数据字段的子集:
siblings = pd.DataFrame(result['siblings'],columns=['name','age'])
siblings
nameage
0Scott30
1Katie38
  • pandas.read_json可以自动将特别格式的JSON数据集转换为Series或DataFrame。默认选项假设JSON数组中的每个对象是表格中的一行:
data = pd.read_json('data/examples/example.json')
data
abc
0123
1456
2789
  • 将数据从pandas输出到JSON,可以使用to_json方法:
print(data.to_json())
{"a":{"0":1,"1":4,"2":7},"b":{"0":2,"1":5,"2":8},"c":{"0":3,"1":6,"2":9}}
print(data.to_json(orient='records'))
[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]

XML和HTML:Web信息收集

  • Python有许多可以读写常见的HTML和XML格式数据的库,包括lxml、Beautiful Soup和html5lib。lxml的速度比较快,但其它的库处理有误的HTML或XML文件更好。pandas有一个内置的功能,read_html,它可以使用lxml和Beautiful Soup自动将HTML文件中的表格解析为DataFrame对象
import pandas as pd
tables = pd.read_html('data/examples/fdic_failed_bank_list.html')
len(tables)
1
failures = tables[0]
failures.head()
Bank NameCitySTCERTAcquiring InstitutionClosing DateUpdated Date
0Allied BankMulberryAR91Today's BankSeptember 23, 2016November 17, 2016
1The Woodbury Banking CompanyWoodburyGA11297United BankAugust 19, 2016November 17, 2016
2First CornerStone BankKing of PrussiaPA35312First-Citizens Bank & Trust CompanyMay 6, 2016September 6, 2016
3Trust Company BankMemphisTN9956The Bank of Fayette CountyApril 29, 2016September 6, 2016
4North Milwaukee State BankMilwaukeeWI20364First-Citizens Bank & Trust CompanyMarch 11, 2016June 16, 2016
  • 这里可以先做一些数据清洗和统计
close_timestamps = pd.to_datetime(failures['Closing Date'])
close_timestamps.dt.year.value_counts()
2010    157
2009    140
2011     92
2012     51
2008     25
2013     24
2014     18
2002     11
2015      8
2016      5
2004      4
2001      4
2007      3
2003      3
2000      2
Name: Closing Date, dtype: int64

利用lxml.objectify解析XML

  • XML(Extensible Markup Language)是另一种常见的支持分层、嵌套数据以及元数据的结构化数据格式。介绍了pandas.read_html函数,XML和HTML的结构很相似,但XML更为通用。
from lxml import objectify
#先用lxml.objectify解析该文件,然后通过getroot得到该XML文件的根节点的引用
path = 'data/mta_perf/Performance_MNR.xml'
parsed = objectify.parse(open(path))
root = parsed.getroot()
#root.INDICATOR返回一个用于产生各个<INDICATOR>XML元素的生成器。
#对于每条记录,我们可以用标记名(如YTD_ACTUAL)和数据值填充一个字典(排除几个标记)
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)
# 最后将数组字典转换为dataFrame
perf = pd.DataFrame(data)
perf.head()
AGENCY_NAMECATEGORYDESCRIPTIONFREQUENCYINDICATOR_NAMEINDICATOR_UNITMONTHLY_ACTUALMONTHLY_TARGETPERIOD_MONTHPERIOD_YEARYTD_ACTUALYTD_TARGET
0Metro-North RailroadService IndicatorsPercent of commuter trains that arrive at thei...MOn-Time Performance (West of Hudson)%96.9951200896.995
1Metro-North RailroadService IndicatorsPercent of commuter trains that arrive at thei...MOn-Time Performance (West of Hudson)%9595220089695
2Metro-North RailroadService IndicatorsPercent of commuter trains that arrive at thei...MOn-Time Performance (West of Hudson)%96.9953200896.395
3Metro-North RailroadService IndicatorsPercent of commuter trains that arrive at thei...MOn-Time Performance (West of Hudson)%98.3954200896.895
4Metro-North RailroadService IndicatorsPercent of commuter trains that arrive at thei...MOn-Time Performance (West of Hudson)%95.8955200896.695
from io import StringIO
tag = '<a href="http://www.google.com">Google</a>'
root  = objectify.parse(StringIO(tag)).getroot()
#接下来就可以访问标签或者链接文本中的任何字段
root
<Element a at 0xcac8a0>
root.get('href')
'http://www.google.com'
root.text
'Google'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值