北京旅游攻略?Python动态图给你展示!

Python与算法之美

共 21377字,需浏览 43分钟

 · 2021-07-05

今日表情



不少同学想必都去过北京,但是大多数的景点可能都没有去过,毕竟北京市是一个小学语文课本中地理名词扎堆的地方。在北京都有哪些经典的旅游景点呢?让我们用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, (255255255))
    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+2for 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.130.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)


收工。😋


万水千山总是情,点个在看行不行?


北京还有哪些你去过的非常不错的旅游景点,欢迎在留言区和大家分享哦!



浏览 19
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报