北京旅游攻略?Python动态图给你展示!
Python与算法之美
共 21377字,需浏览 43分钟
·
2021-07-05 16:43
今日表情
不少同学想必都去过北京,但是大多数的景点可能都没有去过,毕竟北京市是一个小学语文课本中地理名词扎堆的地方。在北京都有哪些经典的旅游景点呢?让我们用Python来做个北京6日旅游攻略的短视频吧!😋
先上数据
D1 天安门广场(1.5小时) → 前门大街(1.5小时) → 北京全聚德(前门店)(1小时) → 故宫(3小时) → 景山公园(1小时)
D2 天坛(2.5小时) → 雍和宫(2小时) → 孔庙和国子监博物馆(1.5小时) → 簋街(2小时)
D3 恭王府(2.5小时) → 什刹海(3小时) → 南锣鼓巷(机动选择,1.5小时) → 什刹海酒吧街(2小时)
D4 圆明园(3小时) → 清华大学(2小时) → 鸟巢(1小时) → 水立方(1小时)
D5 颐和园(4小时) → 北京大学(2小时)
D6 八达岭长城(3-4小时) → 明十三陵(2小时)
再上视频
最后上代码
import numpy as np
import pandas as pd
import geopandas as gpd
import shapely
from shapely import geometry as geo
from shapely import wkt
import geopandas as gpd
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import contextily as ctx
import imageio
import os
from PIL import Image
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.rcParams['animation.writer'] = 'html'
plt.rcParams['animation.embed_limit'] = 100
def rgba_to_rgb(img_rgba):
img_rgb = Image.new("RGB", img_rgba.size, (255, 255, 255))
img_rgb.paste(img_rgba, mask=img_rgba.split()[3])
return img_rgb
def html_to_gif(html_file, gif_file, duration=0.5):
path = html_file.replace(".html","_frames")
images = [os.path.join(path,x) for x in sorted(os.listdir(path))]
frames = [imageio.imread(x) for x in images]
if frames[0].shape[-1]==4:
frames = [np.array(rgba_to_rgb(Image.fromarray(x))) for x in frames]
imageio.mimsave(gif_file, frames, 'gif', duration=duration)
return gif_file
cmap = [
'#2E91E5',
'#1CA71C',
'#DA16FF',
'#B68100',
'#EB663B',
'#00A08B',
'#FC0080',
'#6C7C32',
'#862A16',
'#620042',
'#DA60CA',
'#0D2A63']*100
dfplace = pd.read_csv("./data/travel.csv")
dfplace["geometry"] = [shapely.wkt.loads(x) for x in dfplace["geometry"]]
dfplace = gpd.GeoDataFrame(dfplace,geometry="geometry")
dfplace = dfplace.set_crs("epsg:4326").to_crs("epsg:3857")
df = pd.DataFrame({"x":[p.x for p in dfplace["geometry"]],
"y":[p.y for p in dfplace["geometry"]],
"z":dfplace["interval"],
"day":dfplace["day"]})
df.index = dfplace["place"]
def trace_map_dance(df,title = "北京经典6日旅行路线",
filename = None,
figsize = (8,6),dpi = 144,
duration = 0.5,
anotate_points = ["故宫","北京大学","八达岭长城"]):
fig, ax =plt.subplots(figsize=figsize,dpi=dpi)
def plot_frame(i):
ax.clear()
ax.axis("off")
k = i//3+1
m = i%3
dfdata = df.iloc[:k,:].copy()
dftmp = df.iloc[:k-1,:].copy()
text = dfdata["day"].tolist()[-1]
#============================================================
#绘制背景
#============================================================
#设置绘图范围
bounds = dfbeijing.total_bounds # k==1
if 1<k<len(df)+1:
bounds = dfplace.query("day=='{}'".format(text)).total_bounds
if k>=len(df)+1:
bounds = dfplace.total_bounds
(xmin,ymin,xmax,ymax) = bounds
cx = (xmin+xmax)/2.0
cy = (ymin+ymax)/2.0
dx = max(xmax-xmin,100)
dy = max(ymax-ymin,100)
if dx/dy<8/6.0:
dx = dy*8/6.0
else:
dy = dx*6.0/8
bounds = np.array([min(cx-8000,cx-dx/2.0),min(cy-6000,cy-dy/2.0),
max(cx+8000,cx+dx/2.0),max(cy+6000,cy+dy/2.0)])
ax.set_xlim(bounds[0]-(bounds[2]-bounds[0])/3, bounds[2]+(bounds[2]-bounds[0])/3)
ax.set_ylim(bounds[1]-(bounds[3]-bounds[1])/3, bounds[3]+(bounds[3]-bounds[1])/3)
gaode = 'http://wprd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7'
openstreet = "https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png"
ctx.add_basemap(ax,source=gaode,alpha=0.5)
#============================================================
#绘制散点
#============================================================
# 绘制散点图像
if len(dftmp)>0:
ax.scatter(dftmp["x"],dftmp["y"],s = 100*dftmp["z"]/df["z"].mean(),
c = (cmap*100)[0:len(dftmp)],alpha = 0.5,zorder = 3)
# 添加注释文字
for j,p in enumerate(dftmp.index):
px,py,pz = dftmp.loc[p,["x","y","z"]].tolist()
if p in anotate_points:
ax.annotate(p,xy = (px,py), xycoords = "data",xytext = (-20,15),
fontsize = 10,fontweight = "bold",color = cmap[j], textcoords = "offset points")
#绘制轨迹线
lines = [dfdata[["x","y"]].values[i:i+2] for i in range(len(dfdata)-1)]
for ln in lines[:-1]:
x, y = np.transpose(ln)
line = plt.Line2D(x,y,color="gray",linestyle="-",linewidth= 2.5)
ax.add_artist(line)
# 添加标题和排名序号
ax.set_title(title,color = "black",fontsize = 12)
ax.text(0.13, 0.9, text, va="center", ha="center",
alpha=0.5, size = 50,transform = ax.transAxes)
# 结尾呈现全局轨迹无动画
if i>=3*len(df):
for ln in lines[-1:]:
x, y = np.transpose(ln)
line = plt.Line2D(x,y,color="gray",linestyle="-",linewidth= 2.5)
ax.add_artist(line)
return 0
# 添加注意力动画
if m==0:
px,py,pz = dfdata["x"][[-1]],dfdata["y"][[-1]],dfdata["z"][-1]
p = dfdata.index[-1]+":"+str(pz)+"Hours"
ax.scatter(px,py,s = 800*pz/df["z"].mean(),
c = cmap[len(dfdata)-1:len(dfdata)],alpha = 0.5,zorder = 4)
ax.annotate(p,xy = (px,py), xycoords = "data",
xytext = (-20,15),fontsize = 20,fontweight = "bold",
color = cmap[k-1], textcoords = "offset points",zorder = 5)
for ln in lines[-1:]:
x, y = np.transpose(ln)
line = plt.Line2D(x,y,color="gray",linestyle=":",linewidth= 4.5)
ax.add_artist(line)
if m==1:
px,py,pz = dfdata["x"][[-1]],dfdata["y"][[-1]],dfdata["z"][-1]
p = dfdata.index[-1]+":"+str(pz)+"Hours"
ax.scatter(px,py,s = 400*pz/df["z"].mean(),
c = cmap[len(dfdata)-1:len(dfdata)],alpha = 0.5,zorder = 4)
ax.annotate(p,xy = (px,py), xycoords = "data",
xytext = (-20,15),fontsize = 15,fontweight = "bold",
color = cmap[k-1], textcoords = "offset points",zorder = 5)
for ln in lines[-1:]:
x, y = np.transpose(ln)
line = plt.Line2D(x,y,color="gray",linestyle="--",linewidth= 3.5)
ax.add_artist(line)
if m==2:
px,py,pz = dfdata["x"][[-1]],dfdata["y"][[-1]],dfdata["z"][-1]
p = dfdata.index[-1]+":"+str(pz)+"Hours"
ax.scatter(px,py,s = 100*pz/df["z"].mean(),
c = cmap[len(dfdata)-1:len(dfdata)],alpha = 0.5,zorder = 4)
ax.annotate(p,xy = (px,py), xycoords = "data",
xytext = (-20,15),fontsize = 10,fontweight = "bold",
color = cmap[k-1], textcoords = "offset points",zorder = 5)
for ln in lines[-1:]:
x, y = np.transpose(ln)
line = plt.Line2D(x,y,color="gray",linestyle="-",linewidth= 2.5)
ax.add_artist(line)
return 0
my_animation = animation.FuncAnimation(fig,plot_frame,
frames = range(0,3*len(df)+5),interval = int(duration*1000))
if filename is None:
try:
from IPython.display import HTML
HTML(my_animation.to_jshtml())
return HTML(my_animation.to_jshtml())
except ImportError:
pass
else:
my_animation.save(filename)
return filename
html_file = "北京经典6日行路线.html"
trace_map_dance(df,filename=html_file)
gif_file = html_file.replace(".html",".gif")
html_to_gif(html_file,gif_file,duration=0.8)
收工。😋
万水千山总是情,点个在看行不行?
北京还有哪些你去过的非常不错的旅游景点,欢迎在留言区和大家分享哦!
评论