最近需要制作动态的房价排行榜.
需要的效果:
1 从房价100名到第一名逐步呈现
2 进场需要动画效果
3 出场需要动画效果
源码分享如下:
#coding=utf-8
#
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import animation # 动图的核心函数
# count为bar进场的动画帧数,每count帧取同一个数
count = 3
def is_fangjia(x, fields):
for field in fields:
# print(field)
# print(x)
if field in str(x) or x == 0:
return False
return True
class Plot(object):
"""docstring for Plot"""
def __init__(self, data):
# 中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots(figsize = (12,6))
self.fig = fig
self.ax = ax
self.data = data
def showGif(self, save_path, writer = 'imagemagick'):
plt.cla()
ani = animation.FuncAnimation(fig = self.fig,
func = self.update,
frames = len(self.data)*count,
init_func = self.init,
interval = 0.5,
blit = False,
repeat = False)
# 不用imagemagick时,可以保存为html
ani.save(save_path, writer = writer,fps = 3)
def init(self):
bar = self.ax.barh([], [], color = '#6699CC')
return bar
def update(self, i):
j,n = divmod(i,count)
self.colors=['cornflowerblue','tomato','coral','darksalmon','orangered','sienna','chocolate',
'saddlebrown','orange','burlywood','olive','olivedrab','greenyellow','lawngreen',
'orchid','palegreen','aqua','deepskyblue','dodgerblue','darkviolet','crimson']*10
self.ax.cla()
data = self.data[j]
# [2, [17969, 17970], ['深业堤亚纳湾', '北辰三角洲D2区'], [100, 99]]
x = data[1]#x轴是房价列表
y = data[3] #y轴是小区房价的名次列表
v = data[2]#每条bar的内容是小区名称列表
year = data[0]#标题是该出场小区的出场顺序,名次是101-year
bars = []
for k in range(len(x)):
if k == len(x)-1:
bar = self.ax.barh(k, x[k]*(n+1)/count, color=self.colors[y[k]])
elif k == 0 and len(x) == 10:
bar = self.ax.barh(k, x[k], color=self.colors[y[k]])
else:
bar = self.ax.barh(k, x[k], color=self.colors[y[k]])
bars.append(bar)
#添加数据标签
for index,rect in enumerate(bars):
rect = rect[-1]
w = rect.get_width()
self.ax.text(w, rect.get_y() + rect.get_height() / 2, '{}'.format(v[index]), ha = 'right',va = 'center')
self.ax.text(w, rect.get_y() + rect.get_height() / 2, '{:.2f}万'.format( float(x[index] / 10000)),ha = 'left',va = 'center')
#设置标题
self.ax.set_title('2021年3月长沙小区房价排行榜', loc='left', fontsize='x-large', fontweight='heavy')
self.ax.set_title('第{}名:{}'.format(101 - year, v[-1]), color='red', loc='right', fontsize='large',
fontweight='bold')
#设置Y轴刻度线标签
if len(y)<10:
yticks=range(10)
yticklables=y+[99-i for i in range(10-len(y))]
else:
yticks=range(len(y))
yticklables = y
self.ax.set_yticks(yticks)
self.ax.set_yticklabels(yticklables)
#设置X轴刻度线标签
self.ax.xaxis.set_ticks_position('top')
self.ax.set_xlabel("单位:元/平米")
return bar
def main():
# 读取数据
price = pd.read_csv("房价信息.csv",encoding="gbk",usecols=["小区","房价"])
# print(price)
#筛选保留需要的数据:去掉0 暂无 等无效或无关的数据
fields = ["暂","无"]
price["is_fangjia"] = price.apply(lambda x: is_fangjia(x["房价"], fields), axis = 1)
price = price[price["is_fangjia"] == True]
price["房价"]=[int(i) for i in price["房价"]]
print(price)
num = len(price)#有效数据的总列数
price.sort_values("房价", inplace=True, ascending=False) # 降序排列
price["order"] = [i for i in range(1,num+1)]
price = price[0:100] # 取房价最高的前100名小区
price.sort_values("房价", inplace=True, ascending=True) # 升序排列
print(price)
#按照从低房价到高房价依次出场,出场顺序为year
datas = []
for year in range(1,101):
if year < 10:
data= price[0:year][["小区", '房价',"order"]]#当前没有铺满15个bar之前,取从第1名到当前名次
# price.sort_values("房价", inplace=True, ascending=False) # 降序排列
print(data)
else:
data = price[year-10:year][["小区", '房价',"order"]]#满了15个bar之后,就取当前名次及之前14名
# price.sort_values("房价", inplace=True, ascending=False) # 降序排列
print(data)
datas.append([year, data["房价"].tolist(), data["小区"].tolist(),data["order"].tolist()])
print(datas)
plot = Plot(datas)
plot.showGif("price.gif", writer = "imagemagick")
plot.showGif("price.html", writer = "html")
print('已保存完毕')
if __name__ == '__main__':
main()