bd@atyun.com
前文回顧:使用交互式地圖和動畫可視化倫敦的自行車流動性(上)
上面的代碼使用了一種動態的顏色方案,這取決于站點的容量。我們還可以根據每個站點的出發和到達次數,為這些圓形標記實現動態半徑方案。我們可以得到我們所稱的密度圖,顯示每個車站的凈出發/到達人數。
def DensityMap(stations, cnt_departure, cnt_arrival): London = [51.506949, -0.122876] map = folium.Map(location = London, zoom_start = 12, tiles = "CartoDB dark_matter") stations['Total Departure'] = cnt_departure stations['Total Arrival'] = cnt_arrival for index, row in stations.iterrows(): net_departure = row['Total Departure'] - row['Total Arrival'] _radius = np.abs(net_departure) if np.isnan(_radius): _radius = 0 if net_departure > 0: _color= '#E80018' # target red else: _color= '#81D8D0' # tiffany blue lat, lon = row['lat'], row['lon'] _popup = '('+str(row['capacity'])+'/'+str(int(_radius))+') '+row['station_name'] folium.CircleMarker(location = [lat,lon], radius = _radius, popup = _popup, color = _color, fill_opacity = 0.5).add_to(map) return map
我在這里使用了一種不同的配色方案(target red和tiffany blue在美國都是注冊商標的顏色)來顯示某個車站的發車數量是否大于或小于進站數量。大圈標記表示較大的出發-到達差異。
讓我們看看早上和晚上高峰時間的密度地圖:
# Select peak hours TimeSlice = [25,53] # morning and evening keyword = ['map_morning', 'map_evening'] # Journeys depart between 0820 and 0859, and between 1740 and 1819 for ts, kw in zip(TimeSlice, keyword): df_1 = df[df["TimeSlice"] == ts] df_2 = df[df["TimeSlice"] == (ts+1)] df_target = df_1.append(df_2) cnt_departure = df_target.groupby("id_start").count().iloc[:,0] cnt_arrival = df_target.groupby("id_end").count().iloc[:,0] vars()[kw] = DensityMap(stations, cnt_departure, cnt_arrival)
早高峰密度圖
晚高峰時間的密度圖
密度圖可以在https://edenau.github.io/maps/Density-morning/和https://edenau.github.io/maps/Density-weight/上找到。
前面提到的所有地圖都只關注站點,而不是行程,但是我們也可以通過所謂的連接地圖來可視化行程,通過簡單地在地圖上繪制完成的行程。沒有深入研究很多細節:
連接圖
我們還可以通過folium.LayerControl()添加多個連接層,以分隔經常使用和不經常使用的路徑層。
多層連接圖
連接圖可以在https://edenau.github.io/maps/connection-morning-layers/上找到。
到目前為止,我們已經演示了如何通過圖表來可視化時間和分布信息,以及通過各種地圖來可視化空間信息。但是如果我們在連續的時間實例上生成多個映射呢?我們可以使用動畫可視化時空信息!
生成的地圖是.html文件中的web地圖。其目的是:
為每個時間實例生成一個地圖,在web瀏覽器上瀏覽,截圖并保存圖片,然后將所有圖片鏈接一起作為視頻或.gif文件。
我們將通過selenium實現web瀏覽和屏幕捕獲過程的自動化。。我們還需要一個網絡驅動程序,作為一個Chrome用戶,我選擇了Chrome driver。
from selenium import webdriver def a_frame(i, frame_time, data): my_frame = get_image_map(frame_time, data) # Save the web map delay = 5 # give it some loading time fn = 'frame_{:0>5}'.format(i) DIR = 'frames' f = DIR + '/' + fn + '.html' tmpurl='file://{path}/{mapfile}'.format(path=os.getcwd()+ '/frames',mapfile=fn) my_frame.save(f) # Open the web map and take screenshot browser = webdriver.Chrome() browser.get(tmpurl) time.sleep(delay) f = DIR + '/' + fn + '.png' browser.save_screenshot(f) browser.quit() f = 'frames/frame_{:0>5}.png'.format(i) image = Image.open(io.BytesIO(f)) draw = ImageDraw.ImageDraw(image) font = ImageFont.truetype('Roboto-Light.ttf', 30) # Add text on picture draw.text((20, image.height - 50), 'Time: {}'.format(frame_time), fill=(255, 255, 255), font=font) # Write the .png file dir_name = "frames" if not os.path.exists(dir_name): os.mkdir(dir_name) image.save(os.path.join(dir_name, 'frame_{:0>5}.png'.format(i)), 'PNG') return image
然后我們可以用ffmpeg制作視頻或gif。對于Mac用戶來說,安裝ffmpeg在自制軟件的幫助下幾乎不費什么力氣
自制程序會安裝你需要的東西,而蘋果不會。
安裝Homebrew(使用單個命令)后,只需鍵入
$ brew install ffmpeg
還有,喂!要創建.mp4文件,請嘗試
$ ffmpeg -r 10 -i frames/frame_%05d.png -c:v libx264 -vf fps=25 -crf 17 -pix_fmt yuv420p video.mp4
對于.gif文件,請嘗試
$ ffmpeg -y -t 3 -i frames/frame_%05d.png \ -vf fps=10,scale=320:-1:flags=lanczos,palettegen palette.png $ ffmpeg -r 10 -i frames/frame_%05d.png -i palette.png -filter_complex \ "fps=10,scale=720:-1:flags=lanczos[x];[x][1:v]paletteuse" animation.gif
查看全天的密度地圖動畫:
全天的密度地圖動畫
以及不同時期的行程動畫:
早上的行程動畫
晚上的行程動畫
倫敦的自行車共享系統使用柱形圖、密度圖、連接圖和動畫進行可視化。
Python的抽象使得它成為一個非常好的時空數據可視化工具(以犧牲計算時間為代價)。我利用了folium、selenium、chromedriver、brew、ffmpeg,最重要的是,利用了Vincent代碼的部分構建塊來實現這一點。
歡迎關注ATYUN官方公眾號
商務合作及內容投稿請聯系郵箱:bd@atyun.com
要發表評論,您必須先登錄。