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

目录

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')
>>> 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,并指定分隔符:

>>> 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'])
>>> 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']

当字段是以多种不同数量的空格分开时,尽管你可以手工处理,但在这些情况下也可以向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

由于列名的数量比数据的列数少一个,因此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')
>>> 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

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

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

当然,其他的分隔符也是可以的(写入到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'])
>>> siblings
    name  age
0  Scott   30
1  Katie   38

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,一种办法是对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 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.</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 objectify

path = '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:
            continue
        el_data[child.tag] = child.pyval
    data.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')
>>> 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('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')
>>> 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('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'])
>>> issues
    number                                               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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南河Aure

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值