关于开发工具的选择,经过一些对比研究后,决定使用Anaconda + Pycharm,用anaconda集成的ipython做工作台,做一些分析和小段程序调试的工作,用Pycharm写相应脚本和程序包的开发。这两个工具都是跨平台的,也都有免费版本。
Anaconda是一个用于科学计算的Python发行版,支持 Linux, Mac, Windows系统,提供了包管理与环境管理的功能,可以很方便地解决多版本python并存、切换以及各种第三方包安装问题。Anaconda利用工具/命令conda
来进行package和environment的管理,并且已经包含了Python和相关的配套工具。Anaconda是一个打包的集合,里面预装好了conda、某个版本的python、众多packages、科学计算工具等等。
conda
可以理解为一个工具,也是一个可执行命令,其核心功能是包管理与环境管理。包管理与pip的使用类似,环境管理则允许用户方便地安装不同版本的python并可以快速切换。conda将几乎所有的工具、第三方包都当做package对待,甚至包括python和conda自身!因此,conda打破了包管理与环境管理的约束,能非常方便地安装各种版本python、各种package并方便地切换。
安装后如下所示:
Pycharm是一个跨平台的Python开发工具,是JetBrains公司的产品。其特征包括:自动代码完成、集成的Python调试器、括号自动匹配、代码折叠。Pycharm支持Windows、MacOS以及Linux等系统,而且可以远程开发、调试、运行程序。
IPython 是 Python 科学计算标准工具集的组成部分,是一个增强的 Python Shell,目的是提高编写、测试、调试 Python 代码的速度。主要用于交互式数据处理和利用matplotlib 对数据进行可视化处理。
Matplotlib 是最流行的用于绘制数据图表的 Python 库。
Pandas 主要提供快速便捷地处理结构化数据的大量数据结构和函数。
- 快速高效的多维数组对象 ndarray;
- 直接对数组执行数学运算及对数组执行元素级计算的函数;
- 线性代数运算、随机数生成;
- 将 C、C++、Fortran 代码集成到 Python 的工具等。
SciPy 是一组专门解决科学计算中各种标准问题域的包的集合。主要包括以下包:
- scipy.integrate: 数值积分例程和微分方程求解器;
- scipy.linalg: 扩展了由 numpy.linalg 提供的线性代数例程和矩阵分解功能;
- scipy.optimize: 函数优化器以及根查找算法;
- scipy.signal: 信号处理工具;
- scipy.sparse: 稀疏矩阵和稀疏线性系统求解器;
- scipy.special: SPECFUN(这是一个实现了许多常用数学函数的 Fortran 库)的包装器。
- scipy.stats: 标准连续和离散概率分布、各种统计检验方法和更好的描述统计法;
- scipy.weave: 利用内联 C++ 代码加速数组计算的工具。
IPython中使用Magic Function %pylab
https://*.com/questions/20961287/what-is-pylab/24338062
%pylab
is shortcut for typing all of below commands which in essence adds numpy and matplotlib in to your session. This was added in IPython as a transition tool and current recommendation is that you should not use it. The core reason is that below sets of commands imports too much in the global namespace and also it doesn't allow you to change the mode for matplotlib from UI to QT or something else. You can get history and reasoning behind this at http://nbviewer.ipython.org/github/Carreau/posts/blob/master/10-No-PyLab-Thanks.ipynb?create=1.
This is what %pylab
does:
import numpy import matplotlib from matplotlib import pylab, mlab, pyplot np = numpy plt = pyplot from IPython.core.pylabtools import figsize, getfigs from pylab import * from numpy import *
This is what I use instead at the start of my notebook:
import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline
inline
lets you plot figures inline, instead of in a new window or shell, to see the effect check without inline. inline
only works in the notebook and qtconsole.
使用plot(arange(10))来验证。
使用%pylab后, 不需要调用plt.show()也可以把图形画出来。这是因为当交互式执行的时候,主循环是交互式后端,因此不需要通过show()来加载个事件主循环;当代码以独立进程执行的时候,因为不存在主循环,因此不会响应任何GUI事件,此时需要调用plt.show()。
2017/10/30
https://github.com/wesm/pydata-book 下载利用python进行数据分析的相关数据和源码。
将 JSON 数据转换成 Python 字典
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
import json #加载json模块 path='D:/python_study/pydata-book-2nd-edition/datasets/bitly_usagov/example.txt' records=[json.loads(line) for line in open(path)] #JSON解码会根据提供的数据创建dicts或lists。 如果你想要创建其他类型的对象,可以给json.loads()传递参数 records[:1] #这里records是list,:1表示index小与1的元素组成的子list,这个子list中只有一个元素,也即records[0]
将 records 转换成 DataFrame,DataFrame 是 Pandas 里最重要的数据结构,它可以将数据以表格的形式表示;然后用 value_counts() 方法汇总
from pandas import DataFrame, Series import pandas as pd; import numpy as np frame=DataFrame(records) #DataFrame翻译为数据框, 简单说就是表格. 这里records是list of dectionary,生成的DataFrame的index是list的index(0,1,2...), #DataFrame的column就是dictionary的keys frame['tz'].value_counts()[:10] #frame['tz']选取tz列, frame[1]选取第一行,frame[['tz','a']选取tz和a两列, frame.loc[:10,['tz','a']]取前十行的两列 #frame['tz']的类型是Series, value_counts返回的是该Series对象中独一无二的元素的个数,默认次序按照出现的频率由高到低排序
为了数据的完整,可以给结果中缺失的时区添加一个值(这里用Missing表示),而每条时区内容里缺失的值也需要添加一个未知的值(这里用Unknown表示)
clean_tz=frame['tz'].fillna('Missing') #Series的fillna() 函数 填充缺失值。 pandas使用浮点值NaN表示浮点和非浮点数组里的缺失数据。 #使用isnull()和notnull()函数来判断缺失情况 clean_tz[clean_tz=='']='Unknown' #空字符串''则可以通过布尔型数组索引加以替换,numpy中的布尔型索引用来索引True值对应的行 clean_tz.value_counts()[:10] tz_counts=clean_tz.value_counts() #value_counts()的返回值依旧是Series 类型 tz_counts[:10] tz_counts[:10].plot(kind='barh',rot=0) #Series.plot(): Make plots of Series using matplotlib的pyplot. #pylab is a convenience module that bulk imports matplotlib.pyplot (for plotting) and numpy (for mathematics and #working with arrays) in a single name space. Although many examples use pylab, it is no longer recommended. """kind : str ‘line’ : line plot (default) ‘bar’ : vertical bar plot ‘barh’ : horizontal bar plot ‘hist’ : histogram ‘box’ : boxplot ‘kde’ : Kernel Density Estimation plot ‘density’ : same as ‘kde’ ‘area’ : area plot ‘pie’ : pie plot"""
cframe=frame[frame.a.notnull()] #这里还是使用bool型索引,过滤了那些a值为空的数据 operating_system=np.where(cframe['a'].str.contains('Windows'),'Windows','Not Windows') #numpy中的where函数返回值是numpy.ndarry,参数1是布尔型array, #真值返回参数2,假值返回参数3 by_tz_os=cframe.groupby(['tz', operating_system]) #类型为pandas.core.groupby.DataFrameGroupBy, 这是Pandas的GroupBy对象 agg_counts=by_tz_os.size().unstack().fillna(0) #GroupBy对象的size()函数返回一个Series对象,对象内容是GroupBy的数据和对应的数据条数 #Series对象的unstack函数返回一个DataFrame对象,是将多个Index的Series转化为DataFrame agg_counts[:10] indexer=agg_counts.sum(1).argsort() #DataFrame的sum()函数-- Return the sum of the values for the requested axis, 返回值为Series #argsort()函数按值排序,返回一个Series,这个Series的值是次序 count_subset=agg_counts.take(indexer)[-10:] #DataFrame按照indexer重排次序,然后取出最后十个 count_subset.plot(kind='barh',stacked=True) #画图, stacked 表示堆积图
DataFrame详细讲解
DataFrame
(data=None, index=None, columns=None, dtype=None, copy=False)
DataFrame accepts many different kinds of input:
- Dict of 1D ndarrays, lists, dicts, or Series
- 2-D numpy.ndarray
- Structured or record ndarray
- A Series
- Another DataFrame
Along with the data, you can optionally pass index (row labels) and columns (column labels) arguments. If you pass an index and / or columns, you are guaranteeing the index and / or columns of the resulting DataFrame. Thus, a dict of Series plus a specific index will discard all data not matching up to the passed index.
If axis labels are not passed, they will be constructed from the input data based on common sense rules.
Ipython几个常用命令:
Tab键 -- 自动补全
上下箭头键 -- 历史命令 如果某个命令需要摁很多次上箭头键才能找到,此时只需要输入那条命令的前几个字母然后再摁上箭头键,即可只筛选符合前几个字母的命令
%run命令 -- 执行一个外部的 .py 文件
变量后添加一个问号 -- 查看一个变量或对象相关的通用信息的时候,在此
函数名后添加两个问号(??) -- 可以显示该函数相关的源代码
Ctrl+F 光标前移1个字符 (windows下不工作)
Ctrl+B 光标后移1个字符
Ctrl+A 光标移至行首 (windows下不工作)
Ctrl+E 光标移至行尾
Ctrl+U 删除此行光标之前的所有内容
Ctrl+K 删除此行光标之后的所有内容
Ctrl+L 清屏
%debug -- 命令会启动调试器并自动跳转到“事发地点”
ndarry
是一个多维的数组对象, 其中所有元素的类型必须相同
import numpy as np data1=[1,2,3,4,5,6] #Python list [1, 2, 3, 4, 5, 6], 类型为"list" arr1=np.array(data1) #从python list创建numpy.ndarray: array([1, 2, 3, 4, 5, 6]), 类型为"numpy.ndarray" arr2=np.zeros(5) #创建全0 ndarry arr3=np.ones(6) #创建全1 ndarry arr4=np.empty(5) #创建没有具体值的ndarray,未初始化内容 arr5=np.arange(7) #array([0, 1, 2, 3, 4, 5, 6]), arange是Python中range的数组版 arr6=np.array([1,2,3],dtype=np.float64) #创建array是指定数据类型, arr6.dtype可以查看ndarray中的数据类型 arr=np.array(['1.12','2.21','1.78']) #类型为字符串的ndarray arr.astype(float) #强制类型转换为float类型,astype会创建一个新的数组,所以不会影响原数组 arr7=np.array([1,3,4,5]) arr7+1 #结果为array([2, 4, 5, 6]),ndarray 数组可以让我们不需要使用循环就可以对列表里的元素执行操作, 比如加减乘除之类的操作会对数组里每一个元素进行。
ndarray索引和切片
import numpy as np arr=np.array([0,1,2,3,4,5,6,7,8,9]) arr[5] #一维数组index array([2, 3, 4, 5]) #一维数组切片 arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]]) arr2d[1] #二维数组index arr2d[1][0] #二维数组index arr2d[0:2] #二维数组切片 #布尔值索引指的是一个由布尔值组成的数组可以作为一个数组的索引,返回的数据为True值对应位置的值 names=np.array(['Lucy','Lucy','Peter','Job']) data=np.random.randn(4,3) #np.random.randn生成标准正态分布随机数,而 np.random.rand生成的则位于[0, 1)的随机数 names=='Lucy' #结果为 array([ True, True, False, False], dtype=bool) data[names=='Lucy'] #返回结果为dada数组前两行 #花式索引指的是用整数数组进行索引 arr2d[[0,1]] #结果为array([[1, 2, 3], # [4, 5, 6]])
ndarray矢量计算
矢量化指的是用数组表达式代替循环来操作数组里的每个元素。
NumPy提供的通用函数(既ufunc函数)是一种对ndarray中的数据进行元素级别运算的函数。ufunc是universal function的缩写。NumPy内置的许多ufunc函数都是在C语言级别实现的,因此它们的计算速度非常快。
import numpy as np arr=np.array([0,1,2,3,4,5,6,7,8,9]) np.square(arr) #平方, 结果为array([0, 1, 4, 9, 16, 25, 36, 49, 64, 81]) arr2=np.array([1.1, 2.2, 3.3, 4.4, 5.5, 6.6]) np.rint(arr2) #四舍五入, 结果为array([ 1., 2., 3., 4., 6., 7.]) arr3=np.array([9, 12, 10, 3, 2, 1, 91, 4]) arr4=np.array([1, 2, 3, 4, 5, 6, 7, 8]) np.add(arr3, arr4) #加法, 注意arr3和arr4必须拥有相同的元素个数 np.maximum(arr3, arr4) #取大值,array([ 9, 12, 10, 4, 5, 6, 91, 8]) #numpy.where函数是三元表达式 x if condition else y 的矢量化版本 np.where(arr3>arr4, arr3, arr4) #结果为array([ 9, 12, 10, 4, 5, 6, 91, 8]), 等同于maximum np.where(arr3<10, -1, arr4) #第二个参数和第三个参数可以是标量值,结果为array([-1, 2, 3, -1, -1, -1, 7, -1]) np.sum(arr3) #np.sum函数可以对数组里的元素求和 arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]]) np.sum(arr2d) #也可以对多维数组求和 #二维数组是有横轴和竖轴两个方向的,所以sum函数对于二维数组还可以按照方向进行求和 np.sum(arr2d, axis=0) #同列的各行相加,结果为array([12, 15, 18]) np.sum(arr2d,axis=1) #同行的各列相加,结果为array([ 6, 15, 24])
Series是一个 一维数组对象 ,类似于 NumPy 的一维 array。它除了包含一组数据还包含一组索引,所以可以把它理解为一组带索引的数组。
from pandas import Series, DataFrame import pandas as pd #构建Series对象 obj=Series([2,3,4,-5]) #从Python一维数组构建Series dic={'a':1, 'b':2, 'c':3, 'd':4} obj1=Series(dic) #从Python字典构建Series obj2=Series([2,3,4,-1],index=['a','b','c','d']) #使用index参数显式指定索引 #Series对象的index和值 obj2['a'] obj2[['a','b']] #利用索引读取Series中元素的值 obj2.index #显示Series的index,结果为Index([u'a', u'b', u'c', u'd'], dtype='object'), 类型为pandas.indexes.base.Index obj2.valeus #显示Series中的值,结果为array([ 2, 3, 4, -1], dtype=int64, 类型为np.ndarray #Series对象的运算 obj*2 #索引不变,value变 obj[obj<3] #过滤后只剩下value小于3的那些index和value obj[obj>3] #过滤后只剩下value小于3的那些index和value
DataFrame 是一个表格型的数据结构。它提供有序的列和不同类型的列值。
data={'name':['Carl', 'Peter', 'Lucy', 'Job'], 'age':[30, 34, 20, 36], 'gender':['m', 'm', 'f', 'm']} frame=pd.DataFrame(data) #从字典构建 DataFrame 对象, 结果如下所示
age gender name
0 30 m Carl
1 34 m Peter
2 20 f Lucy
3 36 m Job
#DataFrame 默认根据列名首字母顺序进行排序,想要指定列的顺序德华传入一个列名的字典即可: DataFrame(data, columns=['name', 'age', 'gender'])
name age gender
0 Carl 30 m
1 Peter 34 m
2 Lucy 20 f
3 Job 36 m
#如果传入的列名找不到,它不会报错,而是产生一列 NA 值: frame2=DataFrame(data, columns=['name', 'age', 'gender', 'weight'])
name age gender weight
0 Carl 30 m NaN
1 Peter 34 m NaN
2 Lucy 20 f NaN
3 Job 36 m NaN
#DataFrame 不仅可以以字典索引的方式获取数据,还可以以属性的方法获取,例如: frame2.name frame2['name']
Out[82]:
0 Carl
1 Peter
2 Lucy
3 Job
Name: name, dtype: object
#修改列的值 frame2['weight']=60 frame2
Out[86]:
name age gender weight
0 Carl 30 m 60
1 Peter 34 m 60
2 Lucy 20 f 60
3 Job 36 m 60
#删除一列 del frame2['weight'] frame2
Out[88]:
name age gender
0 Carl 30 m
1 Peter 34 m
2 Lucy 20 f
3 Job 36 m
reindex() 方法:重新索引
Series重新索引
from pandas import Series, DataFrame import pandas as pd obj1=Series([1.2, 2.3, 3.1, 5.2], index=['c', 'e', 'a', 'b']) obj2=obj1.reindex(['a', 'b', 'c', 'd', 'e', 'f']) #按新的index排序 obj3=obj1.reindex(['a', 'b', 'c', 'd', 'e', 'f'], fill_value=0) #按新的index排序并且对NaN值填充默认值 #用前一个或后一个相邻值填充NaN值 obj4=obj1.reindex(['a', 'b', 'c', 'd', 'e', 'f'], method='ffill') #出错,当带有method参数时原来index要是排好序的 obj4=obj1.sort_index().reindex(['a', 'b', 'c', 'd', 'e', 'f'], method='ffill') #需要先sort_index()一下 obj5=obj1.sort_index().reindex(['a', 'b', 'c', 'd', 'e', 'f'], method='bfill') #
DataFrame重新索引, 删除行和列
import numpy as np frame1=DataFrame(np.arange(9).reshape((3,3)), index=['a','b','c'], columns=['Ohio', 'Texas', 'California']) frame1.reindex(['a', 'b', 'c', 'd']) #默认按行reindex frame1.reindex(columns=['Texas', 'Utah', 'California']) #指定columns按列reindex frame1.reindex(index=['a', 'b', 'c', 'd'], columns=['Texas', 'Utah', 'California'], method='ffill') #按行和列reindex, 注意此处的ffill只在列内从前一个copy作为填充值 frame1.drop(['a']) #默认删除行 frame1.drop(['Texas'], axis=1) #删除列
Series索引,选取,过滤
import numpy as np import pandas as pd from pandas import Series, DataFrame obj1=Series(np.arange(4.), index=['a', 'b', 'c', 'd']) obj1['b'] #用index来索引 obj1[1] #即使没有建立数字索引,还是可以像数组一样用数字下标来引用 obj1[['b', 'c']] # obj1[2:4] obj1[b:d]
DataFrame索引,选取,过滤
In [1]: import numpy as np In [2]: import pandas as pd In [3]: from pandas import Series, DataFrame In [4]: data1=DataFrame(np.arange(16).reshape((4,4)), index=['Ohio','Colorado','Utah','New York'], columns=['one','two','three','four']) In [5]: data1 Out[5]: one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 In [6]: data1['two'] #选取一列 Out[6]: Ohio 1 Colorado 5 Utah 9 New York 13 Name: two, dtype: int32 In [7]: data1[['three','one']] #选取多列 Out[7]: three one Ohio 2 0 Colorado 6 4 Utah 10 8 New York 14 12 In [8]: data1[:2] #切片选取行 Out[8]: one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 In [9]: data1[0:2] #切片选取行 Out[9]: one two three four Ohio 0 1 2 3 Colorado 4 5 6 7 In [11]: data1[data1['three']>5] #按条件选取 Out[11]: one two three four Colorado 4 5 6 7 Utah 8 9 10 11 New York 12 13 14 15 In [13]: data1[data1<10] #按条件过滤, 不符合条件的赋值为NaN Out[13]: one two three four Ohio 0.0 1.0 2.0 3.0 Colorado 4.0 5.0 6.0 7.0 Utah 8.0 9.0 NaN NaN New York NaN NaN NaN NaN In [15]: data1.ix['New York', ['two', 'three']] #选取一行的某些列,结构是那些列的值,结果为Series,index为列名 Out[15]: two 13 three 14 Name: New York, dtype: int32 In [17]: data1.ix[2] #选取第二行的所有列,结果是Series,index为列名 Out[17]: one 8 two 9 three 10 four 11 Name: Utah, dtype: int32 In [18]: data1.ix[:'New York', 'two'] #选取多行的某列, 结果为Series,index为行名 Out[18]: Ohio 1 Colorado 5 Utah 9 New York 13 Name: two, dtype: int32 In [20]: data1.ix[data1.three<5, :3] #第一个条件用列值过滤,第二个条件用列切片 Out[20]: one two three Ohio 0 1 2
算术运算和数据对齐
#将2个Series对象相加时,具有重叠索引的索引值会相加处理;不重叠的索引则取并集,值为 NA s1=Series([1,2,3,4], index=['a','b','c','d']) s2=Series([10,20,30,40,50], index=['x','b','c','y','z']) s1+s2 ''' Out[26]: a NaN b 22.0 c 33.0 d NaN x NaN y NaN z NaN dtype: float64 ''' #DataFrame相加时,对齐操作会同时发生在行和列上,把2个对象相加会得到一个新的对象,其行和列为原来2个对象的行和列的并集 #不重叠的索引会取并集,值为 NA df1=DataFrame(np.arange(9.).reshape((3,3)), columns=list('bcd'), index=['Beijing','Shanghai','Guangzhou']) df1 ''' Out[29]: b c d Beijing 0.0 1.0 2.0 Shanghai 3.0 4.0 5.0 Guangzhou 6.0 7.0 8.0 ''' df2=DataFrame(np.arange(12.).reshape((4,3)), columns=list('cde'), index=['Beijing','Guangzhou','Texas','New York']) df2 ''' Out[31]: c d e Beijing 0.0 1.0 2.0 Guangzhou 3.0 4.0 5.0 Texas 6.0 7.0 8.0 New York 9.0 10.0 11.0 ''' df1+df2 ''' Out[32]: b c d e Beijing NaN 1.0 3.0 NaN Guangzhou NaN 10.0 12.0 NaN New York NaN NaN NaN NaN Shanghai NaN NaN NaN NaN Texas NaN NaN NaN NaN ''' #使用add函数,和加法不一样,将会使得仅在一个df中出现的值出现在结果中 df1.add(df2, fill_value=0) ''' Out[33]: b c d e Beijing 0.0 1.0 3.0 2.0 Guangzhou 6.0 10.0 12.0 5.0 New York NaN 9.0 10.0 11.0 Shanghai 3.0 4.0 5.0 NaN Texas NaN 6.0 7.0 8.0 '''
DataFrame上函数和Lambda表达式应用
f=lambda x:x+1 #lambda表达式f, 将每个元素值加一 f2=lambda x:x.max()-x.min() #lambda表达式f2, 将每列最大值减去最小值 def f3(x): #函数f3, 将每列的最小值和最大值返回 ....: return Series([x.min(), x.max()], index=['min','max']) df1.apply(f) ''' Out[38]: b c d Beijing 1.0 2.0 3.0 Shanghai 4.0 5.0 6.0 Guangzhou 7.0 8.0 9.0 ''' df1.apply(f2) ''' Out[40]: b 6.0 c 6.0 d 6.0 dtype: float64 ''' df1.apply(f3) ''' Out[45]: b c d min 0.0 1.0 2.0 max 6.0 7.0 8.0 '''
Series和DataFrame上的排序
In [1]: import numpy as np In [2]: import pandas as pd In [3]: from pandas import Series, DataFrame obj=Series(range(4), index=['d','a','c','b']) obj.sort_index() #按index值升序排列 obj.sort_index(ascending=False) #按index值降序排列 obj.sort_values() #按value值升序排序 obj.sort_values(ascending=False) #按value值降序排列 obj.rank() #返回一个Sereis,每个index对应着的是值的排名 (排名从1开始) frame=DataFrame(np.arange(8).reshape((2,4)), index=['three','one'], columns=list('dabc')) frame.sort_index() #按列名字排序 frame.sort_index(axis=1) #按行名字排序
Pandas,Series 汇总统计和计算
import pandas as pd import numpy as np from pandas import Series, DataFrame df=DataFrame(np.array([1.4,np.nan,7.5,-4.5,np.nan,np.nan,0.75,-1.3]).reshape(4,2),index=['a','b','c','d'],columns=['one','two']) ''' In [5]: df Out[5]: one two a 1.40 NaN b 7.50 -4.5 c NaN NaN d 0.75 -1.3 ''' df.sum() #默认对列sum(), 返回类型为Series ''' Out[6]: one 9.65 two -5.80 dtype: float64 ''' df.sum(axis=1) #对行sum(), 返回类型为Series ''' Out[7]: a 1.40 b 3.00 c 0.00 d -0.55 dtype: float64 ''' df.idxmax() #返回每列的最大值的index, 结果类型为Series ''' Out[12]: one b two d dtype: object ''' In [13]: df.idxmax(axis=1) #返回每行的最大值的columns , 结果类型为Series ''' Out[13]: a one b one c NaN d one dtype: object ''' df.cumsum() #累计型的求和, 默认行, 也可列df.cumsum(axis=1)。 一个NaN值处的累计值还是NaN ''' Out[17]: one two a 1.40 NaN b 8.90 -4.5 c NaN NaN d 9.65 -5.8 ''' df['one'].unique() #unique() 方法用于返回Series数据里的唯一值,返回结果类型为ndarray df['one'].value_counts() #value_counts() 方法用于统计Series中各值出现的频率 ''' Out[29]: 0.75 1 1.40 1 7.50 1 Name: one, dtype: int64 ''' df.isin([1.4]) #isin() 方法用于判断成员资格, 适用于Series和DataFrame ''' Out[32]: one two a True False b False False c False False d False False ''' df['one'].isin([1.4]) ''' Out[33]: a True b False c False d False Name: one, dtype: bool '''
处理缺失数据
df ''' Out[34]: one two a 1.40 NaN b 7.50 -4.5 c NaN NaN d 0.75 -1.3 ''' df['one'].dropna() #对于一个Series,dropna()函数返回一个包含非空数据和索引值的Series ''' Out[35]: a 1.40 b 7.50 d 0.75 Name: one, dtype: float64 ''' df.dropna() #对于DataFrame,dropna()函数同样会丢掉所有含有空元素的数据 ''' Out[36]: one two b 7.50 -4.5 d 0.75 -1.3 ''' df.dropna(how='all') #可以指定how='all',这表示只有行里的数据全部为空时才丢弃, 如果想以同样的方式按列丢弃,可以传入axis=1 ''' Out[37]: one two a 1.40 NaN b 7.50 -4.5 d 0.75 -1.3 ''' df.fillna(0) #如果不想丢掉缺失的数据而是想用默认值填充这些空洞,可以使用fillna()函数 ''' Out[39]: one two a 1.40 0.0 b 7.50 -4.5 c 0.00 0.0 d 0.75 -1.3 ''' df.fillna({'one':10,'two':20,}) #如果不想只以某个标量填充,可以传入一个字典,对不同的列填充不同的值 ''' Out[47]: one two a 1.40 20.0 b 7.50 -4.5 c 10.00 20.0 d 0.75 -1.3 '''
层次化索引
#多层索引Series obj1=Series(np.random.randn(10), index=[['a','a','a','b','b','b','c','c','d','d'],[1,2,3,1,2,3,1,2,2,3]]) #创建多层索引Series ''' In [83]: obj1 Out[83]: a 1 -2.389511 2 -1.598216 3 -0.742905 b 1 1.179948 2 2.158227 3 0.455422 c 1 0.476948 2 -0.509249 d 2 -0.745915 3 1.197959 dtype: float64 ''' obj1['a'] #使用外层索引 ''' Out[84]: 1 -2.389511 2 -1.598216 3 -0.742905 dtype: float64 ''' In [85]: obj1[:,2] #使用内层索引 ''' Out[85]: a -1.598216 b 2.158227 c -0.509249 d -0.745915 dtype: float64 ''' obj1.unstack(level=-1) #多层索引Series转换为DataFrame,内层索引作columns ''' Out[92]: 1 2 3 a -2.389511 -1.598216 -0.742905 b 1.179948 2.158227 0.455422 c 0.476948 -0.509249 NaN d NaN -0.745915 1.197959 ''' obj1.unstack(level=0) #多层索引Series转换为DataFrame,外层索引作columns Out[93]: a b c d 1 -2.389511 1.179948 0.476948 NaN 2 -1.598216 2.158227 -0.509249 -0.745915 3 -0.742905 0.455422 NaN 1.197959 #创建多层索引DataFrame df=DataFrame(np.random.randint(0, 150, size=(6,3)), columns=['语文','数学','Python'], index=[['Michael',' Michael','Lisa','Lisa','Po','Po'],['期中','期末','期中','期末','期中','期末']]) ''' Out[53]: 语文 数学 Python Michael 期中 21 127 84 期末 147 29 84 Lisa 期中 34 30 64 期末 52 129 62 Po 期中 116 40 12 期末 97 92 52 ''' df.loc['Michael'] #以外层行索引的方式选择数据子集 ''' Out[61]: 语文 数学 Python 期中 21 127 84 期末 147 29 84 ''' df.loc['Michael',['语文']] #以外层行索引加列的方式选择数据子集 ''' Out[60]: 语文 期中 21 期末 147 ''' df.loc['Po','期中'] #外层加内层索引的引用 ''' Out[71]: 语文 116 数学 40 Python 12 Name: (Po, 期中), dtype: int32 ''' df.swaplevel() #swaplevel()函数可以将两个级别的数据进行交换 ''' Out[96]: 语文 数学 Python 期中 Michael 21 127 84 期末 Michael 147 29 84 期中 Lisa 34 30 64 期末 Lisa 52 129 62 期中 Po 116 40 12 期末 Po 97 92 52 ''' df.sortlevel(0,ascending=False) #按第一层index进行排序 ''' Out[97]: 语文 数学 Python Po 期末 97 92 52 期中 116 40 12 Michael 期末 147 29 84 期中 21 127 84 Lisa 期末 52 129 62 期中 34 30 64 ''' df.sortlevel(1) #按第二层index进行排序 ''' Out[98]: 语文 数学 Python Lisa 期中 34 30 64 Michael 期中 21 127 84 Po 期中 116 40 12 Lisa 期末 52 129 62 Michael 期末 147 29 84 Po 期末 97 92 52 '''
数据合并
df1=DataFrame({'name':['Carl','Lucy','a','b','c'], 'data1':range(5)}) ''' In [105]: df1 Out[105]: data1 name 0 0 Carl 1 1 Lucy 2 2 a 3 3 b 4 4 c ''' df2=DataFrame({'name':['Carl','Lucy','x','y','z'], 'data2':range(5)}) '''In [113]: df2 Out[113]: data2 name 0 0 Carl 1 1 Lucy 2 2 x 3 3 y 4 4 z ''' pd.merge(df1, df2, on='name') #内连接, merge以列名作为连接键 ''' Out[114]: data1 name data2 0 0 Carl 0 1 1 Lucy 1 ''' pd.merge(df1, df2, on='name',how='left') #左连接 ''' Out[115]: data1 name data2 0 0 Carl 0.0 1 1 Lucy 1.0 2 2 a NaN 3 3 b NaN 4 4 c NaN ''' pd.merge(df1, df2, on='name',how='outer') #外链接 ''' Out[116]: data1 name data2 0 0.0 Carl 0.0 1 1.0 Lucy 1.0 2 2.0 a NaN 3 3.0 b NaN 4 4.0 c NaN 5 NaN x 2.0 6 NaN y 3.0 7 NaN z 4.0 ''' df1.join(df2,lsuffix='_caller', rsuffix='_other') #join以索引作为连接键 pd.concat([df1,df2]) #轴向连接,即沿着一条轴将多个对象堆叠到一起 ''' Out[138]: data1 data2 name 0 0.0 NaN Carl 1 1.0 NaN Lucy 2 2.0 NaN a 3 3.0 NaN b 4 4.0 NaN c 0 NaN 0.0 Carl 1 NaN 1.0 Lucy 2 NaN 2.0 x 3 NaN 3.0 y 4 NaN 4.0 z ''' pd.concat([df1,df2], axis=1) #行向连接,即沿着一条轴将多个对象堆叠到一起 ''' Out[139]: data1 name data2 name 0 0 Carl 0 Carl 1 1 Lucy 1 Lucy 2 2 a 2 x 3 3 b 3 y 4 4 c 4 z ''' df1.combine_first(df2) #合并重叠数据 ''' Out[144]: data1 data2 name 0 0 0.0 Carl 1 1 1.0 Lucy 2 2 2.0 a 3 3 3.0 b 4 4 4.0 c '''
数据重塑/轴向旋转
- stack: 将数据的列“旋转”为行。
- unstack:将数据的行“旋转”为列。
In [148]: df1 ''' Out[148]: data1 name 0 0 Carl 1 1 Lucy 2 2 a 3 3 b 4 4 c ''' In [149]: df1.unstack() #结果为Series,将列转换为外层索引,原来索引作为内层索引 ''' Out[149]: data1 0 0 1 1 2 2 3 3 4 4 name 0 Carl 1 Lucy 2 a 3 b 4 c dtype: object ''' In [150]: df1.stack() #结果为Series, 将列转换为内层索引,保留原来索引作为外层索引 ''' Out[150]: 0 data1 0 name Carl 1 data1 1 name Lucy 2 data1 2 name a 3 data1 3 name b 4 data1 4 name c dtype: object '''
ldata=DataFrame({'date':['1989-06-01','1989-06-01','1989-06-01','1999-07-02','1999-07-02','1999-07-02','2009-08-21','2009-08-21','2009-08-21'], 'item':['Carl','Lucy','Peter','Carl','Lucy','Peter','Carl','Lucy','Peter'],'value':[60,60,61,74,68,76,89,94,95]}) ldata #长格式数据 ''' Out[155]: date item value 0 1989-06-01 Carl 60 1 1989-06-01 Lucy 60 2 1989-06-01 Peter 61 3 1999-07-02 Carl 74 4 1999-07-02 Lucy 68 5 1999-07-02 Peter 76 6 2009-08-21 Carl 89 7 2009-08-21 Lucy 94 8 2009-08-21 Peter 95 ''' ldata.pivot('date','item','value') #DataFrame.pivot(index=None, columns=None, values=None) #Reshape data (produce a “pivot” table) based on column values. #Uses unique values from index / columns to form axes of the resulting DataFrame. ''' Out[156]: item Carl Lucy Peter date 1989-06-01 60 60 61 1999-07-02 74 68 76 2009-08-21 89 94 95 '''
2017/11/06
数据转换指的是对数据的过滤、清理以及其他的转换操作
data=DataFrame({'k1':['a']*3+['b']*4, 'k2':[1,1,2,3,3,3,4]}) ''' In [158]: data Out[158]: k1 k2 0 a 1 1 a 1 2 a 2 3 b 3 4 b 3 5 b 3 6 b 4 ''' data.duplicated() # 检测各行是否重复(默认判断所有列),第一次出现的时候不叫重复,以后再出现叫做重复 ''' Out[159]: 0 False 1 True 2 False 3 False 4 True 5 True 6 False dtype: bool ''' data.drop_duplicates() #丢弃重复行(默认判断所有列) ''' Out[160]: k1 k2 0 a 1 2 a 2 3 b 3 6 b 4 ''' data.duplicated(['k1']) #传入列参数,以参数列来判断是否重复 ''' Out[162]: 0 False 1 True 2 True 3 False 4 True 5 True 6 True dtype: bool ''' data.duplicated(keep='last') #使用keep=‘last’参数来以最后一个值为保留值 ''' Out[164]: 0 True 1 False 2 False 3 True 4 True 5 False 6 False dtype: bool ''' 利用映射进行数据转换 data1=DataFrame({'name':['Lucy','Lisa','Job','Peter'], 'english_score':[90,95,100,60]}) ''' In [166]: data1 Out[166]: english_score name 0 90 Lucy 1 95 Lisa 2 100 Job 3 60 Peter ''' name_to_country={'Lucy':'China','Lisa':'China','Job':'Japan','Peter':'America'} ''' In [168]: name_to_country Out[168]: {'Job': 'Japan', 'Lisa': 'China', 'Lucy': 'China', 'Peter': 'America'} ''' data1['country']=data1['name'].map(name_to_country) #利用映射进行数据转换 data1 ''' Out[171]: english_score name country 0 90 Lucy China 1 95 Lisa China 2 100 Job Japan 3 60 Peter America ''' data1['country']=data1['name'].map(lambda x:name_to_country[x]) #和上面映射效果一样 data1['country']=data1['name'].map(lambda x:name_to_country[x]) #replace()函数进行替换 data1.rename(columns=str.upper) #重命名索引 ''' Out[180]: ENGLISH_SCORE NAME COUNTRY 0 90 Lucy China 1 95 Lisa China 2 100 Job Japan 3 60 Peter America ''' #将数据按值分组 scores=[40,54,60,85,78,85,87,81,94,95,98,64,93,97,54] scores_level=[0,60,80,95,100] cats=pd.cut(scores, scores_level) In [187]: cats #type是pandas.core.categorical.Categorical ''' Out[187]: [(0, 60], (0, 60], (0, 60], (80, 95], (60, 80], ..., (95, 100], (60, 80], (80, 95], (95, 100], (0, 60]] Length: 15 Categories (4, object): [(0, 60] < (60, 80] < (80, 95] < (95, 100]] ''' pd.value_counts(cats) # ''' Out[189]: (80, 95] 7 (0, 60] 4 (95, 100] 2 (60, 80] 2 dtype: int64 ''' #异常值过滤和替换 data2=DataFrame(np.random.randn(10,4)) #生成随机数DataFrame In [192]: data2 ''' Out[192]: 0 1 2 3 0 0.645459 1.750947 1.394631 0.284294 1 0.553139 0.283731 1.414306 0.198257 2 1.457770 -0.322144 1.327653 0.004593 3 -1.662690 -0.043047 -0.092989 -1.880086 4 0.380053 0.405532 0.656668 -0.372074 5 -1.324082 1.447865 -1.073686 -0.404050 6 -0.356304 -1.804861 -0.328367 0.226051 7 -0.377587 0.254406 -0.470246 1.467169 8 1.614043 -1.022648 1.292851 0.045828 9 0.641298 0.422020 -0.144660 -0.097150 ''' In [193]: data2.describe() # Generates descriptive statistics that summarize the central tendency, dispersion and shape of a dataset’s distribution, excluding NaN values. ''' Out[193]: 0 1 2 3 count 10.000000 10.000000 10.000000 10.000000 mean 0.157110 0.137180 0.397616 -0.052717 std 1.082637 1.047255 0.927418 0.826236 min -1.662690 -1.804861 -1.073686 -1.880086 25% -0.372266 -0.252370 -0.282440 -0.303343 50% 0.466596 0.269068 0.281840 0.025211 75% 0.644419 0.417898 1.318953 0.219102 max 1.614043 1.750947 1.414306 1.467169 ''' In [194]: data2[np.abs(data2)>2] ''' Out[194]: 0 1 2 3 0 NaN NaN NaN NaN 1 NaN NaN NaN NaN 2 NaN NaN NaN NaN 3 NaN NaN NaN NaN 4 NaN NaN NaN NaN 5 NaN NaN NaN NaN 6 NaN NaN NaN NaN 7 NaN NaN NaN NaN 8 NaN NaN NaN NaN 9 NaN NaN NaN NaN ''' In [195]: data2[np.abs(data2)>1] ''' Out[195]: 0 1 2 3 0 NaN 1.750947 1.394631 NaN 1 NaN NaN 1.414306 NaN 2 1.457770 NaN 1.327653 NaN 3 -1.662690 NaN NaN -1.880086 4 NaN NaN NaN NaN 5 -1.324082 1.447865 -1.073686 NaN 6 NaN -1.804861 NaN NaN 7 NaN NaN NaN 1.467169 8 1.614043 -1.022648 1.292851 NaN 9 NaN NaN NaN NaN ''' data2[(np.abs(data2)>1).any(1)] #找出绝对值大于1的行 ''' Out[197]: 0 1 2 3 0 0.645459 1.750947 1.394631 0.284294 1 0.553139 0.283731 1.414306 0.198257 2 1.457770 -0.322144 1.327653 0.004593 3 -1.662690 -0.043047 -0.092989 -1.880086 5 -1.324082 1.447865 -1.073686 -0.404050 6 -0.356304 -1.804861 -0.328367 0.226051 7 -0.377587 0.254406 -0.470246 1.467169 8 1.614043 -1.022648 1.292851 0.045828 ''' data2[(np.abs(data2)>1)]=0 #将大于1的值赋值为0 ''' In [199]: data2 Out[199]: 0 1 2 3 0 0.645459 0.000000 0.000000 0.284294 1 0.553139 0.283731 0.000000 0.198257 2 0.000000 -0.322144 0.000000 0.004593 3 0.000000 -0.043047 -0.092989 0.000000 4 0.380053 0.405532 0.656668 -0.372074 5 0.000000 0.000000 0.000000 -0.404050 6 -0.356304 0.000000 -0.328367 0.226051 7 -0.377587 0.254406 -0.470246 0.000000 8 0.000000 0.000000 0.000000 0.045828 9 0.641298 0.422020 -0.144660 -0.097150 '''
2017/11/06
安装TuShare
参考了TuShare主页 http://www.waditu.cn/, 幸好之前一直在用Anaconda,就不用从头安装了。 然后'import lxml'试一下发现lxml也已经安装了, 那么下面只需要'pip install tushare' 安装TuShare了。安装过程如下:
>pip install tushare
Collecting tushare
Downloading tushare-1.0.2-py2-none-any.whl (241kB)
100% |████████████████████████████████| 245kB 100kB/s
Installing collected packages: tushare
Successfully installed tushare-1.0.2
You are using pip version 8.1.2, however version 9.0.1 is available.
You should consider upgrading via the 'python -m pip install --upgrade pip' command.
TuShare是一个免费、开源的python财经数据接口包。主要实现对股票等金融数据从数据采集、清洗加工 到 数据存储的过程,能够为金融分析人员提供快速、整洁、和多样的便于分析的数据,为他们在数据获取方面极大地减轻工作量,使他们更加专注于策略和模型的研究与实现上。
安装完成后简单的测试下是否工作:
import tushare as ts
ts.get_hist_data('600848')#一次性获取全部数据
ts.get_realtime_quotes('000581') #获取实时数据
ts.get_tick_data('600848',date='2017-11-06') #按日期获取股票tick数据
很多工具都能实现高效读写磁盘上以二进制格式存储的科学数据。HDF5就是其中一个流行的工业级库,它是一个C库,带有许多语言接口,如Java、Python和MATLAB等。HDF5中的HDF指的是层次型数据格式(hierarchical data format)。每个HDF5文件都含有一个文件系统式的节点结构,它使你能够存储多个数据集并支持元数据。与其他简单格式相比,HDF5支持多种压缩器的即时压缩,还能更高效地存储重复模式数据。对于那些非常大的无法直接放入内存的数据集,HDF5就是不错的选择,因为它可以高效地分块读写。
Python中的HDF5库有两个接口(即PyTables和h5py,PyTables和h5py是两个Python项目),它们各自采取了不同的问题解决方式。h5py提供了一种直接而高级的HDF5 API访问接口,而PyTables则抽象了HDF5的许多细节以提供多种灵活的数据容器、表索引、查询功能以及对核外计算技术(out-of-core computation)的某些支持。HDF5不是数据库。它最适合用作“一次写多次读”的数据集。虽然数据可以在任何时候被添加到文件中,但如果同时发生多个写操作,文件就可能会被破坏。
import tables -- 加载PyTables模块, 测试了一下安装Anaconda后就可以直接加载PyTables模块, 下面写和读HDF5文件并没有用到PyTables的函数,用的只是Pandas中已经带的个最小化的类似于字典的HDFStore类。
b=DataFrame(np.random.standard_normal((9,4)), columns=['nume1','num2','num3','num4']) ''' In [239]: b Out[239]: nume1 num2 num3 num4 0 1.158960 0.379281 -0.946333 1.032113 1 0.200613 -0.493041 1.790898 0.626836 2 -0.863466 -0.093312 1.135044 -1.905544 3 0.725022 -1.235164 -0.187282 0.123741 4 0.825146 0.622544 1.008107 0.957544 5 -0.658977 -0.552654 0.203021 0.768545 6 -0.755136 -0.089755 1.184829 0.476440 7 0.627674 -1.586048 0.622072 -0.202613 8 -0.674689 0.530108 1.169081 -0.136596 ''' #存储DataFrame到HDF5文件中 h5fd=pd.HDFStore('test.h5', 'w') h5fd['data']=b h5fd.close() #读取HDF5文件 h5fd2=pd.HDFStore('test.h5','r') c=h5['data'] ''' In [247]: c Out[247]: num1 num2 num3 num4 0 0.209036 0.387769 -0.790830 0.012579 1 -1.666029 1.659803 -0.187105 -0.655953 2 0.318093 -0.088663 -0.260422 -1.534559 3 -0.110904 -0.528009 0.937565 0.207867 4 0.694693 0.740356 -1.078945 -0.263803 5 -1.534053 -0.817347 -1.117847 0.486794 6 -0.710491 0.693885 -1.506978 0.828116 7 -0.767901 -0.167871 0.633814 -2.155509 8 1.716380 1.124709 2.207792 0.046054 '''
一个简单的读取股票数据并存储的例子
import tushare as ts d=ts.get_tick_data('600848',date='2017-11-06') #读取股票历史数据 type(d) ''' Out[250]: pandas.core.frame.DataFrame ''' len(d) ''' Out[251]: 3711 ''' h6=pd.HDFStore('test6.h5', 'w') #将数据写入文件 h6['data']=d h6.close() h7=pd.HDFStore('test6.h5', 'r') #读取文件到DataFrame e=h7['data'] type(e) ''' Out[267]: pandas.core.frame.DataFrame ''' len(e) ''' Out[268]: 3711 '''
HDF5压缩格式
a=np.random.standard_normal((9000000,4)) b=pd.DataFrame(a) h5=pd.HDFStore('test_a1.h5','w') #无压缩存储 h5['data']=b h5.close() h6=pd.HDFStore('test_a2.h5','w',complevel=4, complib='blosc') #压缩存储 h6['data']=b h6.close()
2017/12/17
升级tushare到版本1.0.7, 因为使用之前的版本是有些调用出错如下:
(C:\Anaconda2) C:\Users\Administrator>pip install tushare --upgrade Collecting tushare Downloading tushare-1.0.7-py2-none-any.whl (235kB) 100% |████████████████████████████████| 245kB 175kB/s Collecting requests>=2.0.0 (from tushare) Downloading requests-2.18.4-py2.py3-none-any.whl (88kB) 100% |████████████████████████████████| 92kB 204kB/s Collecting lxml>=3.8.0 (from tushare) Downloading lxml-4.1.1-cp27-cp27m-win32.whl (3.2MB) 100% |████████████████████████████████| 3.2MB 53kB/s Collecting pandas>=0.18.0 (from tushare) Downloading pandas-0.21.1-cp27-cp27m-win32.whl (8.4MB) 100% |████████████████████████████████| 8.4MB 34kB/s Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.0.0->tushare) Downloading chardet-3.0.4-py2.py3-none-any.whl (133kB) 100% |████████████████████████████████| 143kB 66kB/s Collecting certifi>=2017.4.17 (from requests>=2.0.0->tushare) Downloading certifi-2017.11.5-py2.py3-none-any.whl (330kB) 100% |████████████████████████████████| 337kB 123kB/s Collecting urllib3<1.23,>=1.21.1 (from requests>=2.0.0->tushare) Downloading urllib3-1.22-py2.py3-none-any.whl (132kB) 100% |████████████████████████████████| 133kB 81kB/s Collecting idna<2.7,>=2.5 (from requests>=2.0.0->tushare) Downloading idna-2.6-py2.py3-none-any.whl (56kB) 100% |████████████████████████████████| 61kB 39kB/s Collecting numpy>=1.9.0 (from pandas>=0.18.0->tushare) Downloading numpy-1.13.3-2-cp27-none-win32.whl (6.7MB) 100% |████████████████████████████████| 6.7MB 40kB/s Collecting python-dateutil (from pandas>=0.18.0->tushare) Downloading python_dateutil-2.6.1-py2.py3-none-any.whl (194kB) 100% |████████████████████████████████| 194kB 57kB/s Collecting pytz>=2011k (from pandas>=0.18.0->tushare) Downloading pytz-2017.3-py2.py3-none-any.whl (511kB) 100% |████████████████████████████████| 512kB 39kB/s Collecting six>=1.5 (from python-dateutil->pandas>=0.18.0->tushare) Downloading six-1.11.0-py2.py3-none-any.whl Installing collected packages: chardet, certifi, urllib3, idna, requests, lxml, numpy, six, python-dateutil, pytz, pandas, tushare Found existing installation: idna 2.1 Uninstalling idna-2.1: Successfully uninstalled idna-2.1 Found existing installation: requests 2.10.0 Uninstalling requests-2.10.0: Successfully uninstalled requests-2.10.0 Found existing installation: lxml 3.6.0 Uninstalling lxml-3.6.0: Successfully uninstalled lxml-3.6.0 Exception: Traceback (most recent call last): File "c:\anaconda2\lib\site-packages\pip\basecommand.py", line 215, in main status = self.run(options, args) File "c:\anaconda2\lib\site-packages\pip\commands\install.py", line 342, in run prefix=options.prefix_path, File "c:\anaconda2\lib\site-packages\pip\req\req_set.py", line 795, in install requirement.commit_uninstall() File "c:\anaconda2\lib\site-packages\pip\req\req_install.py", line 767, in commit_uninstall self.uninstalled.commit() File "c:\anaconda2\lib\site-packages\pip\req\req_uninstall.py", line 142, in commit rmtree(self.save_dir) File "c:\anaconda2\lib\site-packages\pip\_vendor\retrying.py", line 49, in wrapped_f return Retrying(*dargs, **dkw).call(f, *args, **kw) File "c:\anaconda2\lib\site-packages\pip\_vendor\retrying.py", line 212, in call raise attempt.get() File "c:\anaconda2\lib\site-packages\pip\_vendor\retrying.py", line 247, in get six.reraise(self.value[0], self.value[1], self.value[2]) File "c:\anaconda2\lib\site-packages\pip\_vendor\retrying.py", line 200, in call attempt = Attempt(fn(*args, **kwargs), attempt_number, False) File "c:\anaconda2\lib\site-packages\pip\utils\__init__.py", line 102, in rmtree onerror=rmtree_errorhandler) File "c:\anaconda2\lib\shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "c:\anaconda2\lib\shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "c:\anaconda2\lib\shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "c:\anaconda2\lib\shutil.py", line 247, in rmtree rmtree(fullname, ignore_errors, onerror) File "c:\anaconda2\lib\shutil.py", line 252, in rmtree onerror(os.remove, fullname, sys.exc_info()) File "c:\anaconda2\lib\site-packages\pip\utils\__init__.py", line 114, in rmtree_errorhandler func(path) WindowsError: [Error 5] : 'c:\\users\\admini~1\\appdata\\local\\temp\\pip-0hrgno-uninstall\\anaconda2\\lib\\site-packages\\lxml\\etree.pyd'
升级过程中报错,好像是卸载已有某些module的老版本有问题, 多运行几次升级命令即可。最终升级成功并且可以获取tushare数据。