python:pandas(7),读写文本格式数据

来源:互联网 发布:淘宝买了汽枪配件警察 编辑:程序博客网 时间:2024/06/05 20:31

利用python进行数据分析

第六章:数据加载、存储与文本格式

NumPy提供了一个低级但异常高效的二进制数据加载和存储机制,而对于pandas的输入与输出划分为几个大类:
读取文本文件和其他更高效的磁盘存储格式,
加载数据库中的数据,
利用Web API操作网络资源。

1,读写文本格式的数据

表6-1:pandas中的解析函数
| 函数 | 说明 |
| read_csv | 从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为逗号 |
| read_table | 从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为制表符(“\t”) |
| read_fwf | 读取定宽列格式数据(也就是说,没有制表符) |
| read_clipboard | 读取剪贴板中的数据,可以看做read _table的剪贴板版,在将网页转换为表格示很有用 |

这些函数在将分本数据转换为DataFrame时,这些函数的选项可以划分为以下几个大类:

  • 索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获取列名。
  • 类型推断和数据转换:包括用户定义值的转换、缺失值标记列表等。
  • 日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合成结果汇总的单个列。
  • 迭代:支持对大文件进行逐块迭代。
  • 不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西(比如由成千上万个逗号隔开的数值数据)。

1,类型推断(type inference)
指你不用需要指定列的类型到底是数值、整数、布尔值,还是字符串。但日期和其他自定义类型的处理需要进行另外的处理。
以逗号为分割的(CSV)文本文件:
>>> import pandas as pd
>>> import os
>>> cat ex1.csv
a,b,c,d,message
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
>>> df=pd.read_csv('C:\Users\Administrator\Desktop\\ex1.csv') #该文件字符以逗号分隔所以可以用read_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
>>> df=pd.read_table('C:\Users\Administrator\Desktop\\ex1.csv', sep=',') #如果用read_table(默认以‘\t’分隔)读取文件,需要指定分隔符类型sep=’,’
read_table和read_csv默认将文件的第一行作为输出数据的行标题,但是如果文件本身不存在行标题则需要加入另外参数。
>>> cat ex2.csv
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
文件读取后可以让pandas为其分配默认的列名,也可以自定义列名。
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex2.txt', header=None) #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
自动分配了默认的列名(0, 1, 2, 3, 4)
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex2.txt', names=['a', 'b', 'c', 'd', 'message']) #names=[] 表示自定义列名,将列名依次写入一个列表中
···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的索引。你可以明确表示要将该列放到索引4的位置上,可通过index_col参数指定“message”:
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex2.txt', names=['a', 'b', 'c', 'd', 'message'], index_col='message') #index_col=’message’ 将message这一列设定为索引,而‘message’作为index的name
···a b c d
message
hello 1 2 3 4
world 5 6 7 8
foo 9 10 11 12
如果希望将多个列做成一个层次化索引,只需传入由列编号列名组成的列表即可: 重点用法
>>> cat ex3.txt
a,b,c,d,message,keys
1,2,3,4,hello,key
5,6,7,8,world,key
9,10,11,12,foo,key
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex3.txt', index_col=['keys', 'message'])
·····a b c d
keys·message
key·hello 1 2 3 4
···world 5 6 7 8
···foo 9 10 11 12
index_col=[‘keys’, ‘message’]列表当中的第一个元素作为第一层索引,第二个元素作为第二层索引,依此类推。
也可以加上names等多个参数
>>> cat ex4.txt
1,2,3,4,hello,key
5,6,7,8,world,key
9,10,11,12,foo,key
>>> names=['a', 'b', 'c', 'd', 'message', 'keys']
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex4.txt', names=names, index_col=['keys', 'message'])
·····a b c d
keys·message
key·hello 1 2 3 4
···world 5 6 7 8
···foo 9 10 11 12
上述建立多层索引的例子中,read_csv()当中的names包括message和keys而index _col包括的名称要与names当中的message和keys字符相同
如果有些表格不是用固定的分隔符去分隔字段(比如空白符或其他)。处理这种文件,可以编写一个正则表达式作为read_table的分隔符。
>>> cat ex5.txt
A B C D
aaa 1 2 3 4
bbb 5 6 7 8
ccc 9 10 11 12
ddd 13 14 15 16
这个文本格式中,aaa与1,2,3,4分隔开两个空格,1,2,3,4之间各分隔开一个空格,而A,B,C,D各自与1,2,3,4对齐,对于这种空格处理,可以正则表达式\s+表示。
>>> pd.read_table('C:\Users\Administrator\Desktop\\ex5.txt', sep='\s+')
A B C D
aaa 1 2 3 4
bbb 5 6 7 8
ccc 9 10 11 12
ddd 13 14 15 16
read_table()以sep=’\s+’ 参数设定的字符或表达式作为分隔符
由于列名比数据行的数量少,
准确的说法是:列名的数量比列的数量少1,完整的说法是:列名“行”中“有内容的”字段数量比其他数据“行”中“有内容的”字段数量少1。
所以read_table推断第一列应该是DataFrame的索引,(如果相等则以0,1,2,3……作为索引)
skiprows参数表示跳过文件的指定的行,而得到数据内容
>>> cat ex6.txt
# hey!
a,b,c,d,message
# diffrent for you!
# who reads CSV files
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex6.txt', 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、-1、#IND、以及NULL等。
>>> cat ex7.txt
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('C:\Users\Administrator\Desktop\\ex7.txt')
>>> 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字符串,自动转换成了NaN(缺失值)
>>> 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('C:\Users\Administrator\Desktop\\ex7.txt', 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('C:\Users\Administrator\Desktop\\ex7.txt', 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
字典提供了缺失值对应的关系,键表示对应的DataFrame的列名,值表示要将该列的哪些值填充为缺失值,’message’: [‘foo’, ‘NA’],表示将message这一列当中的‘foo’和NA值填充为缺失值(NaN)。

表6-2:read_csv/read _rable函数的参数
| 参数 | 说明 |
| path | 表示文件系统位置、URL、文件型对象的字符串 |
| sep或delimter | 用于对行中各字段进行拆分的字符序列或正则表达式 |
| header | 用作列名的行号。默认为0(第一行),如果没有header行就应该设置为None |
| index_col | 用作行索引的列编号或列名。可以是单个名称/数字或由多个名称/数字组成的列表(层次化索引) |
| names | 用于结果的列名列表,结合header=None |
| skiprows | 需要忽略的行数(从文件开始处算起),或需要跳过的行号列表(从0开始) |
| na_values | 一组用于替换NA的值(可以用na_rep代替) |
| comment | 用于将注释信息从行尾拆分出去的字符(一个或多个) |
| parse_dates | 尝试将数据解析为日期,默认为False。如果为True,则尝试解析所有列。此外, 还可以指定需要解析的一组列号或列名。如果列表的元素为列表或元组,就会将多个列组合到一起再进行日期解析工作(例如,日期/时间分别位于两个列中) |
| keep_date_col | 如果连接多列解析日期,则保持参与连接的列。默认非False。 |
| converters | 由列号/列名跟函数之间的映射关系组成的字典。例如,{‘foo’: f}会对foo列的所有值应用函数f |
| dayfirst | 当解析有歧义的日期时,将其看做国际格式(例如,7/6/2012 -> June 7, 2012)。默认为False |
| date_parser | 用于解析日期的函数 |
| nrows | 需要读取的行数(从文件开始处算起) |
| iterator | 返回一个TextParser以便逐块读取文件 |
| chunksize | 文件块的大小(用于迭代) |
| skipfooter | 需要忽略的行数(从文件末尾处算起) |
| verbose | 打印各种解析器输出信息,比如“非数值列中缺失值的数量”等 |
| encoding | 用于unicode的文件编码格式。例如,“utf-8”表示用UTF-8编码的文本 |
| squeeze | 如果数据经解析后仅含一列,则返回Series |
| thousands | 千分位分隔符,如“,”或“.” |

2,逐块读取文本文件

如果只想读取文件的部分内容可在read_csv函数内加入,nrows(从文件开始读取的行数)、shipfooter(从文件末尾忽略的行数)或skiprows(从文件开头忽略的行数,或需要跳过的行号,从0开始)。
>>> cat ex8.txt
1,2,3,4,hello,key
5,6,7,8,world,key
9,10,11,12,foo,key
13,14,15,16,kep,key
17,18,19,20,ssh,key
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex8.txt', nrows=3)
1 2 3 4 hello key
0 5 6 7 8 world key
1 9 10 11 12 foo key
2 13 14 15 16 kep key
如果将第一行标记为列索引,nrows=3,表示读取除列索引以外的前3行内容。
>>> pd.read_csv('C:\Users\Administrator\Desktop\\ex8.txt', skipfooter=3)
1 2 3 4 hello key
0 5 6 7 8 world key
skipfooter=3表示过滤掉除列索引以外的后3行内容,其余文件内容进行读取。

3,将数据写到文本格式

利用DataFrame的to_csv方法,可将数据写到一个以逗号分隔的文件中。
>>> data=pd.read_csv('C:\Users\Administrator\Desktop\\ex8.txt', header=None, names=['a', 'b', 'c', 'd', 'e', 'f'])
>>> data
a b c d e f
0 1 2 3 4 hello key
1 5 6 7 8 world key
2 9 10 11 12 foo key
3 13 14 15 16 kep key
4 17 18 19 20 ssh key
>>> data.to_csv('C:\Users\Administrator\Desktop\\ex9.txt', sep='\t')
输出文件分隔符默认为“,”,这里通过sep=’\t’将分隔符设定为制表符
缺失值在输出结果中会被表示为空字符串。但在输出后可以表示为别的标记值:
>>> cat ex10.csv
0.1,,0.3,0.4,L
1.1,1.2,1.3,NA,B
2.9,2.8,2.7,2.6,
5.6,5.7,5.8,5.0,V
>>> data=pd.read_csv('ex10.csv')
>>> data
one two three four key
0 0.1 NaN 0.3 0.4 L
1 1.1 1.2 1.3 NaN B
2 2.9 2.8 2.7 2.6 NaN
3 5.6 5.7 5.8 5.0 V
>>> data.to_csv('ex11.csv')
>>> data.to_csv('ex12.csv', na_rep='NULL')
>>> cat ex11.csv
,one,two,three,four,key
0,0.1,,0.3,0.4,L
1,1.1,1.2,1.3,,B
2,2.9,2.8,2.7,2.6,
3,5.6,5.7,5.8,5.0,V
>>> cat ex12.csv
,one,two,three,four,key
0,0.1,NULL,0.3,0.4,L
1,1.1,1.2,1.3,NULL,B
2,2.9,2.8,2.7,2.6,NULL
3,5.6,5.7,5.8,5.0,V
默认情况下会将行列标签写入文件中,也可用两个参数对输出行列标签进行禁用
>>> data.to_csv('ex13.csv', index=False, header=False)
>>> cat ex13.csv
0.1,,0.3,0.4,L
1.1,1.2,1.3,,B
2.9,2.8,2.7,2.6,
5.6,5.7,5.8,5.0,V
Series也存在一个to_csv方法:
>>> dates=pd.date_range('1/1/2000', periods=7)
>>> dates
DatetimeIndex([‘2000-01-01’, ‘2000-01-02’, ‘2000-01-03’, ‘2000-01-04’,
‘2000-01-05’, ‘2000-01-06’, ‘2000-01-07’],
dtype=’datetime64[ns]’, freq=’D’)
>>> ts=pd.Series(np.arange(7), index=dates)
>>> ts
>>> ts.to_csv('tseries.csv')
>>> cat tseries.csv
2000-01-01,0
2000-01-02,1
2000-01-03,2
2000-01-04,3
2000-01-05,4
2000-01-06,5
2000-01-07,6

4,手工处理分隔符格式

对于一般的表格型数据,大多用pandas.read_table进行加载,然而有些数据需要进行手工处理
>>> cat ex14.csv
“a”,”b”,”c”
“1”,”2”,”3”
“1”,”2”,”3”,”4”
>>> import csv
>>> f=open('ex14.csv')
>>> reader=csv.reader(f) #对于csv格式的文件需要利用csv.reader读取内容
将上述方法合并
>>> lines=list(csv.reader(open('ex14.csv')))
>>> lines
[['a', 'b', 'c'], ['1', '2', '3'], ['1', '2', '3', '4']]
>>> header, values = lines[0], lines[1:]
>>> data_dict={h: v for h, v in zip(header, zip(*values))}
>>> data_dict
{'a': ('1', '1'), 'c': ('3', '3'), 'b': ('2', '2')}

原创粉丝点击