2021-03-10

最近需要制作动态的房价排行榜.
需要的效果:
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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值