Numpy已经能够帮助我们处理数据,能够结合matplotlib解决部分数据展示等问题,那么pandas学习的目的在什么地方呢?
array([[92,55,78,50,50],[71,76,50,48,96],[45,84,78,51,68],[81,91,56,54,76],[86,66,77,67,95],[46,86,56,61,99],[46,95,44,46,56],[80,50,45,65,57],[41,93,90,41,97],[65,83,57,57,40]])如果数据展示为这样,可读性就会更友好:
Pandas中一共有三种数据结构,分别为:Series、DataFrame和MultiIndex(老版本中叫Panel)。
其中Series是一维数据结构,DataFrame是二维的表格型数据结构,MultiIndex是三维的数据结构。
#导入pandasimportpandasaspdpd.Series(data=None,index=None,dtype=None)通过已有数据创建:
color_count[2]#结果1001.2.2DataFrameDataFrame是一个类似于二维数组或表格(如excel)的对象,既有行索引,又有列索引:
#导入pandasimportpandasaspdpd.DataFrame(data=None,index=None,columns=None)举例一:
pd.DataFrame(np.random.randn(2,3))结果:
举例二:创建学生成绩表
使用np创建的数组显示方式,比较两者的区别。
#生成10名同学,5门功课的数据score=np.random.randint(40,100,(10,5))#均匀分布#结果array([[92,55,78,50,50],[71,76,50,48,96],[45,84,78,51,68],[81,91,56,54,76],[86,66,77,67,95],[46,86,56,61,99],[46,95,44,46,56],[80,50,45,65,57],[41,93,90,41,97],[65,83,57,57,40]])但是这样的数据形式很难看到存储的是什么的样的数据,可读性比较差!!
问题:如何让数据更有意义的显示?
#使用Pandas中的数据结构score_df=pd.DataFrame(score)结果:
给分数数据增加行列索引,显示效果更佳:
data.shape#结果(10,5)DataFrame的行索引列表
array([[54,82,62,81,47],[50,58,73,72,48],[88,89,49,99,83],[79,81,69,45,87],[87,64,62,74,85],[68,56,58,77,53],[77,49,82,48,82],[96,49,67,94,71],[98,77,44,99,41],[71,52,74,90,44]])转置
data.T结果:
如果不补充参数,默认5行。填入参数N则显示前N行
data.head(5)结果:
如果不补充参数,默认5行。填入参数N则显示后N行
data.tail(5)结果:
现在要将下图的行索引改变,变成下下图所示样子,怎么做呢?
stu=["学同学_"+str(i)foriinrange(score_df.shape[0])]#必须整体全部修改data.index=stu注意:以下修改方式是错误的,说明不能单独修改
#重置索引,drop=Truedata.reset_index()结果:
设置新索引案例:
1、创建
MultiIndex是三维的数据结构;
多级索引(也称层次化索引)是pandas的重要功能,可以在Series、DataFrame对象上拥有2个以及2个以上的索引。
打印刚才的df的行索引结果
为了更好的理解这些基本操作,我们将读取一个真实的股票数据。关于文件操作,后面在介绍,这里只先用一下API。
获取’2018-02-27’这天的’open’的结果:
如下:
例一:
#按照开盘价大小进行排序,使用ascending指定按照大小排序data.sort_values(by="open",ascending=True).head()结果:
例二:
这个股票的日期索引原来是从大到小,现在重新排序,从小到大:
#对索引进行排序data.sort_index()结果:
series排序时,只有一列,不需要参数
data.open.head().sub(2)2018-02-2721.532018-02-2620.802018-02-2320.882018-02-2220.252018-02-1419.49Name:open,dtype:float643.2逻辑运算3.2.1逻辑运算符号代码语言:javascript复制data["open"]>232018-02-27True2018-02-26False2018-02-23False2018-02-22False2018-02-14False代码语言:javascript复制#逻辑判断的结果可以作为筛选的依据data[data["open"]>23].head()结果:
data.query("open<24&open>23").head()结果:
例如判断’open’是否为23.53和23.85:
对于单个函数去进行统计的时候,坐标轴还是按照默认列“columns”(axis=0,default),如果要对行“index”需要指定(axis=1)。
#使用统计函数:0代表列求结果,1代表行求统计结果data.max(axis=0)#最大值open34.99high36.35close35.21low34.01volume501915.41price_change3.03p_change10.03turnover12.56my_price_change3.41dtype:float64代码语言:javascript复制#方差data.var(axis=0)open1.545255e+01high1.662665e+01close1.554572e+01low1.437902e+01volume5.458124e+09price_change8.072595e-01p_change1.664394e+01turnover4.323800e+00my_price_change6.409037e-01dtype:float64#标准差data.std(axis=0)open3.930973high4.077578close3.942806low3.791968volume73879.119354price_change0.898476p_change4.079698turnover2.079375my_price_change0.800565dtype:float64中位数为将数据从小到大排列,在最中间的那个数为中位数。如果没有中间数,取中间两个数的平均值。
如果要使用plot函数,需要导入matplotlib.下面是绘图代码:
importmatplotlib.pyplotasplt#plot显示图形,plot方法集成了直方图、条形图、饼图、折线图stock_rise.cumsum().plot()#需要调用show,才能显示出结果plt.show()结果:
关于plot,稍后会介绍API的选择。
下面看个例子:
看个例子:
importmatplotlib.pyplotasplt#plot显示图形,plot方法集成了直方图、条形图、饼图、折线图stock_rise.cumsum().plot(kind="line")#需要调用show,才能显示出结果plt.show()结果:
注:使用的时候查看。
我们的数据大部分存在于文件当中,所以pandas会支持复杂的IO操作,pandas的API支持众多的文件格式,如CSV、SQL、XLS、JSON、HDF5。
注:最常用的HDF5和CSV文件
接下来重点看一下,应用CSV方式、HDF方式和json方式实现文件的读取和存储。
举例:读取之前的股票的数据:
下面例子把index指定为False,那么保存的时候就不会保存行索引了:
#把Unnamed:0这一列,变成行索引open.set_index(["Unnamed:0"])#把索引名字变成indexopen.index.name="index"5.2HDF55.2.1read_hdf与to_hdfHDF5文件的读取和存储需要指定一个键,值为要存储的DataFrame
day_close=pd.read_hdf("./data/day_close.h5")如果读取的时候出现以下错误
需要安装安装tables模块避免不能读取HDF5文件
new_close=pd.read_hdf("./data/test.h5",key="day_close")注意:优先选择使用HDF5文件存储
JSON是我们常用的一种数据交换格式,在前后端的交互经常用到,也会在存储的时候选择这种格式。所以我们需要知道Pandas如何进行读取和存储JSON格式。
案例:
json_read=pd.read_json("./data/Sarcasm_Headlines_Dataset.json",orient="records",lines=True)结果为:
按如下步骤进行:
步骤就是上面的这样,下面通过例子来看看怎么使用pandas处理的:
np.all(pd.notnull(movie))#返回False代码语言:javascript复制#判断是否是缺失值,是则返回Truepd.isnull(movie).head()#结果:RankTitleGenreDescriptionDirectorActorsYearRuntime(Minutes)RatingVotesRevenue(Millions)Metascore0FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse1FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse2FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse3FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse4FalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalseFalse这个也不好观察,我们利用np.any()来判断是否有缺失值,若有则返回True,下面看例子:
np.any(pd.isnull(movie))#返回True6.2.2存在缺失值nan,并且是np.nanpandas删除缺失值,使用dropna的前提是,缺失值的类型必须是np.nan
#这个循环,每次取出一列数据,然后用均值来填充foriinmovie.columns:ifnp.all(pd.notnull(movie[i]))==False:print(i)movie[i].fillna(movie[i].mean(),inplace=True)6.2.3不是缺失值nan,有默认标记的直接看例子:
数据是这样的:
URLError:
连续属性的离散化就是在连续属性的值域上,将值域划分为若干个离散的区间,最后用不同的符号或整数值代表落在每个子区间中的属性值。
离散化有很多种方法,这里使用一种最简单的方式去操作:
这样我们将数据分到了三个区间段,对应的标记为矮、中、高三个类别,最终要处理成一个"哑变量"矩阵。
下面通过股票数据的例子来看看,具体是怎么操作的。
我们对股票每日的"p_change"这一列进行离散化,下图便是离散化后的结果,当前数据存在哪个区间,则这个区间标记为1,否则为0。
那具体怎么做的呢?接着看:
先读取股票的数据,筛选出p_change数据。
使用的工具:
#自行分组qcut=pd.qcut(p_change,10)#计算分到每个组数据个数qcut.value_counts()#运行结果:(5.27,10.03]65(0.26,0.94]65(-0.462,0.26]65(-10.030999999999999,-4.836]65(2.938,5.27]64(1.738,2.938]64(-1.352,-0.462]64(-2.444,-1.352]64(-4.836,-2.444]64(0.94,1.738]63Name:p_change,dtype:int64自定义区间分组:
#自己指定分组区间bins=[-100,-7,-5,-3,0,3,5,7,100]p_counts=pd.cut(p_change,bins)p_counts.value_counts()#运行结果:(0,3]215(-3,0]188(3,5]57(-5,-3]51(7,100]35(5,7]35(-100,-7]34(-7,-5]28Name:p_change,dtype:int647.3.3股票涨跌幅分组数据变成one-hot编码把下图中左边的表格转化为使用右边形式进行表示:
下面看看pandas中是怎么实现的:
下面是例子:
#得出one-hot编码矩阵dummies=pd.get_dummies(p_counts,prefix="rise")运行结果:
如果你的数据由多张表组成,那么有时候需要将不同的内容合并在一起分析
比如我们将刚才处理好的one-hot编码与原数据合并:
#按照行索引进行pd.concat([data,dummies],axis=1)结果:
例子:
探究股票的涨跌与星期几有关?
以下图当中表示,week代表星期几,1,0代表这一天股票的涨跌幅是好还是坏,里面的数据代表比例
但是我们看到count只是每个星期日子的好坏天数,并没有得到比例,该怎么去做?
#算数运算,先求和sum=count.sum(axis=1).astype(np.float32)#进行相除操作,得出比例pro=count.div(sum,axis=0)结果:
使用plot画出这个比例,使用stacked的柱状图
分组与聚合通常是分析数据的一种方式,通常与一些统计函数一起使用,查看数据的分组情况
下图展示了分组与聚合的概念:
案例:不同颜色的不同笔的价格数据
从文件中读取星巴克店铺数据
现在我们有一组从2006年到2016年1000部最流行的电影数据
首先获取导入包,获取数据:
%matplotlibinlineimportpandasaspdimportnumpyasnpfrommatplotlibimportpyplotasplt代码语言:javascript复制#文件的路径path="./data/IMDB-Movie-Data.csv"#读取文件df=pd.read_csv(path)11.2.1问题一:我们想知道这些电影数据中评分的平均分,导演的人数等信息,我们应该怎么获取?
使用mean函数
df["Rating"].mean()#结果:6.723200000000003求出唯一值,然后进行形状获取
##导演的人数#df["Director"].unique().shape[0]#方法一np.unique(df["Director"]).shape[0]#方法二64411.2.2问题二:对于这一组电影数据,如果我们想Rating的分布情况,应该如何呈现数据?
选择分数列数据,进行plot
发现直接通过pandas的plot画图,显示的下标不合适,这个时候我们需要借助matplotlib来改变。
进行绘制直方图
对于这一组电影数据,如果我们希望统计电影分类(genre)的情况,应该如何处理数据?