在数据分析领域,最出名的绘图工具就是matlib。在Python同样有类似的功能。就是matplotlib。前面几章我们都在介绍数据的生成,整理,存储。那么这一章将介绍如果图形化的呈现这些数据。来看下面的代码
这个代码通过numpy生成50个随机数,然后进行求和,最后将50个数绘制成图像,k--代表以虚线的方式
import matplotlib.pyplot as plt
from numpy.random import randn
if __name__=="__main__":
plt.plot(randn(50).cumsum(),‘k--‘)
plt.show()
得到的图片如下
我们还可以在一副图中显示多个图片。
fig=plt.figure()
ax1=fig.add_subplot(2,2,1)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
ax4=fig.add_subplot(2,2,4)
plt.show()
matplotlib的图像都位于Figure对象中,通过fig.add_subplot可以创建多个图片。比如fig.add_subplot(2,2,1)代表总共4个图像,1代表为第1个图像。那么这样我们就可以绘制多个图像,每个图像用不同的方式来呈现
fig=plt.figure()
ax1=fig.add_subplot(2,2,1)
ax2=fig.add_subplot(2,2,2)
ax3=fig.add_subplot(2,2,3)
ax4=fig.add_subplot(2,2,4)
ax1.plot(randn(50).cumsum(), ‘k--‘)
ax2.hist(randn(50).cumsum())
ax3.scatter(np.arange(30),np.arange(30)+3*randn(30))
ax4.plot(randn(50).cumsum())
plt.show()
下面4 张图分别绘制了4种图形。
subplots的参数如下
我们还可以针对subplot调整各个图的间距,通过subplots_adjust就可以达到
下面的代码通过创造4个图像,且共享x,y坐标轴。通过wspace和hsapce设置为0,将各个图像的左右,上下边界都连接在了一起。
fig,axis=plt.subplots(2,2,sharex=True,sharey=True)
[axis[i,j].hist(randn(50),bins=50,color=‘k‘,alpha=0.5) for i in range(2) for j in range(2)]
plt.subplots_adjust(wspace=0, hspace=0)
plt.show()
结果如下:
前面介绍了如何作图,下面将对图片进行更细化的操作,设置x,y轴的刻度以及设置图片标题。在下面的代码中,设置x的刻度为0,10,25,40,50几个区间并设置图片的标题为test
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(randn(50).cumsum(),‘k‘,label=‘one‘)
ax.set_xticks([0,10,25,40,50])
ax.set_title("test")
plt.show()
结果如下:
还可以通过ax.text(x,y,"2010")的方式对图标上的某一点坐标进行文本标注
比如ax.text(0,0,"2010")就在0,0的坐标上标注2010的样式
既然生成了图片,那么该如何保存呢. 通过savefig的方式就可以进行保存,通过指定不同的图片后缀名就可以进行文件的保存。
plt.savefig("figure.svg")
plt.savefig("figure.jpg")
plt.savefig("figure.png")
pandas中的绘图函数:
前面介绍了matplotlib中的绘图方法,这一章将介绍pandas中绘图方法。代码如下
首先通过Series产生数据,然后Series对象的索引会被传递给matplotlib用于绘制X轴
s=Series(np.random.randn(10).cumsum(),index=np.arange(0,100,10))
s.plot(color=‘k‘,alpha=0.7)
plt.title(‘pandas test‘)
plt.show()
结果如下所示:
接下来看下DataFrame的结果图:
d=DataFrame(np.random.randn(10,4).cumsum(0),columns=[‘A‘,‘B‘,‘C‘,‘D‘],index=np.arange(0,100,10))
d.plot()
plt.show()
结果如下:
通过上图可以看到DataFrame的plot方法会在一个subplot中为各列绘制一条线,并自动创建图例。
Series.plot方法的参数:
DataFrame的plot参数
在plot中通过指定kind可以生成不同的图形,比如kind=’bar’就是生成柱状图
我们在来看下下面的这组数据,通过设置stacked=True即可为DataFrame生成堆积柱状图,这样可以使得每行的值就会被堆积在一起。
frame=DataFrame([[1,16,1,1,0,0],[2,53,18,13,1,0],[0,39,15,18,3,1],[1,48,4,5,1,3]],columns=[1,2,3,4,5,6],index=[‘Fri‘,‘Sat‘,‘Sun‘,‘Thur‘])
frame.index.name=[‘day‘]
frame.columns.names=[‘size‘]
print frame
frame.plot(kind=‘barh‘,stacked=True)
plt.show()
数据如下:该数据的列表示人的索引。行代表是天数。这个数据的意义在与指示每个人在从周四到周日的消费情况
size 1 2 3 4 5 6
[day]
Fri 1 16 1 1 0 0
Sat 2 53 18 13 1 0
Sun 0 39 15 18 3 1
Thur 1 48 4 5 1 3
通过下面得到的结果来看,我们可以看到在周末的时候消费明显增加。
密度图:
密度图也成为kde图,这个图是生成标准正态分布图
s=Series(np.random.randn(20))
s.plot(kind=‘kde‘)
plt.show()
得到的正态分布图如下:
1.获取数据:
想要获得道指30只成分股的最新股价
import requests import re import pandas as pd def retrieve_dji_list(): try: r = requests.get(‘https://money.cnn.com/data/dow30/‘) except ConnectionError as err: print(err) search_pattern = re.compile(‘class="wsod_symbol">(.*?)<\/a>.*?<span.*?">(.*?)<\/span>.*?\n.*?class="wsod_stream">(.*?)<\/span>‘) dji_list_in_text = re.findall(search_pattern, r.text) dji_list = [] for item in dji_list_in_text: dji_list.append([item[0], item[1], float(item[2])]) return dji_list dji_list = retrieve_dji_list() djidf = pd.DataFrame(dji_list) print(djidf)
整理数据, 改变列名, index等
cols=[‘code‘,‘name‘,‘lasttrade‘] djidf.columns=cols # 改变列名 djidf.index=range(1,len(djidf)+1)
最后结果为:
数据的选择
djidf.code # 获取code列+index djidf[‘code‘] # 获取code列 , 两者同功能 djidf.loc[1:5,] # 前5行 djidf.loc[:,[‘code‘,‘lasttrade‘]] #所有行 djidf.loc[1:5,[‘code‘,‘lasttrade‘]] #1-5行, loc表示标签index djidf.loc[1,[‘code‘,‘lasttrade‘]] #1行 djidf.at[1,‘lasttrade‘] # 只有一个值的时候可以用at djidf.iloc[2:4,[0,2]] # 表示物理文职, 并且4取不到, 就只有第三行第四行 djidf.iat[1,2] # 单个值
简单的数据筛选: 平均股价, 股价大于180的公司名
djidf.lasttrade.mean() # 121.132 djidf[djidf.lasttrade>=180].name
找到股价前三名的公司 , 降序排列
tempdf=djidf.sort_values(by=‘lasttrade‘,ascending=False) tempdf[:3].name
如何根据index排序呢? 专门有函数sort_index()
df=pd.DataFrame(np.random.randn(3,3),index=[‘c‘,‘b‘,‘a‘],columns=list(‘xyz‘)) df.sort_index() # 根据index 进行排序
*获取AXP公司过去一年的股价数据获取
import requests import re import json import pandas as pd from datetime import date def retrieve_quotes_historical(stock_code): quotes = [] url = ‘https://finance.yahoo.com/quote/%s/history?p=%s‘ % (stock_code, stock_code) try: r = requests.get(url) except ConnectionError as err: print(err) m = re.findall(‘"HistoricalPriceStore":{"prices":(.*?),"isPending"‘, r.text) if m: quotes = json.loads(m[0]) # m = [‘[{...},{...},...]‘] quotes = quotes[::-1] # 原先数据为date最新的在最前面 return [item for item in quotes if not ‘type‘ in item] quotes = retrieve_quotes_historical(‘AXP‘) list1=[] for i in range(len(quotes)): x=date.fromtimestamp(quotes[i][‘date‘]) y=date.strftime(x,‘%Y-%m-%d‘) list1.append(y) quotesdf_ori=pd.DataFrame(quotes,index=list1) quotesdf_m = quotesdf_ori.drop([‘adjclose‘], axis = 1) #删除adjclose列 quotesdf=quotesdf_m.drop([‘date‘],axis=1) print(quotesdf)
上述需要对时间进行处理, 将时间转为‘%Y-%m-%d‘的格式, 并且将这个时间作为一个list 成为quotesdf的index.
数据的筛选
quotesdf[(quotesdf.index>=‘2017-03-01‘) & (quotesdf.index<=‘2017-03-31‘)] quotesdf[(quotesdf.index>=‘2017-11-30‘) & (quotesdf.index<=‘2018-03-31‘)& (quotesdf.close>=90)]
简单计算
(1) 统计AXP股价涨跌的天数 (close>open)
len(quotesdf.close>quotesdf.open)
(2) 相邻两天的涨跌
import numpy as np status=np.sign(np.diff(quotesdf.close)) status # 250 的长度, 比quotesdf 少1 status[np.where(status==1)].size # np.where(status==1)是由下标构成的array #
上述统计还可以直接用describe函数, 得到基本统计信息
import pandas as pd import numpy as np index_df = pd.DataFrame(np.random.rand(3,3), index=[‘a‘,‘b‘,‘c‘], columns=[‘index_1‘,‘index_2‘,‘index_3‘]) index_df.describe() # 超级强大
(3) 统计2018一月的交易日天数
t=quotesdf[(quotesdf.index>=‘2018-01-01‘) & (quotesdf.index<‘2018-02-01‘)] len(t) #21
进一步, 如何统计近一年每个月的交易日天数?
统计每个月的出现天数就行了, 如何提取月份信息? 要把时间的字符串转化为 时间格式,
import time list2=[] for i in range(len(quotesdf)): temp=time.strptime(quotesdf.index[i],‘%Y-%m-%d‘) list2.append(temp.tm_mon) # 取月份 tempdf=quotesdf.copy() tempdf[‘month‘]=list2 # 新增一列月份的数据 print(tempdf[‘month‘].value_counts()) # 计算每个月的出现次数
注意:
strptime 将字符串格式化为time结构, time 中会包含年份, 月份等信息
strftime 将time 结构格式化一个字符串, 之前生成quotesdf中用到过
上述方法略微麻烦, 如何快速知道每个月的交易日天数? groupby
# 统计每一月的股票开盘天数 x=tempdf.groupby(‘month‘).count() # 统计近一年每个月的成交量 tempdf.groupby(‘month‘).sum().volume # 先每个月进行求和, 但是这些对其他列也进行了求和, 属于无效计算, 如何避免? tempdf.groupby(‘month‘).volume.sum() # 交换顺序即可
引申: 一般groupby 与apply 在一起用. 具体不展开了
def f(df): return df.age.count() data_df.groupby(‘taste of mooncake‘).apply(f)
(二) 合并DataFrame: append, concat, join
# append p=quotesdf[:2] q=quotesdf[‘2018-01-01‘:‘2018-01-05‘] p.append(q) # concat pieces=[tempdf[:5],tempdf[len(tempdf)-5:]] pd.concat(pieces)
两个结构不同的DataFrame 如何合并?
piece1=quotesdf[0:3] piece2=tempdf[:3] pd.concat([piece1,piece2],ignore_index=True)
piece2有month 但是piece1中没有这个字段
join函数中的各种参数, 可以用来实现SQL的各种合并功能.
#join 两个dataframe要有共同的字段(列名) #djidf: code/name #AKdf: volume/code/month # 合并之后的字段: code/name/volume/month pd.merge(djidf.drop([‘lasttrade‘],axis=1),AKdf, on=‘code‘)
原文地址:https://www.cnblogs.com/abdm-989/p/12129149.html