9.2 Pandas

Pandas是基于NumPy的一个非常好用的库,正如名字一样,人见人爱。之所以如此,是因为不论是读取还是处理数据,用它都非常简单。

9.2.1 基本的数据结构

Pandas有两种自己独有的基本数据结构。读者应该注意的是,它固然有着两种数据结构,因为它依然是Python的一个库,所以,Python中有的数据类型在这里依然适用,同样还可以使用类自己定义数据类型。不过,Pandas里面又定义了两种数据类型:Series和DataFrame,它们让数据操作更简单。

以下操作都是基于如下模块导入:

9.2 Pandas - 图1

为了省事,后面就不再显示了。如果你跟我一样是使用的ipython notebook,只需要开始引入模块即可。

  • SeriesSeries如同列表一样,有一系列数据,每个数据对应一个索引值。比如这样一个列表:[9,3,8],如果跟索引值写到一起,就是:

9.2 Pandas - 图2

这种样式我们已经熟悉了,不过,有些时候需要把它竖过来表示:

9.2 Pandas - 图3

上面两种,只是表现形式上的差别罢了。

Series就是“竖起来”的list:

9.2 Pandas - 图4

另外一点也很像列表,就是其中元素的类型由你任意决定(其实是由需要来决定)。

这样,我们就创建了一个Series对象,这个对象有其属性和方法。比如,下面的两个属性依次可以显示Series对象的数据值和索引:

9.2 Pandas - 图5

列表的索引只能是从0开始的整数,在默认情况下,Series数据类型其索引也是如此。但区别于列表的是,Series可以自定义索引:

9.2 Pandas - 图6

每个元素都有了索引,就可以根据索引操作元素了。还记得list中的操作吗?在Series中也有类似的操作。先看简单的,根据索引查看其值和修改其值:

9.2 Pandas - 图7

这是不是又有点类似dict数据?的确如此,看下面就理解了。

前面定义Series对象的时候,用的是列表,即Series()方法的参数中第一个列表就是其数据值,如果需要定义index,放在后面依然是一个列表。除了这种方法之外,还可以用下面的方法定义Series对象:

9.2 Pandas - 图8

现在是否理解为什么前面那个类似dict了?因为本来就是可以这样定义的。

这时候,索引依然可以自定义。Pandas的优势在这里体现出来,如果自定义了索引,自定义的索引会自动寻找原来的索引。如果一样,就取原来索引对应的值,这个可以简称为“自动对齐”。

9.2 Pandas - 图9

在sd中,只有“'python':8000,'c++':8100,'c#':4000”,没有“java”,但是在索引参数中有,于是其他能够“自动对齐”的照搬原值,没有的那个“java”依然在新Series对象的索引中存在,并且自动为其赋值NaN。在Pandas中,如果没有值,都对齐赋给NaN。下面来一个更特殊的:

9.2 Pandas - 图10

新得到的Series对象索引与sd对象一个也不对应,所以都是NaN。

Pandas有专门的方法来判断值是否为空。

9.2 Pandas - 图11

此外,Series对象也有同样的方法:

9.2 Pandas - 图12

其实,对索引的名字是可以重新定义的:

9.2 Pandas - 图13

对于Series数据,也可以做类似下面的运算:

9.2 Pandas - 图14

上面的演示都是在ipython notebook中进行的,所以截图了。在学习Series数据类型的同时了解了ipyton notebook。对于后面的所有操作,读者都可以在ipython notebook中进行,也可以在Python交互模式中进行。

  • DataFrameDataFrame是一种二维的数据结构,非常接近于电子表格或者类似MySQL数据库的形式。它的竖行称之为columns,横行跟前面的Series一样,称之为index,也就是说可以通过columns和index来确定一个主句的位置。

9.2 Pandas - 图15

下面的演示在Python交互模式下进行,读者仍然可以在ipython notebook环境中测试。

  1. >>> import pandas as pd
  2. >>> from pandas import Series, DataFrame
  3.  
  4. >>> data = {"name":["yahoo","google","facebook"], "marks":[200,400,800], "price":[9, 3, 7]}
  5. >>> f1 = DataFrame(data)
  6. >>> f1
  7. marks name price
  8. 0 200 yahoo 9
  9. 1 400 google 3
  10. 2 800 facebook 7

这是定义一个DataFrame对象的常用方法——使用dict定义。字典的“键”("name","marks","price")就是DataFrame的columns的值(名称),字典中每个“键”的“值”是一个列表,它们就是那一竖列中的填充数据。上面的定义中没有确定索引,所以,按照惯例(Series中已经形成的惯例)就是从0开始的整数。从上面的结果中很明显表示出来,这就是一个二维的数据结构(类似Excel或者MySQL中的查看效果)。

上面的数据显示中,columns的顺序没有规定,就如同字典中键的顺序一样,但是在DataFrame中,columns跟字典键相比,有一个明显不同,就是其顺序可以被规定,如下所示:

  1. >>> f2 = DataFrame(data, columns=['name','price','marks'])
  2. >>> f2
  3. name price marks
  4. 0 yahoo 9 200
  5. 1 google 3 400
  6. 2 facebook 7 800

跟Series类似,DataFrame数据的索引也能够自定义。

  1. >>> f3 = DataFrame(data, columns=['name', 'price', 'marks', 'debt'], index=['a','b', 'c','d'])
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. File "/usr/lib/pymodules/python2.7/pandas/core/frame.py", line 283, in __init__
  5. mgr = self._init_dict(data, index, columns, dtype=dtype)
  6. File "/usr/lib/pymodules/python2.7/pandas/core/frame.py", line 368, in _init_dict
  7. mgr = BlockManager(blocks, axes)
  8. File "/usr/lib/pymodules/python2.7/pandas/core/internals.py", line 285, in __init__
  9. self._verify_integrity()
  10. File "/usr/lib/pymodules/python2.7/pandas/core/internals.py", line 367, in _verify_integrity
  11. assert(block.values.shape[1:] == mgr_shape[1:])
  12. AssertionError

报错了。这个报错信息太不友好了,也没有提供什么线索,这就是交互模式的不利之处。修改之,错误在于index的值——列表,其数据项多了一个,data中是三行,这里给出了四个项(['a','b','c','d'])。

  1. >>> f3 = DataFrame(data, columns=['name', 'price', 'marks', 'debt'], index=['a','b','c'])
  2. >>> f3
  3. name price marks debt
  4. a yahoo 9 200 NaN
  5. b google 3 400 NaN
  6. c facebook 7 800 NaN

读者还要注意观察上面的显示结果。因为在定义f3的时候,columns的参数中比以往多了一项('debt'),但是这项在data这个字典中并没有,所以debt这一竖列的值都是空的,在Pandas中,空就用NaN来代表了。

定义DataFrame的方法,还可以使用“字典套字典”的方式。

  1. >>> newdata = {"lang":{"firstline":"python","secondline":"java"}, "price":{"firstline": 8000}}
  2. >>> f4 = DataFrame(newdata)
  3. >>> f4
  4. lang price
  5. firstline python 8000
  6. secondline java NaN

在字典中就规定好数列名称(第一层键)和每横行索引(第二层字典键)以及对应的数据(第二层字典值),即在字典中规定好每个数据格子中的数据,没有规定的都是空。

  1. >>> DataFrame(newdata, index=["firstline","secondline","thirdline"])
  2. lang price
  3. firstline python 8000
  4. secondline java NaN
  5. thirdline NaN NaN

如果额外确定了索引,就如同上面显示的一样,除非在字典中有相应的索引内容,否则都是NaN。

前面定义了DataFrame数据,它也是一种对象类型,比如变量f3引用了一个对象,它的类型是DataFrame。承接以前的思维方法:对象有属性和方法。

  1. >>> f3.columns
  2. Index(['name', 'price', 'marks', 'debt'], dtype=object)

DataFrame对象的columns属性能够显示素有的columns名称,并且,还能用下面类似字典的方式得到某竖列的全部内容(当然包含索引):

  1. >>> f3['name']
  2. a yahoo
  3. b google
  4. c facebook
  5. Name: name

这其实就是一个Series,或者说,可以将DataFrame理解为是由一个一个的Series组成的。

一直耿耿于怀没有数值的那一列,下面的操作是统一给那一列赋值:

  1. >>> f3['debt'] = 89.2
  2. >>> f3
  3. name price marks debt
  4. a yahoo 9 200 89.2
  5. b google 3 400 89.2
  6. c facebook 7 800 89.2

除了能够统一赋值之外,还能够“点对点”添加数值,结合前面的Series,既然DataFrame对象的每竖列都是一个Series对象,那么可以先定义一个Series对象,然后把它放到DataFrame对象中。如下:

  1. >>> sdebt = Series([2.2, 3.3], index=["a","c"]) #注意索引
  2. >>> f3['debt'] = sdebt

将Series对象(sdebt变量所引用)赋给f3['debt']列,Pandas的一个重要特性——自动对齐,在这里起做用了,在Series中,只有两个索引("a","c"),它们将和DataFrame中的索引自动对齐。于是乎:

  1. >>> f3
  2. name price marks debt
  3. a yahoo 9 200 2.2
  4. b google 3 400 NaN
  5. c facebook 7 800 3.3

自动对齐之后,没有被复制的依然保持NaN。

还可以更精准地修改数据吗?当然可以,完全仿照字典的操作:

  1. >>> f3["price"]["c"]= 300
  2. >>> f3
  3. name price marks debt
  4. a yahoo 9 200 2.2
  5. b google 3 400 NaN
  6. c facebook 300 800 3.3

这些操作是不是都不陌生?这就是Pandas中的两种数据对象。

9.2.2 读取CSV文件

因为篇幅限制,不能将有关Pandas的内容完全详细讲述,只能“抛砖引玉”,向大家做一个简单介绍,说明其基本使用方法。当读者在实践中使用的时候,如果遇到问题,可以结合相关文档或者通过搜索来解决。

1.关于CSV文件

CSV是一种通用的、相对简单的文件格式,在表格类型的数据中用途很广泛,很多关系型数据库都支持这种类型文件的导入导出,并且Excel这种常用的数据表格也能和CSV文件之间转换。

逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其他字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。

从上述维基百科的叙述中,重点要解读出“字段间分隔符”和“最常见的是逗号或制表符”,当然,这种分隔符也可以自行制定。比如下面这个我命名为marks.csv的文件,就是用逗号(必须是半角的)作为分隔符:

  1. name,physics,python,math,english
  2. Google,100,100,25,12
  3. Facebook,45,54,44,88
  4. Twitter,54,76,13,91
  5. Yahoo,54,452,26,100

其实,这个文件要表达的事情是(如果转化为表格形式):

9.2 Pandas - 图16

最简单、最直接的就是用open()打开文件:

  1. >>> with open("./marks.csv") as f:
  2. ... for line in f:
  3. ... print line
  4. ...
  5. name,physics,python,math,english
  6.  
  7. Google,100,100,25,12
  8.  
  9. Facebook,45,54,44,88
  10.  
  11. Twitter,54,76,13,91
  12.  
  13. Yahoo,54,452,26,100

此方法可以,但略显麻烦。

Python中还有一个CSV的标准库,足可见CSV文件的使用频繁了。

  1. >>> import csv
  2. >>> dir(csv)
  3. ['Dialect', 'DictReader', 'DictWriter', 'Error', 'QUOTE_ALL', 'QUOTE_MINIMAL', 'QUOTE_NONE', 'QUOTE_NONNUMERIC', 'Sniffer', 'StringIO', '_Dialect', '__all__', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '__version__', 'excel', 'excel_tab', 'field_size_limit', 'get_dialect', 'list_dialects', 're', 'reader', 'reduce', 'register_dialect', 'unregister_dialect', 'writer']

什么时候也不要忘记这种最佳学习方法。从上面的结果可以看出CSV模块提供的属性和方法。仅仅就读取本例子中的文件:

  1. >>> import csv
  2. >>> csv_reader = csv.reader(open("./marks.csv"))
  3. >>> for row in csv_reader:
  4. ... print row
  5. ...
  6. ['name', 'physics', 'python', 'math', 'english']
  7. ['Google', '100', '100', '25', '12']
  8. ['Facebook', '45', '54', '44', '88']
  9. ['Twitter', '54', '76', '13', '91']
  10. ['Yahoo', '54', '452', '26', '100']

算是稍有改善。

如果对上面的结果都不满意的话,那么看看Pandas的效果:

  1. >>> import pandas as pd
  2. >>> marks = pd.read_csv("./marks.csv")
  3. >>> marks
  4. name physics python math english
  5. 0 Google 100 100 25 12
  6. 1 Facebook 45 54 44 88
  7. 2 Twitter 54 76 13 91
  8. 3 Yahoo 54 452 26 100

看了这样的结果,你还不感到惊讶吗?你还不喜欢Pandas吗?这是多么精妙的显示,它就是一个DataFrame数据。

还有另外一种方法:

  1. >>> pd.read_table("./marks.csv", sep=",")
  2. name physics python math english
  3. 0 Google 100 100 25 12
  4. 1 Facebook 45 54 44 88
  5. 2 Twitter 54 76 13 91
  6. 3 Yahoo 54 452 26 100

如果你有足够的好奇心来研究这个名叫DataFrame的对象,可以这样:

  1. >>> dir(marks)
  2. ['T', '_AXIS_ALIASES', '_AXIS_NAMES', '_AXIS_NUMBERS', '__add__', '__and__', '__array__', '__array_wrap__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__div__', '__doc__', '__eq__', '__floordiv__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', '__getstate__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__neg__', '__new__', '__nonzero__', '__or__', '__pow__', '__radd__', '__rdiv__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rmul__', '__rpow__', '__rsub__', '__rtruediv__', '__setattr__', '__setitem__', '__setstate__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__weakref__', '__xor__', '_agg_by_level', '_align_frame', '_align_series', '_apply_broadcast', '_apply_raw', '_apply_standard', '_auto_consolidate', '_bar_plot', '_boolean_set', '_box_item_values', '_clear_item_cache', '_combine_const', '_combine_frame', '_combine_match_columns', '_combine_match_index', '_combine_series', '_combine_series_infer', '_compare_frame', '_consolidate_inplace', '_constructor', '_count_level', '_cov_helper', '_data', '_default_stat_axis', '_expand_axes', '_from_axes', '_get_agg_axis', '_get_axis', '_get_axis_name', '_get_axis_number', '_get_item_cache', '_get_numeric_data', '_getitem_array', '_getitem_multilevel', '_helper_csvexcel', '_het_axis', '_indexed_same', '_init_dict', '_init_mgr', '_init_ndarray', '_is_mixed_type', '_item_cache', '_ix', '_join_compat', '_reduce', '_reindex_axis', '_reindex_columns', '_reindex_index', '_reindex_with_indexers', '_rename_columns_inplace', '_rename_index_inplace', '_sanitize_column', '_series', '_set_axis', '_set_item', '_set_item_multiple', '_shift_indexer', '_slice', '_unpickle_frame_compat', '_unpickle_matrix_compat', '_verbose_info', '_wrap_array', 'abs', 'add', 'add_prefix', 'add_suffix', 'align', 'append', 'apply', 'applymap', 'as_matrix', 'asfreq', 'astype', 'axes', 'boxplot', 'clip', 'clip_lower', 'clip_upper', 'columns', 'combine', 'combineAdd', 'combineMult', 'combine_first', 'consolidate', 'convert_objects', 'copy', 'corr', 'corrwith', 'count', 'cov', 'cummax', 'cummin', 'cumprod', 'cumsum', 'delevel', 'describe', 'diff', 'div', 'dot', 'drop', 'drop_duplicates', 'dropna', 'dtypes', 'duplicated', 'fillna', 'filter', 'first_valid_index', 'from_csv', 'from_dict', 'from_items', 'from_records', 'get', 'get_dtype_counts', 'get_value', 'groupby', 'head', 'hist', 'icol', 'idxmax', 'idxmin', 'iget_value', 'index', 'info', 'insert', 'irow', 'iteritems', 'iterkv', 'iterrows', 'ix', 'join', 'last_valid_index', 'load', 'lookup', 'mad', 'max', 'mean', 'median', 'merge', 'min', 'mul', 'ndim', 'pivot', 'pivot_table', 'plot', 'pop', 'prod', 'product', 'quantile', 'radd', 'rank', 'rdiv', 'reindex', 'reindex_axis', 'reindex_like', 'rename', 'rename_axis', 'reorder_levels', 'reset_index', 'rmul', 'rsub', 'save', 'select', 'set_index', 'set_value', 'shape', 'shift', 'skew', 'sort', 'sort_index', 'sortlevel', 'stack', 'std', 'sub', 'sum', 'swaplevel', 'tail', 'take', 'to_csv', 'to_dict', 'to_excel', 'to_html', 'to_panel', 'to_records', 'to_sparse', 'to_string', 'to_wide', 'transpose', 'truncate', 'unstack', 'values', 'var', 'xs']

一个一个浏览一下,通过名字可以知道那个方法或者属性的大概,然后就可以根据你自己的喜好和需要,试一试:

  1. >>> marks.index
  2. Int64Index([0, 1, 2, 3], dtype=int64)
  3. >>> marks.columns
  4. Index([name, physics, python, math, english], dtype=object)
  5. >>> marks['name'][1]
  6. 'Facebook'

这几个是让你回忆一下前面的。从DataFrame对象的属性和方法中找一个,再尝试:

  1. >>> marks.sort(column="python")
  2. name physics python math english
  3. 1 Facebook 45 54 44 88
  4. 2 Twitter 54 76 13 91
  5. 0 Google 100 100 25 12
  6. 3 Yahoo 54 452 26 100

按照竖列“python”的值排队,结果也是很让人满意的。下面几个操作,也是常用到的,并且秉承了Python的一贯方法:

  1. >>> marks[:1]
  2. name physics python math english
  3. 0 Google 100 100 25 12
  4. >>> marks[1:2]
  5. name physics python math english
  6. 1 Facebook 45 54 44 88
  7. >>> marks["physics"]
  8. 0 100
  9. 1 45
  10. 2 54
  11. 3 54
  12. Name: physics

可以说,当你已经掌握了通过dir()和help()查看对象的方法和属性时,就已经掌握了Pandas的用法,其实何止Pandas,其他对象都是如此。

2.读取其他格式数据

CSV是常用来存储数据的格式之一,此外常用的还有MS Excel格式的文件,以及JSON和XML格式的数据等,它们都可以使用Pandas来轻易读取。

在下面的结果中寻觅一下,有没有跟Excel有关的方法。

  1. >>> dir(pd)
  2. ['DataFrame', 'DataMatrix', 'DateOffset', 'DateRange', 'ExcelFile', 'ExcelWriter', 'Factor', 'HDFStore', 'Index', 'Int64Index', 'MultiIndex', 'Panel', 'Series', 'SparseArray', 'SparseDataFrame', 'SparseList', 'SparsePanel', 'SparseSeries', 'SparseTimeSeries', 'TimeSeries', 'WidePanel', '__builtins__', '__doc__', '__docformat__', '__file__', '__name__', '__package__', '__path__', '__version__', '_engines', '_sparse', '_tseries', 'concat', 'core', 'crosstab', 'datetime', 'datetools', 'debug', 'ewma', 'ewmcorr', 'ewmcov', 'ewmstd', 'ewmvar', 'ewmvol', 'fama_macbeth', 'groupby', 'info', 'io', 'isnull', 'lib', 'load', 'merge', 'notnull', 'np', 'ols', 'pivot', 'pivot_table', 'read_clipboard', 'read_csv', 'read_table', 'reset_printoptions', 'rolling_apply', 'rolling_corr', 'rolling_corr_pairwise', 'rolling_count', 'rolling_cov', 'rolling_kurt', 'rolling_max', 'rolling_mean', 'rolling_median', 'rolling_min', 'rolling_quantile', 'rolling_skew', 'rolling_std', 'rolling_sum', 'rolling_var', 'save', 'set_eng_float_format', 'set_printoptions', 'sparse', 'stats', 'tools', 'util', 'value_range', 'version']

虽然没有类似read_csv()的方法,但是有ExcelFile类,于是乎:

  1. >>> xls = pd.ExcelFile("./marks.xlsx")
  2. Traceback (most recent call last):
  3. File "<stdin>", line 1, in <module>
  4. File "/usr/lib/pymodules/python2.7/pandas/io/parsers.py", line 575, in __init__
  5. from openpyxl import load_workbook
  6. ImportError: No module named openpyxl

我这里少了一个模块,看报错提示,用pip安装openpyxl模块:sudo pip install openpyxl。继续:

  1. >>> xls = pd.ExcelFile("./marks.xlsx")
  2. >>> dir(xls)
  3. ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_parse_xls', '_parse_xlsx', 'book', 'parse', 'path', 'sheet_names', 'use_xlsx']
  4. >>> xls.sheet_names
  5. ['Sheet1', 'Sheet2', 'Sheet3']
  6. >>> sheet1 = xls.parse("Sheet1")
  7. >>> sheet1
  8. 0 1 2 3 4
  9. 0 5 100 100 25 12
  10. 1 6 45 54 44 88
  11. 2 7 54 76 13 91
  12. 3 8 54 452 26 100

结果中,columns的名字与前面CSV结果不一样,数据部分是同样的结果。从结果中可以看到,sheet1也是一个DataFrame对象。

对于单个的DataFrame对象,如何通过属性和方法进行操作?如果读者理解了本书从一开始就贯穿进来的思想——利用dir()和help()或者到官方网站看文档——此时就能比较轻松地进行各种操作了。

从数据库中查询出来的数据,也可以按照Series或者DataFrame类型数据进行组织,然后就可以对其操作。

9.2.3 处理股票数据

某段时间某国股市很火爆,不少专家在分析股市火爆的各种原因,不久,该国的股票又开始狂跌,各种各样的救市政策仅仅是螳臂当车罢了。不过,我还是很淡定的,因为没钱。

但是,为了体现本人也是与时俱进的,就以股票数据为例子,来简要说明Pandas和其他模块在处理数据上的应用。

1.下载YAHOO上的数据

或许你好奇,为什么要下载YAHOO上的股票数据呢?国内网站上不是也有吗?有,但我不喜欢用。我喜欢YAHOO,因为它曾经吸引我,注意我说的是www.yahoo.com。

9.2 Pandas - 图17

虽然YAHOO的身影渐行渐远,但它终究是值得记忆的。所以,我要演示如何下载YAHOO财经栏目中的股票数据。

  1. In [1]: import pandas
  2. In [2]: import pandas.io.data
  3.  
  4. In [3]: sym = "BABA"
  5.  
  6. In [4]: finace = pandas.io.data.DataReader(sym, "yahoo", start="2014/11/11")
  7. In [5]: print finace.tail(3)
  8. Open High Low Close Volume Adj Close
  9. Date
  10. 2015-06-17 86.580002 87.800003 86.480003 86.800003 10206100 86.800003
  11. 2015-06-18 86.970001 87.589996 86.320000 86.750000 11652600 86.750000
  12. 2015-06-19 86.510002 86.599998 85.169998 85.739998 10207100 85.739998

下载了阿里巴巴的股票数据(自2014年11月11日以来),并且打印最后三条。

2.画图

已经得到了一个DataFrame对象,就是前面已经下载并用finace变量引用的对象。

  1. In[6]: import matplotlib.pyplot as plt
  2. In [7]: plt.plot(finace.index, finace["Open"])
  3. Out[]: [<matplotlib.lines.Line2D at 0xa88e5cc>]
  4.  
  5. In [8]: plt.show()

结果如图9-4所示。

9.2 Pandas - 图18图9-4 阿里巴巴股票数据图

从图9-4中可以看出阿里巴巴的股票自从2014年11月11日到2015年6月19日的股票开盘价的变化。

上面指令中的import matplotlib.pyplot as plt是此前没有看到的。matplotlib模块是Python中绘制二维图形的模块,是最好的模块。可惜matplotlib的发明者——John Hunter已经于2012年8月28日因病医治无效英年早逝,这真是天妒英才呀。为了缅怀他,请读者访问官方网站:matplotlib.org(http://matplotlib.org/),并认真学习这个模块的使用。

经过上面的操作,读者可以用dir()这个以前常用的法宝来查看finace所引用的DataFrame对象的方法和属性等。只要运用dir+help就能够对这个对象进行操作,也就是能够对该股票数据进行各种操作。

再次声明,本书仅仅是稍微演示一下相关操作,如果读者要深入研习,恭请寻找相关的专业书籍资料阅读学习。