目录
1. 文本格式数据的读写
1.1 分块读入文本文件
1.2 将数据写入文本格式
1.3 使用分隔格式
1.4 JSON数据
1.5 XML和HTML:网络抓取
1.5.1 使用lxml.objectify解析XML
2. 二进制格式
2.1 使用HDF5格式
2.2 读取Microsoft Excel文件
3. 与Web API交互
4. 与数据库交互
1. 文本格式数据的读写
表格型数据读取为DataFrame对象是pandas的重要特性。read_csv和read_table可能是我们使用最多的函数。
Pandas的解析函数
从一个小型的逗号分隔文本文件(CSV)开始,这个文件是逗号分隔的,我们可以使用read_csv将它读入一个DataFrame:
>>> df = pd.read_csv('examples/ex1.csv')
>>> dfa b c d message
0 1 2 3 4 hello
1 5 6 7 8 world
2 9 10 11 12 foo
也可以使用read_table,并指定分隔符:
>>> 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', 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>>> 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
假设你想要message列成为返回DataFrame的索引,你可以指定位置4的列为索引,或将'message'传给参数index_col:
>>> 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
当你想要从多个列中形成一个分层索引,需要传入一个包含列序号或列名的列表:
>>> parsed = pd.read_csv('examples/csv_mindex.csv',
>>> index_col=['key1', 'key2'])
>>> parsedvalue1 value2
key1 key2
one a 1 2b 3 4c 5 6d 7 8
two a 9 10b 11 12c 13 14d 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']
当字段是以多种不同数量的空格分开时,尽管你可以手工处理,但在这些情况下也可以向read_table传入一个正则表达式作为分隔符。在本例中,正则表达式为\s+,因此我们可以得到:
>>> result = pd.read_table('examples/ex3.txt', sep='\s+')
>>> resultA 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
由于列名的数量比数据的列数少一个,因此read_table推断第一列应当作为DataFrame的索引。
解析函数有很多附加参数帮助你处理各种发生异常的文件格式。例如,你可以使用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')
>>> resultsomething 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'])
>>> resultsomething 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']}
>>> 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
一些read_csv/read_table函数参数
1.1 分块读入文本文件
当处理大型文件或找出正确的参数集来正确处理大文件时,你可能需要读入文件的一个小片段或者按小块遍历文件。
在尝试大文件之前,我们可以先对pandas的显示设置进行调整,使之更为紧凑:
>>> pd.options.display.max_rows = 10
>>> result = pd.read_csv('examples/ex6.csv')
>>> resultone 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 x 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
<pandas.io.parsers.TextFileReader at 0x7f6b1e2672e8>
read_csv返回的TextParser对象允许你根据chunksize遍历文件。例如,我们可以遍历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方法,允许你按照任意大小读取数据块。
1.2 将数据写入文本格式
数据可以导出为分隔的形式。
>>> data = pd.read_csv('examples/ex5.csv')
>>> datasomething 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')
当然,其他的分隔符也是可以的(写入到sys.stdout时,控制台中打印的文本结果):
>>> import sys
>>> 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')
1.3 使用分隔格式
绝大多数的表型数据都可以使用函数pandas.read_table从硬盘中读取。然而,在某些情况下,一些手动操作可能是必不可少的。接收一个带有一行或多行错误的文件并不少见,read_table也无法解决这种情况。
对于任何带有单字符分隔符的文件,可以使用Python的内建csv模块。要使用它,需要将任一打开的文件或文件型对象传给csv.reader:
import csv
f = open('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('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')}
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)
>>> result
{'name': 'Wes','pet': None,'places_lived': ['United States', 'Spain', 'Germany'],'siblings': [{'age': 30, 'name': 'Scott', 'pets': ['Zeus', 'Zuko']},{'age': 38, 'name': 'Katie', 'pets': ['Sixes', 'Stache', 'Cisco']}]}
json.dumps可以将Python对象转换回JSON:
>>> asjson = json.dumps(result)
将JSON对象或对象列表转换为DataFrame或其他数据结构。比较方便的方式是将字典构成的列表(之前是JSON对象)传入DataFrame构造函数,并选出数据字段的子集:
>>> siblings = pd.DataFrame(result['siblings'], columns=['name', 'age'])
>>> siblingsname age
0 Scott 30
1 Katie 38
pandas.read_json的默认选项是假设JSON数组中的每个对象是表里的一行:
>>> data = pd.read_json('examples/example.json')
>>> dataa b c
0 1 2 3
1 4 5 6
2 7 8 9
从pandas中将数据导出为JSON,一种办法是对Series和DataFrame使用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}]
1.5 XML和HTML:网络抓取
Python拥有很多可以对HTML和XML格式进行读取、写入数据的库,例如lxml(http://lxml.de )、Beautiful Soup和html5lib。尽管lxml是相对更快的库,但其他库可以更好地处理异常的HTML或XML文件。
pandas的内建函数read_html可以使用lxml和Beautiful Soup等库将HTML中的表自动解析为DataFrame对象。
首先,必须安装read_html所使用的附加库:
conda install lxml
pip install beautifulsoup4 html5lib
pandas.read_html函数有很多选项,但是默认情况下,它会搜索并尝试解析所有包含在<table>标签中的表格型数据,返回的结果是DataFrame对象的列表:
>>> tables = pd.read_html('examples/fdic_failed_bank_list.html')
>>> len(tables)
1>>> failures = tables[0]
>>> failures.head()Bank Name City ST CERT \
0 Allied Bank Mulberry AR 91
1 The Woodbury Banking Company Woodbury GA 11297
2 First CornerStone Bank King of Prussia PA 35312
3 Trust Company Bank Memphis TN 9956
4 North Milwaukee State Bank Milwaukee WI 20364 Acquiring Institution Closing Date Updated Date
0 Today's Bank September 23, 2016 November 17, 2016
1 United Bank August 19, 2016 November 17, 2016
2 First-Citizens Bank & Trust Company May 6, 2016 September 6, 2016
3 The Bank of Fayette County April 29, 2016 September 6, 2016
4 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
1.5.1 使用lxml.objectify解析XML
XML(eXtensible Markup Language)是另一种常用的结构化数据格式,它使用元数据支持分层、嵌套数据。
<INDICATOR><INDICATOR_SEQ>373889</INDICATOR_SEQ><PARENT_SEQ></PARENT_SEQ><AGENCY_NAME>Metro-North Railroad</AGENCY_NAME><INDICATOR_NAME>Escalator Availability</INDICATOR_NAME><DESCRIPTION>Percent of the time that escalators are operationalsystemwide. The availability rate is based on physical observations performedthe morning of regular business days only. This is a new indicator the agencybegan reporting in 2009.</DESCRIPTION><PERIOD_YEAR>2011</PERIOD_YEAR><PERIOD_MONTH>12</PERIOD_MONTH><CATEGORY>Service Indicators</CATEGORY><FREQUENCY>M</FREQUENCY><DESIRED_CHANGE>U</DESIRED_CHANGE><INDICATOR_UNIT>%</INDICATOR_UNIT><DECIMAL_PLACES>1</DECIMAL_PLACES><YTD_TARGET>97.00</YTD_TARGET><YTD_ACTUAL></YTD_ACTUAL><MONTHLY_TARGET>97.00</MONTHLY_TARGET><MONTHLY_ACTUAL></MONTHLY_ACTUAL>
</INDICATOR>
使用lxml.objectify,我们可以解析这个文件,并用getroot来获得对XML文件的根节点的引用:
from lxml import objectifypath = 'datasets/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:continueel_data[child.tag] = child.pyvaldata.append(el_data)
最后,将包含字典的列表转换为DataFrame:
>>> perf = pd.DataFrame(data)
>>> perf.head()
XML数据可以比例子更复杂。每个标签也可以包含元数据。考虑一个HTML连接标签,也是有效的XML:
>>> from io import StringIO
>>> tag = '<a href="http://www.google.com">Google</a>'
>>> root = objectify.parse(StringIO(tag)).getroot()
>>> root
<Element a at 0x7f6b15817748>>>> root.get('href')
'http://www.google.com'>>> root.text
'Google'
2. 二进制格式
使用Python内建的pickle序列化模块进行二进制格式操作是存储数据(也称为序列化)最高效、最方便的方式之一。pandas对象拥有一个to_pickle方法可以将数据以pickle格式写入硬盘:
>>> frame = pd.read_csv('examples/ex1.csv')
>>> framea 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('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很难确保格式的长期有效性;一个今天被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
>>> 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 x 1 columns]
HDFStore支持两种存储模式,'fixed'和'table'。后者速度更慢,但支持一种特殊语法的查询操作:
>>> store.put('obj2', frame, format='table')
>>> store.select('obj2', where=['index >= 10 and index <= 15'])a
10 1.007189
11 -1.296221
12 0.274992
13 0.228913
14 1.352917
15 0.886429>>> store.close()
put是store['obj2']=frame方法的显式版本,但允许我们设置其他选项,如存储格式。
pandas.read_hdf函数是这些工具的快捷方法:
>>> 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
2.2 读取Microsoft Excel文件
pandas也支持通过ExcelFile类或pandas.read_excel函数来读取存储在Excel 文件中的表格型数据。这些工具内部是使用附加包xlrd和openpyxl来分别读取XLS和XLSX文件的。
使用ExcelFile时,通过将xls或xlsx的路径传入,生成一个实例:
>>> xlsx = pd.ExcelFile('examples/ex1.xlsx')
>>> pd.read_excel(xlsx, 'Sheet1')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('examples/ex1.xlsx', 'Sheet1')
>>> framea 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('examples/ex2.xlsx')
>>> frame.to_excel(writer, 'Sheet1')
>>> writer.save()
也可以将文件路径传给to_excel,避免直接调用ExcelWriter:
>>> frame.to_excel('examples/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)
>>> resp
<Response [200]>
Response(响应)对象的json方法将返回一个包含解析为本地Python对象的JSON的字典:
>>> data = resp.json()
>>> data[0]['title']
'BUG: rank with +-inf, # 6945'
data中的每个元素都是一个包含GitHub问题页面上的所有数据的字典(注释除外)。可以将data直接传给DataFrame,并提取感兴趣的字段:
>>> issues = pd.DataFrame(data, columns=['number','title',
>>> 'labels', 'state'])
>>> issuesnumber title\
0 17903 BUG:rank with +-inf, #6945
1 17902 Revert "ERP: Raise ValueError when setting sca...
2 17901 Wrong orientation of operations between DataFr...
3 17900 added 'infer' option to compression in _get_ha...
4 17898 Last day of month should group with that month
.. ... ...
25 17854 Adding an integer-location based "get" method
26 17853 BUG: adds validation for boolean keywords in D...
27 17851 BUG: duplicate indexing with embedded non-orde...
28 17850 ImportError: No module named 'pandas.plotting'
29 17846 BUG: Ignore division by 0 when merging empty d...Labels state
0 [] open
1 [{'id': 35818298, 'url': 'https://api.github.c... open
2 [] open
3 [] open
4 [{'id': 76811, 'url': 'https://api.github.com/ ... open
.. ... ...
25 [{'id': 35818298, 'url': 'https://api.github.c ... open
26 [{'id': 42670965, 'url': 'https://api.github.c ... open
27 [{'id': 76811, 'url': 'https://api.github.com/ ... open
28 [{'id': 31932467, 'url': 'https://api.github.c ... open
29 [{'id': 76865106, 'url': 'https://api.github.c ... open
[30 rows x 4 columns]
通过一些复杂操作,可以创建一些更高阶的接口来访问常用的Web API,以返回DataFrame对象以便于分析。
4. 与数据库交互
在业务场景中,大部分数据并不是储存在文本或Excel文件中的。基于SQL的关系型数据库(例如SQL Server、PostgreSQL和MySQL)使用广泛,很多小众数据库也变得越发流行。数据库的选择通常取决于性能、数据完整性以及应用的可伸缩性需求。
从SQL中将数据读取为DataFrame是相当简单直接的,pandas有多个函数可以简化这个过程。作为例子,将使用Python内建的sqlite3驱动来生成一个SQLite数据库:
>>> import sqlite3
>>> query = """
>>> CREATE TABLE test
>>> (a VARCHAR(20), b VARCHAR(20),
>>> c REAL, d INTEGER
>>> );""">>> con = sqlite3.connect('mydata.sqlite')
>>> con.execute(query)
<sqlite3.Cursor at 0x7f6b12a50f10>>>> 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)
<sqlite3.Cursor at 0x7f6b15c66ce0>>>> con.commit()
当从数据库的表中选择数据时,大部分Python的SQL驱动(PyODBC、psycopg2、MySQLdb、pymssql等)返回的是元组的列表:
>>> 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)]
可以将元组的列表传给DataFrame构造函数,但还需要包含在游标的description属性中的列名:
>>> cursor.description
(('a', None, None, None, None, None, None),('b', None, None, None, None, None, None),('c', None, None, None, None, None, None),('d', None, None, None, None, None, None))>>> pd.DataFrame(rows, columns=[x[0] for x in cursor.description])a b c d
0 Atlanta Georgia 1.25 6
1 Tallahassee Florida 2.60 3
2 Sacramento California 1.70 5
使用SQLAlchemy连接到相同的SQLite数据库,并从之前创建的表中读取数据:
>>> import sqlalchemy as sqla
>>> db = sqla.create_engine('sqlite:///mydata.sqlite')
>>> pd.read_sql('select * from test', db)a b c d
0 Atlanta Georgia 1.25 6
1 Tallahassee Florida 2.60 3
2 Sacramento California 1.70 5