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

本博客为《利用Python进行数据分析》的读书笔记,请勿转载用于其他商业用途。

1. 文本格式数据的读写

输入和输出通常有以下几种类型:

  • 读取文本文件及硬盘上其他更高效的格式文件
  • 从数据库载入数据
  • 与网络资源进行交互(比如Web API)

将表格类型数据读取为DataFrame对象是pandas的重要特性。下表总结了部分实现该功能的函数,read_csvread_table可能是后期我们使用最多的函数。

表:Pandas的解析函数

函数 描述
read_csv 从文件、URL或文件型对象读取分隔好的数据,逗号是默认分隔符
read_table 从文件、URL或文件型对象读取分隔好的数据,制表符(‘t/’)是默认分隔符
read_fwf 从特定宽度格式的文件中读取数据(无分隔符)
read_clipboard read_table的剪贴版本,在将表格从Web页面上转换成数据时有用
read_excel 从Excel的XLS或XLSX文件中读取表格数据
read_hdf 读取用pandas存储的HDF5文件
read_html 从HTML文件中读取所有表格数据
read_json 从JSON(JavaScript Object No tation)字符串中读取数据
read_msgpack 读取MessagePack二进制格式的pandas数据
read_pickle 读取以Python pickle格式存储的任意对象
read_sas 读取存储在SAS系统中定制存储格式的SAS数据集
read_sql 将SQL查询的结果(使用SQLAlchemy)读取为pandas的DataFrame
read_stata 读取Stata格式的数据集
read_feather 读取Feather二进制格式

这些函数的可选参数主要有以下几种类型:

  • 索引
    可以将一或多个列作为返回的DataFrame,从文件或用户处获得列名,或者没有列名。
  • 类型推断和数据转换
    包括用户自定义的值转换和自定义的缺失值符号列表
  • 日期时间解析
    包括组合功能,也包括将分散在多个列上的日期和时间信息组合成结果中的单个列。
  • 迭代
    支持对大型文件的分块迭代。
  • 未清洗数据问题
    跳过行、页脚、注释以及其他次要数据,比如使用逗号分隔千位的数字。

由于现实世界中的数据非常混乱,随着时间推移,一些数据加载函数(尤其是read_csv)的可选参数变得非常复杂。pandas的在线文档有大量示例展示这些参数是如何工作的。如果你在读取某个文件时遇到了困难,在文档中可能会有相似的示例帮助你如何找到正确的参数。
一些数据载入函数,比如pandas.read_csv,会进行类型推断,因为列的数据类型并不是数据格式的一部分。那就意味着我们不必指定哪一列时数值、整数、布尔值或字符串。其他的数据格式,比如HDF5、Feather和msgpack在格式中已经存储了数据类型。
处理日期和其他自定义类型可能需要额外的努力。我们从一个小型的逗号分隔符文本文件(csv)开始:
csv文件的内容大概这个样子
由于这个文件时逗号分隔的,我们可以使用read_csv将它读入一个DataFrame:

df = pd.read_csv('C:/ex1.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('C:/ex1.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

有些文件并不包含表头,比如:
在这里插入图片描述
要读取该文件,我们需要选择一些选项。你可以允许pandas自动分配默认列名,也可以自己指定列名:

df = pd.read_csv('C:/ex2.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('C:/ex2.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的索引,可以指定位置4的列为索引,或将’message’传给参数index_col

names = ['a', 'b', 'c', 'd', 'message']
df = pd.read_csv('C:/ex2.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

如果我们想要从多个列中形成一个分层索引,需要传入一个包含序列号或列名的列表:
在这里插入图片描述

parsed = pd.read_csv('C:/csv_mindex.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

在某些情况下,一张表的分隔符并不是固定的,使用空白或其他方式来分隔字段,考虑如下文本文件:
在这里插入图片描述

data = list(open('C:/ex3.txt'))
print(data)
#
['\tA\tB\tC\n', 
'aaa\t1\t2\t3\n', 
'bbb\t4\t5\t6\n', 
'ccc\t7\t8\t9\n', 
'ddd\t10\t11\t12\n']
result = pd.read_table('C:/ex3.txt', sep='\s+')
print(result)
#
      A   B   C
aaa   1   2   3
bbb   4   5   6
ccc   7   8   9
ddd  10  11  12

本例中,由于列名的数量比数据的列少一个,因此read_table推断第一列应当作为DataFrame的索引。
解析函数有很多附加参数帮助你处理各种发生异常的文件格式。例如,你可以使用skiprows来跳过第1、3、4行:
在这里插入图片描述

df = pd.read_csv('C:/ex4.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:
在这里插入图片描述

result = pd.read_csv('C:/ex5.csv')
print(result)
#
  something  a   b   c   d message
0       one  1   2   3   4     NaN
1       two  5   6   7   8   world
2     three  9  10  11  12     foo
print(pd.isnull(result))
#
   something      a      b      c      d  message
0      False  False  False  False  False     True
1      False  False  False  False  False    False
2      False  False  False  False  False    False

na_values选项可以传入一个列表或一组字符串来处理缺失值:

result = pd.read_csv('C:/ex5.csv', na_values=['NULL'])
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

在字典中,每列可以指定不同的缺失值标识:

sentinels = {'message': ['foo', 'NA'], 'something': ['two']}
data = pd.read_csv('C:/ex5.csv', na_values=sentinels)
print(data)
#
  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_csvpandas.read_table中常用的选项。

表:一些read_csv / read_table函数参数

参数 描述
path 表明文件系统位置的字符串,URL或文件类型
sep或delimiter 用于分隔每行字段的字符序列或正则表达式
header 用作列名的行号,默认是0(第一行),如果没有列名的话,应该为None
index_col 用作结果中行索引的列号或列名,可以是一个单一的名称/数字,也可以是一个分层索引
names 结果的列名列表,和header=None一起使用
skiprows 从文件开头处起,需要跳过的行数或行号列表
na_values 需要用NA替换的序列值
comment 在行结尾处分隔注释的字符
parse_dates 尝试将数据解析为datetime,默认是False。如果为True,将尝试解析所有的列。也可以指定列号或列名列表来进行解析。如果列表的元素是元组或列表,将会把多个列组合在一起进行解析(如日期/时间将拆分为两列)
keep_date_col 如果连接列到解析日期上,保留被连接的列,默认是False
converters 包含列名称映射到函数的字典(例如{‘foo’: f}会把函数f应用到‘foo’列)
dayfirst 解析非明确日期时,按照国际格式处理(例如7/6/2012 ->June 7, 2012),默认为False
date_parser 用于解析日期的函数
nrows 从文件开头处读入的行数
iterator 返回一个TextParser对象,用于零散地读入文件
chunksize 用于迭代的块大小
skip_footer 忽略文件尾部的行数
verbose 打印各种解析器输出的信息,比如位于非数值列中的缺失值数量
encoding Unicode文本编码(例如‘utf-8’用于表示UTF-8编码的文本)
squeeze 如果解析数据只包含一列,返回一个Series
thousands 千位分隔符(例如‘,’或‘.’)

1.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方法,允许你按照任意大小读取数据块。

1.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

1.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_NONNUMERICcsv.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'))

1.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())

1.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

2. 二进制格式

使用Python内建的pickle序列化模块进行二进制格式操作时存储数据(也称为序列化)最高效、最方便的方式之一。pandas对象拥有一个to_pickle方法可以将数据以pickle格式写入硬盘:

frame = pd.read_csv('ex1.csv')
print(frame)

#
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo
frame.to_pickle('frame_picke')

我们直接使用内建的pickle读取文件中“pickle”化的对象,或更方便地使用pandas.read_pickle做上述操作:

data = pd.read_pickle('frame_pickle')
print(data)

#
   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很难确保格式的长期有效性;一个今天被pickle化的对象可能明天因为库的新版本而无法反序列化。

pandas内建支持其他两个二进制格式:HDF5和MessagePack。

2.1 使用HDF5格式

HDF5是一个备受好评的文件格式,用于存储大量的科学数组数据。它以C库的形式提供,并且具有许多其他语言的接口,包括Java、Julia、MATLAB和Python。HDF5中的“HDF”代表分层数据格式。每个HDF5文件可以存储多个数据集并且支持元数据。与更简单格式相比,HDF5支持多种压缩模式的即时压缩,是的重复模式的数据可以更高第存储。HDF5适用于处理不适合在内存中存储的超大型数据,可以使你高效读写大型数组的一小块。
尽快可以通过使用Pytables或h5py等库直接访问HDF5文件,但pandas提供了一个高阶的接口,可以简化Series和DataFrame的存储。HDFStore类像字典一样工作并处理低级别细节:

frame = pd.DataFrame({'a': np.random.randn(100)})
store = pd.HDFStore('mydata.h5')
store['obj1'] = frame
store['obj1_col'] = frame['a']
store
#
<class 'pandas.io.pytables.HDFStore'>
File path: mydata.h5

结果跟书上还是有一些差距。
包含在HD5文件中的对象可以使用相同的字典型API进行检索:

store['obj1']
#
	       a
0	0.779202
1	-1.077735
2	0.028898
3	-0.050125
4	0.477923
5	-2.152421
6	0.639740
7	-0.786466
8	-1.091780
9	0.606801
10	-0.489952
11	1.124520
12	-0.700125
13	0.702218
14	-1.729623
15	0.391208
16	-1.409342
17	0.565409
18	-0.985509
19	2.000896
20	1.498629
21	2.446517
22	0.889966
23	-1.171885
24	1.115902
25	-0.400008
26	-1.439171
27	-0.457836
28	1.790552
29	0.615969
...	...
70	-0.004149
71	0.730181
72	0.615633
73	-1.425845
74	0.116927
75	0.853079
76	0.462751
77	0.952087
78	-0.853721
79	0.144893
80	-0.485946
81	0.035803
82	1.812239
83	1.682183
84	-1.364205
85	1.349751
86	0.057801
87	0.310320
88	-0.091248
89	-0.197712
90	-1.018919
91	-1.330481
92	-1.133903
93	-0.773132
94	-0.320451
95	-1.131031
96	-0.373055
97	-0.844670
98	-1.377580
99	0.263320
100 rows × 1 columns

HDFStore支持两种存储格式,'fixed''table'。后者速度更慢,但支持一种特殊语法的查询操作:

store.put('obj2', frame, format='table')
store.select('obj2', where=['index >= 10 and index <= 15'])
store.close()
#
            a
10	-0.489952
11	1.124520
12	-0.700125
13	0.702218
14	-1.729623
15	0.391208

putstore['obj2']=frame方法的显示版本,但允许我们设置其他选项,如存储格式。
pandas.read_hdf函数是这些工具的快捷方法:

frame.to_hdf('mydata.h5', 'obj3', format='table')
print(pd.read_hdf('mydata.h5', 'obj3', where=['index < 5']))
#
           a
0	0.779202
1	-1.077735
2	0.028898
3	-0.050125
4	0.477923
5	-2.152421

如果你处理存储在远程服务器上的数据时,比如Amazon S3或HDFS,使用其他专门为分布式存储而设计的二进制格式更为合适,比如Apache Parquet。Parquet和其他类似的存储格式仍然在发展中。
如果你是在本地处理大量数据,推荐尝试PyTables和h5py,看看他们是否符合需求。由于很多数据分析的困难在于I/O密集(而非CPU密集),使用像HDF5这样的工具可以大大加速你的应用。
HDF5并不是数据库,它是一种适合一次写入多次读取的数据集。尽管数据可以在任何时间添加到文件中,但如果多个写入者持续写入,文件可能会损坏。

2.2 读取Microsoft Excel文件

pandas也支持通过ExcelFile类或pandas.read_excel函数来读取存储在Excel 2003(或更高版本)文件中的表格类型数据。这些工具内部是使用附加包xlrdopenpyxl来分别读取XLS和XLSX文件的。你可能需要使用pip或conda手动安装这些工具。
使用ExcelFile时,通过将xls或xlsx的路径传入,生成一个实例:

xlsx = pd.ExcelFile('ex1.xlsx')
data = pd.read_excel(xlsx, 'Sheet1')
print(data)

#
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

如果你读取的是含有多个表的文件,生成ExcelFile更快,但你也可以更简洁地将文件名传入pandas.read_excel

frame = pd.read_excel('ex1.xlsx', 'Sheet1')
print(frame)

#
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

如需将pandas数据写入到Excel格式中,必须先生成一个ExcelWriter,然后使用pandas对象的to_excel方法将数据写入:
在这里插入图片描述

writer = pd.ExcelWriter('ex2.xlsx', 'Sheet1')
frame.to_excel(writer, 'Sheet1')
writer.save()

我们也可以将文件路径传给to_excel,避免直接调用ExcelWriter

frame.to_excel('ex2.xlsx')

3. 与Web API交互

很多网站都有公开API,通过JSON或其他格式提供数据服务。有多种方式可以利用Python来访问API。我推荐的简单易用方式是使用requests包。要获取GitHub上最新的30条关于pandas的问题,我们可以使用附加库requests发送一个HTTP GET请求:

import requests

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

#
<Response [200]>

Response(响应)对象json方法将返回一个包含解析为本地Python对象的JSON的字典。

data = resp.json()
print(data[0]['title'])

#
TST: expand tests for ExtensionArray setitem with nullable arrays

data中的每个元素都是一个包含GitHub问题页面上所有数据的字典(注释除外)。我们可以将data直接传给DataFrame,并提取感兴趣的字段:

issues = pd.DataFrame(data, columns=['numbers', 'title', 'labels', 'state'])
print(issues)

结果如下图:
在这里插入图片描述
通过一些复杂操作,我们可以创建一些更高阶的接口来访问常用的Web API,以返回DataFrame对象以便于分析。

4. 与数据库交互

发布了27 篇原创文章 · 获赞 9 · 访问量 982

猜你喜欢

转载自blog.csdn.net/sinat_42574069/article/details/104137812