数据分析--数据加载,存储与文件格式

Data Loading, Storage,

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

xiaoyao

import numpy as np
import pandas as pd
np.random.seed(12345)
import matplotlib.pyplot as plt
plt.rc('figure', figsize=(10, 6))
np.set_printoptions(precision=4, suppress=True)

Reading and Writing Data in Text Format

读取,将数据写入到text文件中

# read_csv默认以','间隔
df = pd.read_csv('examples/ex1.csv')
df
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
# read_table默认以'\t'分隔
pd.read_table('examples/ex1.csv', sep=',')
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
"""有的文件没有标题行,可以通过pandas为其分配默认的列名,也可以自定义列名
"""
pd.read_csv('examples/ex2.csv', names=['a', 'b', 'c', 'd', 'message'])
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
pd.read_csv('examples/ex2.csv', header=None)
0 1 2 3 4
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
"""
如果希望将message列做成DataFrame的索引,可以明确表示将该列放到索引4的位置上,也可以通过
index_col参数指定“message”
"""
names = ['a', 'b', 'c', 'd', 'message']
pd.read_csv('examples/ex2.csv', names=names, index_col='message')
a b c d
message
hello 1 2 3 4
world 5 6 7 8
foo 9 10 11 12
# !cat examples/csv_mindex.csv
parsed = pd.read_csv('examples/csv_mindex.csv',
                     index_col=['key1', 'key2'])
parsed
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
list(open('examples/ex3.txt'))
['            A         B         C\n',
 'aaa -0.264438 -1.026059 -0.619500\n',
 'bbb  0.927272  0.302904 -0.032399\n',
 'ccc -0.264273 -0.386314 -0.217601\n',
 'ddd -0.871858 -0.348382  1.100491\n']

有些表格可能不是用固定的分隔符去分隔字段的(比如说:空白字符或者其他模式)。有些表格可能不是用固定的分隔字段的(比如空白字符或者其他模式来分隔字段)。

正则表达式中\s匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[ \f\n\r\t\v]

  • \f -> 匹配一个换页
  • \n -> 匹配一个换行符
  • \r -> 匹配一个回车符
  • \t -> 匹配一个制表符
  • \v -> 匹配一个垂直制表符
    而“\s+”则表示匹配任意多个上面的字符。
"""
虽然可以手动对数据进行规整,这里的字段是被不同空白字符间隔开的。这种情况下,可以传递一个
正则表达式作为read_table的分隔符。可以使用正则表达式表达为: \s+

"""
result = pd.read_table('examples/ex3.txt', sep='\s+')
result
A B C
aaa -0.264438 -1.026059 -0.619500
bbb 0.927272 0.302904 -0.032399
ccc -0.264273 -0.386314 -0.217601
ddd -0.871858 -0.348382 1.100491
# 使用skiprows跳过文件的第一行,第三行,第四行
pd.read_csv('examples/ex4.csv', skiprows=[0, 2, 3])
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
# 缺失值处理是文件解析任务中的一个重要的组成部分。

# 缺失数据经常是没有(空字符串)要么使用某个标记值进行表示。

# 默认情况之下,pandas或使用一组经常出现的标记值进行识别,比如:NA以及NULL
result = pd.read_csv('examples/ex5.csv')
result
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
pd.isnull(result)
something a b c d message
0 False False False False False True
1 False False False True False False
2 False False False False False False
# na_values可以使用一个列表或者集合的字符串表示缺失值
result = pd.read_csv('examples/ex5.csv', na_values=['NULL'])
result
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
# 字典的各列可以使用不同的NA标记值
sentinels = {'message': ['foo', 'NA'], 'something': ['two']}
pd.read_csv('examples/ex5.csv', na_values=sentinels)
something a b c d message
0 one 1 2 3.0 4 NaN
1 NaN 5 6 NaN 8 world
2 three 9 10 11.0 12 NaN
这里列举出pandas.read_csv和pandas.read_tabel常用的选项。
参数 说明
path 表示文件系统的位置,url,文件型对象的字符串
sep或者delimiter 用于对行中各字段进行拆分的字符序列或者正则表达式
header 用作列名的行号。默认为0,表示第一行,如果没有header行就应该进行设置为None
index_col 用作行索引的列表好或者列名,可以是单个名称或者/数字组成的列表(层次化索引)
names 用于结果的列名列表,结合header=None
⋮ \vdots ⋮ \vdots

Reading Text Files in Pieces 逐块读取文本文件

在处理很大的文件的时候,或者找出大文件中的参数集以便于后续处理,可只想读取文件的一小部分或逐块对文件进行迭代。

# 在看大文件之前,可以先设置pandas显示更加紧密一些
pd.options.display.max_rows = 10
result = pd.read_csv('examples/ex6.csv')
result
one two three four key
0 0.467976 -0.038649 -0.295344 -1.824726 L
1 -0.358893 1.404453 0.704965 -0.200638 B
2 -0.501840 0.659254 -0.421691 -0.057688 G
3 0.204886 1.074134 1.388361 -0.982404 R
4 0.354628 -0.133116 0.283763 -0.837063 Q
... ... ... ... ... ...
9995 2.311896 -0.417070 -1.409599 -0.515821 L
9996 -0.479893 -0.650419 0.745152 -0.646038 E
9997 0.523331 0.787112 0.486066 1.093156 K
9998 -0.362559 0.598894 -1.843201 0.887292 G
9999 -0.096376 -1.012999 -0.657431 -0.573315 0

10000 rows × 5 columns

# 如果只想读入几行(避免读取整个文件),可以通过nrows进行指定即可。
pd.read_csv('examples/ex6.csv', nrows=5)
one two three four key
0 0.467976 -0.038649 -0.295344 -1.824726 L
1 -0.358893 1.404453 0.704965 -0.200638 B
2 -0.501840 0.659254 -0.421691 -0.057688 G
3 0.204886 1.074134 1.388361 -0.982404 R
4 0.354628 -0.133116 0.283763 -0.837063 Q
# 如果需要逐块读取文件,可以指定chunksize(行数)
chunker = pd.read_csv('examples/ex6.csv', chunksize=1000)
chunker

import warnings
warnings.filterwarnings('ignore')

迭代处理ex6.csv,将值计数聚合到“key”列中,操作如下;

chunker = pd.read_csv('examples/ex6.csv', chunksize=1000)

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
Q    340.0
M    338.0
J    337.0
F    335.0
K    334.0
H    330.0
dtype: float64

textParser还有一个get_chunk方法,它可以读取任意大小的块。

Writing Data to Text Format 将数据写出到文本格式

data = pd.read_csv('examples/ex5.csv')
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方法,可以将数据写入到一个以逗号分隔的文件中

data.to_csv('examples/out.csv')
# !cat examples/out.csv
import sys
# 也可以使用其他的分隔符,这里直接写入到sys.stdout,所以仅仅是打印出文本结果而已
data.to_csv(sys.stdout, sep='|')
|something|a|b|c|d|message
0|one|1|2|3.0|4|
1|two|5|6||8|world
2|three|9|10|11.0|12|foo
# 缺失值在输出结果中被表示为空字符串。这里我希望将其表示为别的标记值:
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', 'b', 'c'])
a,b,c
1,2,3.0
5,6,
9,10,11.0

Series也有一个to_csv方法

dates = pd.date_range('1/1/2000', periods=7)
ts = pd.Series(np.arange(7), index=dates)
ts.to_csv('examples/tseries.csv')
# !cat examples/tseries.csv
datesfile = pd.read_csv('examples/tseries.csv')
datesfile
Unnamed: 0 0
0 2000-01-01 0
1 2000-01-02 1
2 2000-01-03 2
3 2000-01-04 3
4 2000-01-05 4
5 2000-01-06 5
6 2000-01-07 6

Working with Delimited Formats 处理分隔符格式

大部分存储在磁盘上的表格型数据都可以使用pandas.read_table进行加载,但有时需要做一些手工处理。实际上,因为接收到含有畸形行的文件而使得read_table出毛病的情况很常见。

# 将任意打开的文件或者文件型的对象传给csv.reader:对这个reader进行迭代将会产生一个元组(
# 同时:移除了所有的引号)

import csv
f = open('examples/ex7.csv')

reader = csv.reader(f)
for line in reader:
    print(line)

f.close()

为了使得数据格式合乎要求,进行处理。

首先,读取文件到一个多行的列表中;

with open('examples/ex7.csv') as f:
    lines = list(csv.reader(f))
# 将这些行分开为;标题行和数据行
header, values = lines[0], lines[1:]
# 关于zip 函数的使用
a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]
zipped = zip(a,b)     # 打包为元组的列表
print(zipped)

print(zip(a,c) )             # 元素个数与最短的列表一致

print((*zipped)  )

# 然后,使用字典构造式和zip(*values),后者将行转置为列,创建数据列的字典:

"""
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
"""
data_dict = {h: v for h, v in zip(header, zip(*values))}
data_dict
{'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}

class my_dialect(csv.Dialect):
lineterminator = ‘\n’
delimiter = ‘;’
quotechar = ‘"’
quoting = csv.QUOTE_MINIMAL

reader = csv.reader(f, dialect=my_dialect)

reader = csv.reader(f, delimiter=’|’)

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’))

JSON Data JSON数据

JSON已经成为:通过http请求在web浏览器和其他的应用程序之间发送数据的标准格式之一。他比表格型的数据更加灵活。

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"]}]
}
"""
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)

将(一个或者一组)JSON对象转换为DataFrame或者其他便于分析的数据结构?

最简单的方式就是:往DataFrame构造器传入一个字典的列表(就是原先的JSON对象),并选取数据字段的子集.

siblings = pd.DataFrame(result['siblings'], columns=['name', 'age'])
siblings
name age
0 Scott 30
1 Katie 38
# pandas.read_json可以自动将特别格式的json数据集转换为Series或者DataFrame.

# pandas.read_json的默认选项假设json数组中的每个对象是表格中的一行
data = pd.read_json('examples/example.json')
data
a b c
0 1 2 3
1 4 5 6
2 7 8 9
# 如果需要将数据从pandas输出到json,可以使用to_json方法;
print(data.to_json())
print(data.to_json(orient='records'))
{"a":{"0":1,"1":4,"2":7},"b":{"0":2,"1":5,"2":8},"c":{"0":3,"1":6,"2":9}}
[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]

XML and HTML: Web Scraping Web信息收集

python有许多的可以读写常见的html和xml格式数据的库,包括:lxml,beautiful soup和 html5lib.

lxml的速度比较快,但是,,,,其他的库处理有误的html或者xml文件更好。

pandas有一个内置的功能,read_html,它可以使用lxml和beautiful soup 自动将html文件中的表格解析为DataFrame对象。

  • conda install lxml # 或者 pip install lxml
  • pip install beautifulsoup4 html5lib
# 这里的html文件记录了银行倒闭的情况
tables = pd.read_html('examples/fdic_failed_bank_list.html')
len(tables)
1
failures = tables[0]
failures.head()
Bank Name City ST CERT Acquiring Institution Closing Date Updated Date
0 Allied Bank Mulberry AR 91 Today's Bank September 23, 2016 November 17, 2016
1 The Woodbury Banking Company Woodbury GA 11297 United Bank August 19, 2016 November 17, 2016
2 First CornerStone Bank King of Prussia PA 35312 First-Citizens Bank & Trust Company May 6, 2016 September 6, 2016
3 Trust Company Bank Memphis TN 9956 The Bank of Fayette County April 29, 2016 September 6, 2016
4 North Milwaukee State Bank Milwaukee WI 20364 First-Citizens Bank & Trust Company March 11, 2016 June 16, 2016

因为failures有许多列,pandas插入了一个换行符\

# 计算按照年份倒闭的银行数量
close_timestamps = pd.to_datetime(failures['Closing Date'])
close_timestamps.dt.year.value_counts()
2010    157
2009    140
2011     92
2012     51
2008     25
       ... 
2004      4
2001      4
2007      3
2003      3
2000      2
Name: Closing Date, Length: 15, dtype: int64
Parsing XML with lxml.objectify 利用lxml.objectify解析xml
"""

  373889
  
  Metro-North Railroad
  Escalator Availability
  Percent of the time that escalators are operational
  systemwide. The availability rate is based on physical observations performed
  the morning of regular business days only. This is a new indicator the agency
  began reporting in 2009.
  2011
  12
  Service Indicators
  M
  U
  %
  1
  97.00
  
  97.00
  

"""
%pwd
'D:\\python code\\8messy\\4利用python进行数据分析\\pydata-book-2nd-edition'
# 先使用lxml.objectify解析该文件,然后通过getroot得到该xml文件的根节点的引用:
from lxml import objectify

path = 'datasets/mta_perf/Performance_MNR.xml'
parsed = objectify.parse(open(path))
root = parsed.getroot()

root.INDICATOR返回一个用于产生xml元素的生成器。对于每条记录,使用标记名和数据值填充一个字典。

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)
perf.head()
AGENCY_NAME INDICATOR_NAME DESCRIPTION PERIOD_YEAR PERIOD_MONTH CATEGORY FREQUENCY INDICATOR_UNIT YTD_TARGET YTD_ACTUAL MONTHLY_TARGET MONTHLY_ACTUAL
0 Metro-North Railroad On-Time Performance (West of Hudson) Percent of commuter trains that arrive at thei... 2008 1 Service Indicators M % 95 96.9 95 96.9
1 Metro-North Railroad On-Time Performance (West of Hudson) Percent of commuter trains that arrive at thei... 2008 2 Service Indicators M % 95 96 95 95
2 Metro-North Railroad On-Time Performance (West of Hudson) Percent of commuter trains that arrive at thei... 2008 3 Service Indicators M % 95 96.3 95 96.9
3 Metro-North Railroad On-Time Performance (West of Hudson) Percent of commuter trains that arrive at thei... 2008 4 Service Indicators M % 95 96.8 95 98.3
4 Metro-North Railroad On-Time Performance (West of Hudson) Percent of commuter trains that arrive at thei... 2008 5 Service Indicators M % 95 96.6 95 95.8
from io import StringIO
tag = 'Google'
root = objectify.parse(StringIO(tag)).getroot()
root
root.get('href')
root.text
'Google'

Binary Data Formats 二进制数据格式

实现数据的高效二进制格式存储的最有效的办法之一是使用python内置的pickle序列化。

pandas对象都有一个用于将数据以pickle格式保存到磁盘上的to_pickle方法:

frame = pd.read_csv('examples/ex1.csv')
frame
frame.to_pickle('examples/frame_pickle')
# 可以通过pickle 直接读取被pickle化的数据,或者是使用更为方便的pandas.read_pickle
pd.read_pickle('examples/frame_pickle')
a b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo

注意;pickle仅仅建议用于短期的存储格式。原因是很难保证该格式永远是稳定的;现在的pickle对象可能无法被后续版本的库unpickle出来。

Using HDF5 Format 使用hdf5格式

HDF5和MessagePack,,pandas内置支持的两个二进制数据格式。

frame = pd.DataFrame({'a': np.random.randn(100)})
store = pd.HDFStore('mydata.h5')
store['obj1'] = frame
store['obj1_col'] = frame['a']
store

File path: mydata.h5
# HDF5文件中的对象可以通过与字典一样的api进行获取
store['obj1']
a
0 -0.204708
1 0.478943
2 -0.519439
3 -0.555730
4 1.965781
... ...
95 0.795253
96 0.118110
97 -0.748532
98 0.584970
99 0.152677

100 rows × 1 columns

# HDFStore支持两种存储模式,fixed和table,后者会更慢,但是

# 支持使用特殊语法进行查询操作

store.put('obj2', frame, format='table')
store.select('obj2', where=['index >= 10 and index <= 15'])
store.close()
frame.to_hdf('mydata.h5', 'obj3', format='table')
pd.read_hdf('mydata.h5', 'obj3', where=['index < 5'])
a
0 -0.204708
1 0.478943
2 -0.519439
3 -0.555730
4 1.965781
import os
os.remove('mydata.h5')

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

Reading Microsoft Excel Files 读取Microsoft excel文件

xlsx = pd.ExcelFile('examples/ex1.xlsx')
pd.read_excel(xlsx, 'Sheet1')
Unnamed: 0 a b c d message
0 0 1 2 3 4 hello
1 1 5 6 7 8 world
2 2 9 10 11 12 foo
frame = pd.read_excel('examples/ex1.xlsx', 'Sheet1')
frame
Unnamed: 0 a b c d message
0 0 1 2 3 4 hello
1 1 5 6 7 8 world
2 2 9 10 11 12 foo
"""
如果要将pandas数据写入为excel格式,必须像创建一个excelWriter,然后使用pandas对象的to_excel

方法将数据写入其中;
"""
writer = pd.ExcelWriter('examples/ex2.xlsx')
frame.to_excel(writer, 'Sheet1')
writer.save()
# 也可以不用ExcelWriter,而是传递文件的路径到to_excel;
frame.to_excel('examples/ex2.xlsx')

Interacting with Web APIs Web APIs交互

import requests
url = 'https://api.github.com/repos/pandas-dev/pandas/issues'
resp = requests.get(url)
resp

data = resp.json()
data[0]['title']
'BUG: resample().nearest() throws an exception if tz is provided for the DatetimeIndex'
issues = pd.DataFrame(data, columns=['number', 'title',
                                     'labels', 'state'])
issues
number title labels state
0 33895 BUG: resample().nearest() throws an exception ... [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=... open
1 33894 ENH: Construct pandas dataframe from function [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=... open
2 33892 COMPAT: add back block manager constructors to... [{'id': 76865106, 'node_id': 'MDU6TGFiZWw3Njg2... open
3 33891 pandas interpolate inconsistent results with a... [] open
4 33890 CI: failing timedelta64 test on Linux py37_loc... [{'id': 48070600, 'node_id': 'MDU6TGFiZWw0ODA3... open
... ... ... ... ...
25 33851 DOC: Single Document For Code Guidelines [{'id': 134699, 'node_id': 'MDU6TGFiZWwxMzQ2OT... open
26 33849 BUG: weird behaviour of pivot_table when aggf... [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=... open
27 33846 BUG: Series construction with EA dtype and ind... [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=... open
28 33845 TestDatetimeIndex.test_reindex_with_same_tz 32... [{'id': 563047854, 'node_id': 'MDU6TGFiZWw1NjM... open
29 33843 Roll quantile support multiple quantiles as pe... [] open

30 rows × 4 columns

Interacting with Databases 数据库交互

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

Conclusion

你可能感兴趣的:(python,csv,json,数据分析,pandas)