pandas入门(6)——数据加载、存储与文件格式

pandas入门(6)——数据加载、存储与文件格式

输入输出通常可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用Web API操作网络资源

一、读取文本格式数据

函数在将文本数据转换为DataFrame时会用到一些技术,这些函数的选项可以划分为:

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

备注:pandas文档有不同参数的例子,如果你感到阅读某个文件很难,可以通过相似的足够多的例子找到正确的参数

其中一些函数,比如pandas.read_csv,有类型推断功能,因为列数据的类型不属于数据类型。也就是说,你不需要指定列的类型到底是数值、整数、布尔值,还是字符串。其它的数据格式,如HDF5、Feather和msgpack,会在格式中存储数据类型

1、日期和其他自定义类型的处理

若文件以逗号分隔,可以使用read_csv将其读入一个DataFrame:

In [1]: df = pd.read_csv(''D:/python/学习笔记/examples/ex1.csv'')
#或pd.read_table('D:/python/学习笔记/examples/ex1.csv', sep=',')

In [2]: df
Out[2]: 
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo
  1. 并不是所有文件都有标题行,读入这种文件的办法有两个:可以让pandas为其分配默认的列名,也可以自己定义列名,如

    In [3]:pd.read_csv('D:/python/学习笔记/examples/ex2.csv',header=None)
    Out[3]: 
       0   1   2   3      4
    0  1   2   3   4  hello
    1  5   6   7   8  world
    2  9  10  11  12    foo
    
    In [4]: pd.read_csv('D:/python/学习笔记/examples/ex2.csv',names=       ['a','b','c','d','message'])
    Out[4]: 
       a   b   c   d message
    0  1   2   3   4   hello
    1  5   6   7   8   world
    2  9  10  11  12     foo
    
  2. 将message列做成DataFrame的索引,可以明确表示要将该列放到索引4的位置上,也可以通过index_col参数指定"message":

    In [5]: names = ['a', 'b', 'c', 'd', 'message']
    
    In [6]: pd.read_csv('D:/python/学习笔记/examples/ex2.csv', names=names, index_col='message')
    Out[6]: 
             a   b   c   d
    message               
    hello    1   2   3   4
    world    5   6   7   8
    foo      9  10  11  12
    
  3. 将多个列做成一个层次化索引,只需传入由列编号或列名组成的列表即可

    In [7]: parsed=pd.read_csv('D:/python/学习笔记/examples/csv_mindex.csv',index_col=['key1','key2'])
    
    In [8]: parsed
    Out[8]: 
               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
    
  4. 有些表格可能不是用固定的分隔符去分隔字段的(比如空白符或其它模式),虽然可以手动对数据进行规整,这里的字段是被数量不同的空白字符间隔开的。这种情况下,你可以传递一个正则表达式作为read_table的分隔符。可以用正则表达式表达为\s+:

    In [9]: list(open('examples/ex3.txt'))
    Out[9]: 
    ['            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']
     
    In [10]: result=pd.read_table('D:/python/学习笔记/examples/ex3.txt',sep='\s+')
    
    In [11]: result
    Out[11]: 
                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的索引

  5. 解析器函数还有许多参数可以帮助你处理各种各样的异形文件格式。比如说,你可以用skiprows跳过文件的第一行、第三行和第四行:

    In [12]: pd.read_csv('D:/python/学习笔记/examples/ex4.csv', skiprows=[0, 2, 3])
    Out[12]: 
       a   b   c   d message
    0  1   2   3   4   hello
    1  5   6   7   8   world
    2  9  10  11  12     foo
    
  6. 缺失值处理:文件解析任务中的一个重要组成部分。缺失数据经常是要么没有(空字符串),要么用某个标记值表示。默认情况下,pandas会用一组经常出现的标记值进行识别,比如NA及NULL:

    In [13]:result=pd.read_csv('D:/python/学习笔记/examples/ex5.csv')
    
    In [14]: result
    Out[14]: 
      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
    
    In [15]: pd.isnull(result)
    Out[15]: 
       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可以用一个列表或集合的字符串表示缺失值:

    In [16]: result = pd.read_csv('D:/python/学习笔记/examples/ex5', na_values=['NULL'])
    
    In [17]: result
    Out[17]: 
      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标记值:

    In [18]: sentinels = {'message': ['foo', 'NA'], 'something': ['two']}
    
    In [19]: pd.read_csv('D:/python/学习笔记/examples/ex5', na_values=sentinels)
    Out[19]:
    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
    

2、逐快读取文本文件

在处理很大的文件时,或找出大文件中的参数集以便于后续处理时,你可能只想读取文件的一小部分或逐块对文件进行迭代,在看大文件之前,可先设置pandas显示地更紧些:

In [20]: pd.options.display.max_rows = 10
In [21]: result = pd.read_csv('D:/python/学习笔记/examples/ex6.csv')

In [22]: result
Out[22]: 
           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]
If you want to only read a small

如果只想读取几行(避免读取整个文件),通过nrows进行指定即可:

In [23]: pd.read_csv('D:/python/学习笔记/examples/ex6.csv', nrows=5)
Out[23]: 
        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(行数):

In [24]: chunker = pd.read_csv('ch06/ex6.csv', chunksize=1000)

In [25]: chunker
Out[25]: 

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)

In [26]: tot[:10]
Out[26]: 
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

TextParser还有一个get_chunk方法,它使你可以读取任意大小的块

3、将数据写出到文本格式

数据也可以被输出为分隔符格式的文本

In [27]: data = pd.read_csv('D:/python/学习笔记/examples/ex6.csv')

In [28]: data
Out[28]: 
  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方法,我们可以将数据写到一个以逗号分隔的文件中:
In [29]: data.to_csv('D:/python/学习笔记/examples/out.csv')

还可以使用其他分隔符(由于这里直接写出到sys.stdout,所以仅仅是打印出文本结果而已):

In [30]: import sys

In [31]: 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

缺失值在输出结果中会被表示为空字符串,可将其表示为别的标记值:

In [32]: 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

如果没有设置其他选项,则会写出行和列的标签。当然,它们也都可以被禁用:

In [33]: 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

此外,还可以只写出一部分的列,并以你指定的顺序排列

In [34]: 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方法:

In [35]: dates = pd.date_range('1/1/2000', periods=7)

In [36]: ts = pd.Series(np.arange(7), index=dates)

In [37]: ts.to_csv('examples/tseries.csv')

In [37]: !cat examples/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进行加载。然而,有时还是需要做一些手工处理。由于接收到含有畸形行的文件而使read_table出毛病的情况并不少见

对于任何单字符分隔符文件,可以直接使用Python内置的csv模块。将任意已打开的文件或文件型的对象传给csv.reader:

import csv
f = open('D:/python/学习笔记/examples/ex7.csv')

reader = csv.reader(f)

对这个reader进行迭代将会为每行产生一个元组(并移除了所有的引号):

In [38]: for line in reader: #用遍历文件那样遍历reader会产生元组
     print(line)
   
['a', 'b', 'c']
['1', '2', '3']
['1', '2', '3']

首先,读取文件到一个多行的列表中:

In [39]: with open('D:/python/学习笔记/examples/ex7.csv') as f: #将文件读取为行的列表
       lines = list(csv.reader(f))

然后,我们将这些行分为标题行和数据行:

In [40]: header, values = lines[0], lines[1:]

然后,我们可以用字典构造式和zip(*values),后者将行转置为列,创建数据列的字典:

In [41]: data_dict = {h: v for h, v in zip(header, zip(*values))}#打包函数*指解包

In [42]: data_dict
Out[42]: {'a': ('1', '1'), 'b': ('2', '2'), 'c': ('3', '3')}

CSV文件的形式有很多。只需定义csv.Dialect的一个子类即可定义出新格式(如专门的分隔符、字符串引用约定、行结束符等):

class my_dialect(csv.Dialect):
    lineterminator = '\n' #用于写操作的函数结束符,默认\r\n
    delimiter = ';' #用于分割字段的单字符串,默认','
    quotechar = '"' #用于带有特殊字符(如分隔符)的字段引用符号
    quoting = csv.QUOTE_MINIMAL #引用约定 
reader = csv.reader(f, dialect=my_dialect)

各个CSV语支的参数也可以用关键字的形式提供给csv.reader,而无需定义子类:

reader = csv.reader(f, delimiter='|')

要手工输出分隔符文件,你可以使用csv.writer。它接受一个已打开且可写的文件对象以及跟csv.reader相同的那些语支和格式化选项:

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

5、JSON数据

JSON(JavaScript Object Notation的简称)已经成为通过HTTP请求在Web浏览器和其他应用程序之间发送数据的标准格式之一。它是一种比表格型文本格式(如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"]}]
}
"""

其空值null和一些其他的细微差别(如列表末尾不允许存在多余的逗号)之外,JSON非常接近于有效的Python代码。基本类型有对象(字典)、数组(列表)、字符串、数值、布尔值以及null。对象中所有的键都必须是字符串。许多Python库都可以读写JSON数据。我将使用json,因为它是构建于Python标准库中的

通过json.loads即可将JSON字符串转换成Python形式

In [43]: import json

In [44]: result = json.loads(obj)

In [45]: result
Out[45]: 
{'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格式:

In [46]: asjson = json.dumps(result)

将(一个或一组)JSON对象转换为DataFrame或其他便于分析的数据结构

最简单方便的方式是:向DataFrame构造器传入一个字典的列表(就是原先的JSON对象),并选取数据字段的子集,如

In [47]: siblings = pd.DataFrame(result['siblings'], columns=['name', 'age'])

In [48]: siblings
Out[48]: 
    name  age
0  Scott   30
1  Katie   38

pandas.read_json可以自动将特别格式的JSON数据集转换为Series或DataFrame

pandas.read_json的默认选项假设JSON数组中的每个对象是表格中的一行:

In [49]: data = pd.read_json('D:/python/学习笔记/examples/example.json')

In [50]: data
Out[50]: 
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

将数据从pandas输出到JSON,可以使用to_json方法

In [51]: 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}}

In [52]: print(data.to_json(orient='records'))
[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]

二、二进制数据格式

实现数据的高效二进制格式存储最简单的办法之一是使用Python内置的pickle序列化。pandas对象都有一个用于将数据以pickle格式保存到磁盘上的to_pickle方法:

In [53]: frame = pd.read_csv('D:/python/学习笔记/examples/ex1.csv')

In [54]: frame
Out[55]: 
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

In [89]: frame.to_pickle('D:/python/学习笔记/examples/frame_pickle')

你可以通过pickle直接读取被pickle化的数据,或是使用更为方便的pandas.read_pickle:

In [56]: pd.read_pickle('D:/python/学习笔记/examples/frame_pickle')
Out[56]: 
   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的对象可能无法被后续版本的库unpickle出来。虽然我尽力保证这种事情不会发生在pandas中,但是今后的某个时候说不定还是得“打破”该pickle格式

pandas内置支持两个二进制数据格式:HDF5和MessagePack。下一节,我会给出几个HDF5的例子,但我建议你尝试下不同的文件格式,看看它们的速度以及是否适合你的分析工作。pandas或NumPy数据的其它存储格式有:

  • bcolz:一种可压缩的列存储二进制格式,基于Blosc压缩库。
  • Feather:我与R语言社区的Hadley Wickham设计的一种跨语言的列存储文件格式。Feather使用了Apache Arrow的列式内存格式。

1、使用HDF5格式

DF5是一种存储大规模科学数组数据的非常好的文件格式。它可以被作为C标准库,带有许多语言的接口,如Java、Python和MATLAB等。HDF5中的HDF指的是层次型数据格式(hierarchical data format)。每个HDF5文件都含有一个文件系统式的节点结构,它使你能够存储多个数据集并支持元数据。与其他简单格式相比,HDF5支持多种压缩器的即时压缩,还能更高效地存储重复模式数据。对于那些非常大的无法直接放入内存的数据集,HDF5就是不错的选择,因为它可以高效地分块读写。

虽然可以用PyTables或h5py库直接访问HDF5文件,pandas提供了更为高级的接口,可以简化存储Series和DataFrame对象。HDFStore类可以像字典一样,处理低级的细节:

In [57]: frame = pd.DataFrame({'a': np.random.randn(100)})

In [58]: store = pd.HDFStore('mydata.h5')

In [59]: store['obj1'] = frame

In [60]: store['obj1_col'] = frame['a']

In [61]: store
Out[61]: 

File path: mydata.h5
/obj1                frame        (shape->[100,1])                               

/obj1_col            series       (shape->[100])                                 

/obj2                frame_table  (typ->appendable,nrows->100,ncols->1,indexers->
[index])
/obj3                frame_table  (typ->appendable,nrows->100,ncols->1,indexers->
[index])

HDF5文件中的对象可以通过与字典一样的API进行获取:

In [62]: store['obj1']
Out[62]: 
           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’。后者通常会更慢,但是支持使用特殊语法进行查询操作

In [63]: store.put('obj2', frame, format='table')

In [64]: store.select('obj2', where=['index >= 10 and index <= 15'])
Out[64]: 
           a
10  1.007189
11 -1.296221
12  0.274992
13  0.228913
14  1.352917
15  0.886429

In [65]: store.close()

备注:put是store[‘obj2’] = frame方法的显示版本,允许我们设置其它的选项,比如格式

pandas.read_hdf函数可以快捷使用这些工具

In [66]: frame.to_hdf('mydata.h5', 'obj3', format='table')

In [67]: pd.read_hdf('mydata.h5', 'obj3', where=['index < 5'])
Out[67]: 
          a
0 -0.204708
1  0.478943
2 -0.519439
3 -0.555730
4  1.965781

笔记:如果你要处理的数据位于远程服务器,比如Amazon S3或HDFS,使用专门为分布式存储(比如Apache Parquet)的二进制格式也许更加合适。Python的Parquet和其它存储格式还在不断的发展之中,所以此处没有涉及

如果需要本地处理海量数据,我建议你好好研究一下PyTables和h5py,看看它们能满足你的哪些需求。。由于许多数据分析问题都是IO密集型(而不是CPU密集型),利用HDF5这样的工具能显著提升应用程序的效率

注意:HDF5不是数据库。它最适合用作“一次写多次读”的数据集。虽然数据可以在任何时候被添加到文件中,但如果同时发生多个写操作,文件就可能会被破坏

2、读取Microsoft Excel文件

pandas的ExcelFile类或pandas.read_excel函数支持读取存储在Excel 2003(或更高版本)中的表格型数据。这两个工具分别使用扩展包xlrd和openpyxl读取XLS和XLSX文件。你可以用pip或conda安装它们:

pip install xlrd
pip install openpyxl

读取文件

要使用ExcelFile,通过传递xls或xlsx路径创建一个实例:

In [68]: xlsx = pd.ExcelFile('D:/python/学习笔记/examples/ex1.xlsx')

存储在表单中的数据可以read_excel读取到DataFrame:

In [69]: pd.read_excel(xlsx, 'Sheet1')
Out[69]: 
   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:

In [70]: frame = pd.read_excel('D:/python/学习笔记/examples/ex1.xlsx', 'Sheet1')

In [71]: frame
Out[71]: 
   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方法将数据写入到其中:

In [72]: writer = pd.ExcelWriter('D:/python/学习笔记/examples/ex2.xlsx')

In [73]: frame.to_excel(writer, 'Sheet1')

In [74]: writer.save()

你还可以不使用ExcelWriter,而是传递文件的路径到to_excel:

In [75]: frame.to_excel('examples/ex2.xlsx')

3、 Web APIs交互

许多网站都有一些通过JSON或其他格式提供数据的公共API。通过Python访问这些API的办法有不少。一个简单易用的办法(推荐)是requests包(http://docs.python-requests.org)

为了搜索最新的30个GitHub上的pandas主题,我们可以发一个HTTP GET请求,使用requests扩展库:

In [76]: import requests

In [77]: url = 'https://api.github.com/repos/pandas-dev/pandas/issues'

In [76]: resp = requests.get(url)

In [78]: resp
Out[78]: 

响应对象的json方法会返回一个包含被解析过的JSON字典,加载到一个Python对象中:

In [79]: data = resp.json()

In [80]: data[0]['title']
Out[80]: 'Period does not round down for frequencies less that 1 hour'

data中的每个元素都是一个包含所有GitHub主题页数据(不包含评论)的字典。我们可以直接传递数据到DataFrame,并提取感兴趣的字段:

In [81]: issues = pd.DataFrame(data, columns=['number', 'title',
   .....:                                      'labels', 'state'])

In [81]: issues
Out[82]:
    number                                              title  \
0    17666  Period does not round down for frequencies les...   
1    17665           DOC: improve docstring of function where   
2    17664               COMPAT: skip 32-bit test on int repr   
3    17662                          implement Delegator class
4    17654  BUG: Fix series rename called with str alterin...   
..     ...                                                ...   
25   17603  BUG: Correctly localize naive datetime strings...   
26   17599                     core.dtypes.generic --> cython   
27   17596   Merge cdate_range functionality into bdate_range   
28   17587  Time Grouper bug fix when applied for list gro...   
29   17583  BUG: fix tz-aware DatetimeIndex + TimedeltaInd...   
                                               labels state  
0                                                  []  open  
1   [{'id': 134699, 'url': 'https://api.github.com...  open  
2   [{'id': 563047854, 'url': 'https://api.github....  open  
3                                                  []  open  
4   [{'id': 76811, 'url': 'https://api.github.com/...  open  
..                                                ...   ...  
25  [{'id': 76811, 'url': 'https://api.github.com/...  open  
26  [{'id': 49094459, 'url': 'https://api.github.c...  open  
27  [{'id': 35818298, 'url': 'https://api.github.c...  open  
28  [{'id': 233160, 'url': 'https://api.github.com...  open  
29  [{'id': 76811, 'url': 'https://api.github.com/...  open  
[30 rows x 4 columns]

花费一些精力,你就可以创建一些更高级的常见的Web API的接口,返回DataFrame对象,方便进行分析

4、数据库交互

在商业场景下,大多数数据可能不是存储在文本或Excel文件中。基于SQL的关系型数据库(如SQL Server、PostgreSQL和MySQL等)使用非常广泛,其它一些数据库也很流行。数据库的选择通常取决于性能、数据完整性以及应用程序的伸缩性需求。

将数据从SQL加载到DataFrame的过程很简单,此外pandas还有一些能够简化该过程的函数。例如,我将使用SQLite数据库(通过Python内置的sqlite3驱动器):

In [83]: import sqlite3

In [84]: query = """
   .....: CREATE TABLE test
   .....: (a VARCHAR(20), b VARCHAR(20),
   .....:  c REAL,        d INTEGER
   .....: );"""

In [85]: con = sqlite3.connect('mydata.sqlite')

In [86]: con.execute(query)
Out[86]: 

In [87]: con.commit()

然后插入几行数据:

In [88]: data = [('Atlanta', 'Georgia', 1.25, 6),
   .....:         ('Tallahassee', 'Florida', 2.6, 3),
   .....:         ('Sacramento', 'California', 1.7, 5)]

In [89]: stmt = "INSERT INTO test VALUES(?, ?, ?, ?)"

In [90]: con.executemany(stmt, data)
Out[90]: 

从表中选取数据时,大部分Python SQL驱动器(PyODBC、psycopg2、MySQLdb、pymssql等)都会返回一个元组列表:

In [91]: cursor = con.execute('select * from test')

In [92]: rows = cursor.fetchall()

In [93]: rows
Out[93]: 
[('Atlanta', 'Georgia', 1.25, 6),
 ('Tallahassee', 'Florida', 2.6, 3),
 ('Sacramento', 'California', 1.7, 5)]

你可以将这个元组列表传给DataFrame构造器,但还需要列名(位于光标的description属性中):

In [94]: cursor.description
Out[94]: 
(('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))

In [95]: pd.DataFrame(rows, columns=[x[0] for x in cursor.description])
Out[95]: 
             a           b     c  d
0      Atlanta     Georgia  1.25  6
1  Tallahassee     Florida  2.60  3
2   Sacramento  California  1.70  5

这种数据规整操作相当多,你肯定不想每查一次数据库就重写一次。SQLAlchemy项目是一个流行的Python SQL工具,它抽象出了SQL数据库中的许多常见差异。pandas有一个read_sql函数,可以让你轻松的从SQLAlchemy连接读取数据。这里,我们用SQLAlchemy连接SQLite数据库,并从之前创建的表读取数据:

In [96]: import sqlalchemy as sqla

In [96]: db = sqla.create_engine('sqlite:///mydata.sqlite')

In [97]: pd.read_sql('select * from test', db)
Out[97]: 
             a           b     c  d
0      Atlanta     Georgia  1.25  6
1  Tallahassee     Florida  2.60  3
2   Sacramento  California  1.70  5

你可能感兴趣的:(pandas,python,数据分析)