数据载入、存储及文件格式

访问数据是使用各类工具所必需的第一步。我们将重点关注使用pandas进行数据输入和输出,尽管其他库中有许多工具可帮助读取和写入各种格式的数据。
输入和输出通常有以下几种类型:读取文本文件及硬盘上其他更高效的格式文件、从数据库载入数据、与网络资源进行交互(比如Web API)。

1.1文本格式数据的读写

将表格型数据读取为DataFrame对象是pandas的重要特性。
表1-1:Pandas的解析函数

函数 描述
read_csv 从文件、URL或文件型对象读取分隔好的数据,逗号是默认分隔符
read_table 从文件、URL或文件型对象读取分隔好的数据,制表符(‘\t’)是默认分隔符
read_excel 从Excel的XLS或XLSX文件中读取表格数据
read_html 从HTML文件中读取所有表格数据
read_json 从JSON字符串中读取数据
read_sas 读取存储在SAS系统中定制存储格式的SAS数据集
read_sql 将SQL查询的结果读取为pandas的DataFrame

一些数据载入函数,比如pandas.read_csv,会进行类型判断,因为列的数据类型并不是数据格式的一部分。那就意味着我们不必指定哪一列是数值、整数、布尔值或字符串。
让我们从一个小型的逗号分隔文本文件(CSV)开始:
examples.csv
a,b,c,d,message
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
由于这个文件是逗号分隔的,我们可以使用read_csv将它读入一个DataFrame:

import pandas as pd
df = pd.read_csv('examples.csv')
print(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,并指定分隔符:

df = pd.read_table('examples.csv',sep = ',')
print(df)
------------------------
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

有的文件不包含表投行。考虑以下文件:
examples1.csv
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
我们可以允许pandas自动分配默认列名,也可以自己指定列名:

df = pd.read_csv('examples1.csv',header = None)
print(df)
-----------------------
   0   1   2   3      4
0  1   2   3   4  hello
1  5   6   7   8  world
2  9  10  11  12    foo
df = pd.read_csv('examples1.csv',names = ['a','b','c','d','message'])
print(df)
------------------------
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

假设想要message列成为DataFrame的索引,我们可以这样操作:

names = ['a','b','c','d','message']
df = pd.read_csv('examples1.csv',names = names,index_col = 'message')
print(df)
----------------------
         a   b   c   d
message               
hello    1   2   3   4
world    5   6   7   8
foo      9  10  11  12

当你想要从多个列中形成一个分层索引,需要传入一个包含列序号或列名的列表:
examples2.csv
one,a,1,2
one,b,3,4
one,c,5,6
one,d,7,8
two,a,9,10
two,b,11,12
two,c,13,14
two,d,15,16

parsed = pd.read_csv('examples2.csv',index_col = ['key1','key2'])
print(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

在某些情况下,一张表的分隔符并不是固定的,使用空白或其他方法来分隔字段,在这些情况下也可以向read_table传入一个正则表达式作为分隔符。
解析函数有很多附加参数帮助我们来处理发生异常的文件格式,例如,我们可以使用skiprows来跳过第一行、第三行和第四行:
examples3.csv
嘿!
a,b,c,d,message
只是为了让你觉得更难
谁用计算机读取CSV文件?
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo

df = pd.read_csv('examples3.csv',skiprows = [0,2,3])
print(df)
------------------------
   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:
examples4.csv
something,a,b,c,d,message
one,1,2,3,4,NA
two,5,6,8,world
three,9,10,11,12,foo

result = pd.read_csv('examples4.csv')
print(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
print(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选项可以传入一个列表或一组字符串来处理缺失值:

sentinels = {'message':['foo'],'something':['two']}
print(pd.read_csv('examples4.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

表1-1:一些read_csv/read_table函数参数

参数 描述
path 表明文件系统位置的字符串、URL或文件型对象
sep或delimeter 用于分隔每行字段的字符串序列或正则表达式
header 用作列名的行号,默认是0(第一行),如果没有列名的话,应该是None
index_col 用作结果中行索引的列号或者列名,可以是单一的名称/数字,也可以是一个分层索引
names 结果的列名列表,和header=None一起用
skiprows 从文件开头处起,需要跳过的行数或行号列表
na_values 需要用NA替换的值序列
nrows 从文件开头处读入的行数
encoding Unicode文本编码
chunksize 用于迭代的块大小

1.1.1将数据写入文本格式

数据可以导出为分隔的形式。让我们看下之前读取的CSV文件:

result = pd.read_csv('examples4.csv')
print(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

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

result.to_csv('examples5.csv')

examples5.csv
,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
当然,其他的分隔符也是可以的(写入到sys.stdout时,控制台中打印的文本结果):

import sys
result.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
缺失值在输出时以空字符串出现。我们也可以用其他标识值对缺失值进行标注:

result.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
如果没有其他选项被指定的话,行和列标签都会被写入。不过二者也都可以禁止写入:

result.to_csv('sys.stdout',header = False,index = False)

one,1,2,3.0,4,
two,5,6,8,world
three,9,10,11.0,12,foo
我们也可以仅仅写入列的子集,并且按照我们所选择的顺序写入:

result.to_csv('sys.stdout',columns = ['a','b','c'],index = False)

a,b,c
1,2,3.0
5,6,
9,10,11.0

1.1.2使用分割形式

绝大多数的表型数据都可以使用函数pandas.read_table从硬盘中读取。然而,某些情况下,一些手动操作可能是必不可少的。接收一个带有一行或多行错误的文件并不少见,read_table也无法解决这种情况。为了介绍一些基础工具,考虑如下的小型CSV文件:
examples6.csv
“a”,“b”,“c”
“1”,“2”,“3”
“1”,“2”,“3”
对于任何带有单字符分隔符的文件,我们可以使用python的内建csv模块。要使用它,需要将任一打开的文件或文件型对象传给csv.reader:

import csv
f = open('examples6.csv')
reader = csv.reader(f)

像遍历文件那样遍历reader会产生元祖,元祖的值为删除了引号的字符:

for line in reader:
    print(line)
---------------
['a', 'b', 'c']
['1', '2', '3']
['1', '2', '3']

随后我们按部就班,首先将文件读取为行的列表:

with open('examples6.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))}
print(data_dict)
---------------------------------------------------
{'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}

猜你喜欢

转载自blog.csdn.net/weixin_43303087/article/details/84637159