Tự Học Data Science · 16/03/2024 0

04.13 Geographic Data with Basemap

Quy chiếu bản đồ

Điều quan trọng nhất cần quyết định khi sử dụng bản đồ là sử dụng phương pháp ánh xạ nào.Bạn có thể quen thuộc với thực tế là không thể ánh xạ một bản đồ hình cầu, ví dụ như bản đồ Trái Đất, lên một bề mặt phẳng mà không làm méo mó nó hoặc làm mất tính liên tục.Những phương pháp ánh xạ này đã được phát triển trong suốt lịch sử nhân loại, và có rất nhiều lựa chọn!Tùy thuộc vào mục đích sử dụng ánh xạ bản đồ, có những đặc điểm cần được duy trì (ví dụ như hướng, diện tích, khoảng cách, hình dạng, hoặc những yếu tố khác).

Gói Basemap triển khai một số hàng chục phép chiếu như vậy, tất cả được tham chiếu bằng một mã định dạng ngắn.Ở đây chúng tôi sẽ tóm tắt một số phương pháp phổ biến hơn.

Chúng ta sẽ bắt đầu bằng việc định nghĩa một tiện ích để vẽ bản đồ thế giới cùng với các đường kinh độ và vĩ độ:

from itertools import chaindef draw_map(m, scale=0.2):    # draw a shaded-relief image    m.shadedrelief(scale=scale)        # lats and longs are returned as a dictionary    lats = m.drawparallels(np.linspace(-90, 90, 13))    lons = m.drawmeridians(np.linspace(-180, 180, 13))    # keys contain the plt.Line2D instances    lat_lines = chain(*(tup[1][0] for tup in lats.items()))    lon_lines = chain(*(tup[1][0] for tup in lons.items()))    all_lines = chain(lat_lines, lon_lines)        # cycle through these lines and set the desired style    for line in all_lines:        line.set(linestyle='-', alpha=0.3, color='w')

Các quang tâm trụ

Các phép chiếu bản đồ đơn giản nhất là phép chiếu trực giao, trong đó đường viễn và đường kinh độ được ánh xạ lần lượt thành các đường ngang và dọc.Loại ánh xạ này mô phỏng khu vực xích đạo khá tốt, nhưng dẫn đến sai biệt rất lớn gần cực.Khoảng cách giữa các đường vĩ độ được biểu diễn khác nhau giữa các phép chiếu trực giao khác nhau, dẫn đến các thuộc tính bảo tồn khác nhau và sai biệt khác nhau gần cực.Trong hình sau, chúng tôi chỉ ra một ví dụ về phép chiếu trực giao cách xa, ựa trên tỷ lệ độ cao bảo tồn các khoảng cách dọc theo các đường kinh tuyến.Các phép chiếu trực giao khác bao gồm phép chiếu Mercator (projection='merc') và phép chiếu trực giao bằng diện tích (projection='cea').

fig = plt.figure(figsize=(8, 6), edgecolor='w')m = Basemap(projection='cyl', resolution=None,            llcrnrlat=-90, urcrnrlat=90,            llcrnrlon=-180, urcrnrlon=180, )draw_map(m)
ảnh ví dụ - data science lại blog của lưu

Các đối số bổ sung cho Basemap cho cảnh này chỉ định vĩ độ (lat) và kinh độ (lon) của góc dưới bên trái (llcrnr) và góc trên bên phải (urcrnr) của bản đồ mong muốn, tính bằng đơn vị độ.

Phép chiếu giả hình trụ

Các phép chiếu giả tưởng thư cylindrinhiều nhẹ nhàng yêu cầu rằng các vĩ độ (đường vĩ độ không đổi) phải giữ nguyên đứng; điều này có thể mang lại thuộc tính tốt hơn gần cực của phép chiếu.Phép chiếu Mollweide (giá trị “projection=’moll'”) là một ví dụ thông thường về điều này, trong đó tất cả các vĩ độ là cung ellip.Nó được xây dựng sao cho bảo tồn diện tích trên bản đồ: mặc dù có các biến dạng gần cực, diện tích các mảnh nhỏ phản ánh diện tích thực sự.Các phép chiếu giả-tuylô là phép chiếu sin (kí hiệu “projection=’sinu'”) và phép chiếu Robinson (kí hiệu “projection=’robin'”).

fig = plt.figure(figsize=(8, 6), edgecolor='w')m = Basemap(projection='moll', resolution=None,            lat_0=0, lon_0=0)draw_map(m)
ảnh ví dụ - data science lại blog của lưu

Các đối số bổ sung cho Basemap ở đây liên quan đến vĩ độ trung tâm (lat_0) và kinh độ trung tâm (lon_0) cho bản đồ mong muốn.

Phép chiếu phối cảnh

Các chiếu phối được xây dựng bằng cách sử dụng một điểm chiếu phối cụ thể, tương tự như khi bạn chụp ảnh Trái đất từ một điểm cụ thể trong không gian (một điểm mà, đối với một số chiếu phối, kỹ thuật thực ra nằm trong Trái đất!).Một ví dụ phổ biến là chiếu phối đồng phẳng (projection='ortho'), nó hiển thị một mặt của quả địa cầu nhìn từ một người xem ở khoảng cách rất xa. Do đó, nó chỉ có thể hiển thị nửa quả địa cầu trong một lần.Các chiếu phối dựa trên phối chiếu khác bao gồm chiếu phối gnomonic (projection='gnom') và chiếu phối stereographic (projection='stere').Chúng thường là những chiếu phối hữu ích nhất để hiển thị các phần nhỏ của bản đồ.

Đây là một ví dụ về phép chiếu đồng phẳng:

fig = plt.figure(figsize=(8, 8))m = Basemap(projection='ortho', resolution=None,            lat_0=50, lon_0=0)draw_map(m);
ảnh ví dụ - data science lại blog của lưu

Các phép chiếu hình nón

Một phép chiếu hình hình côn chiếu bản đồ vào một côn duy nhất, sau đó được mở ra.Điều này có thể dẫn đến các đặc tính cục bộ rất tốt, nhưng các vùng cách xa điểm tập trung của côn có thể trở nên biến dạng rất nhiều.Một ví dụ về điều này là phép chiếu Lambert Conformal Conic ( projection='lcc'), đã được chúng ta thấy trước đó trong bản đồ Bắc Mỹ.Nó chiếu bản đồ vào một côn được sắp xếp sao cho hai đường kinh bắc tiêu chuẩn (được chỉ định trong Basemap bằng lat_1lat_2) có khoảng cách đại diện tốt, với tỷ lệ giảm dần giữa chúng và tăng dần bên ngoài chúng.Một số phép chiếu hình côn hữu ích khác là phép chiếu hình côn đồng khoảng cách (projection='eqdc') và phép chiếu Albers cân bằng diện tích (projection='aea').Phép chiếu hình côn, giống như phép chiếu góc nhìn, thường là sự lựa chọn tốt cho việc đại diện cho các vùng nhỏ đến trung bình trên trái đất.

fig = plt.figure(figsize=(8, 8))m = Basemap(projection='lcc', resolution=None,            lon_0=0, lat_0=50, lat_1=45, lat_2=55,            width=1.6E7, height=1.2E7)draw_map(m)
ảnh ví dụ - data science lại blog của lưu

Các phép chiếu khác

Nếu bạn định làm nhiều công việc với các hình ảnh dựa trên bản đồ, tôi khuyến nghị bạn nên tìm hiểu về các phép chiếu khác có sẵn, cùng với các đặc tính, lợi ích và nhược điểm của chúng.Rất có thể, chúng có sẵn trong gói Basemap.Nếu bạn đào sâu vào chủ đề này, bạn sẽ tìm thấy một cộng đồng vi tính địa lý tuyệt vời, những người đam mê về đồ họa dựa trên bản đồ và sẵn sàng tranh luận hăng hái ủng hộ phép chiếu yêu thích của họ cho bất kỳ ứng dụng cụ thể nào!

Vẽ nền bản đồ

Trước đó, chúng ta đã thấy các phương thức bluemarble()shadedrelief() để chiếu hình ảnh toàn cầu lên bản đồ, cũng như các phương thức drawparallels()drawmeridians() để vẽ đường kinh và vĩ đạo không đổi.Gói Basemap chứa một loạt các chức năng hữu ích để vẽ đường biên của các yếu tố vật lý như lục địa, đại dương, hồ, sông, cũng như đường biên chính trị như các nước, các tiểu bang và quận của Hoa Kỳ.Dưới đây là một số chức năng vẽ có sẵn mà bạn có thể muốn khám phá bằng cách sử dụng tính năng trợ giúp của IPython:

None

Mức độ giới hạn vật lý và các cơ thể nước

  • drawcoastlines(): Vẽ đường bờ biển
  • drawlsmask(): Vẽ mặt nạ giữa đất liền và biển, để sử dụng khi chiếu ảnh trên một trong hai
  • drawmapboundary(): Vẽ ranh giới bản đồ, bao gồm màu nền cho đại dương
  • drawrivers(): Vẽ sông trên bản đồ
  • fillcontinents(): Tô màu lục địa với một màu đã cho; tùy chọn tô màu hồ với màu khác

Biên giới chính trị

  • drawcountries(): Vẽ biên giới quốc gia
  • drawstates(): Vẽ biên giới các tiểu bang của Hoa Kỳ
  • drawcounties(): Vẽ biên giới các quận của Hoa Kỳ

Tính năng Bản đồ

  • drawgreatcircle(): Vẽ đường tròn lớn giữa hai điểm
  • drawparallels(): Vẽ đường kinh độ
  • drawmeridians(): Vẽ đường vĩ độ
  • drawmapscale(): Vẽ thước đo tuyến tính trên bản đồ

Ảnh toàn cầu

  • bluemarble(): Dự án ảnh blue marble của NASA được chiếu lên bản đồ
  • shadedrelief(): Dự án ảnh shaded relief lên bản đồ
  • etopo(): Vẽ ảnh etopo relief lên bản đồ
  • warpimage(): Dự án ảnh do người dùng cung cấp lên bản đồ

Với các tính năng dựa trên ranh giới, bạn phải đặt độ phân giải mong muốn khi tạo hình ảnh Basemap.Đối số resolution của lớp Basemap đặt cấp độ chi tiết trong các ranh giới, có thể là 'c' (gồ ghề), 'l' (thấp), 'i' (trung bình), 'h' (cao), 'f' (đầy đủ), hoặc None nếu không sử dụng ranh giới nào.Sự lựa chọn này rất quan trọng: đặt ranh giới độ phân giải cao trên bản đồ toàn cầu, ví dụ, có thể rất chậm.

Đây là một ví dụ về việc vẽ ranh giới đất/lục địa và biểu hiện của tham số độ phân giải.Chúng ta sẽ tạo ra cả bản đồ có độ phân giải thấp và cao của đảo Skye tuyệt đẹp thuộc nước Scotland.Nó nằm ở 57,3°N, 6,2°W, và bản đồ có kích thước 90.000 × 120.000 kilômét thể hiện rõ nó:

fig, ax = plt.subplots(1, 2, figsize=(12, 8))for i, res in enumerate(['l', 'h']):    m = Basemap(projection='gnom', lat_0=57.3, lon_0=-6.2,                width=90000, height=120000, resolution=res, ax=ax[i])    m.fillcontinents(color="#FFDDCC", lake_color='#DDEEFF')    m.drawmapboundary(fill_color="#DDEEFF")    m.drawcoastlines()    ax[i].set_title("resolution='{0}'".format(res));
ảnh ví dụ - data science lại blog của lưu

Lưu ý rằng các đường bờ biển độ phân giải thấp không phù hợp cho mức độ phóng to này, trong khi độ phân giải cao hoạt động tốt.Mức độ thấp sẽ hoạt động tốt cho một cái nhìn toàn cầu, và sẽ nhanh hơn nhiều so với việc tải dữ liệu biên giới độ phân giải cao cho toàn bộ hành tinh!Điều này có thể đòi hỏi một số thử nghiệm để tìm tham số độ phân giải chính xác cho một cái nhìn cụ thể: con đường tốt nhất là bắt đầu với một biểu đồ độ phân giải thấp nhanh chóng và tăng độ phân giải khi cần thiết.

Plotting Data trên Bản đồ

Có lẽ một trong những công cụ hữu ích nhất của bộ công cụ Basemap là khả năng vẽ lên nền bản đồ cho một loạt dữ liệu khác nhau.Đối với việc vẽ đồ thị đơn giản và văn bản, bất kỳ hàm plt nào cũng hoạt động trên bản đồ; bạn có thể sử dụng thể hiện Basemap để chuyển đổi tọa độ vĩ độ và kinh độ sang tọa độ (x, y) để vẽ đồ thị bằng plt, như chúng ta đã thấy trong ví dụ Seattle trước đó.

Ngoài ra, còn có nhiều chức năng riêng biệt dành cho bản đồ được cung cấp như các phương thức của Basemap instance.Các chức năng này hoạt động tương tự như những hàm tương ứng trong Matplotlib tiêu chuẩn, nhưng có một đối số Boolean bổ sung latlon, nếu được đặt thành True cho phép bạn truyền các vĩ độ và kinh độ gốc cho phương thức, thay vì tọa độ dự án (x, y).

Một số phương thức đặc thù cho bản đồ bao gồm:

  • contour()/contourf() : Vẽ đường contour hoặc vùng contour
  • imshow(): Vẽ một hình ảnh
  • pcolor()/pcolormesh() : Vẽ đồ thị màu giả cho lưới không đều/đều
  • plot(): Vẽ đường và/hoặc điểm đánh dấu.
  • scatter(): Vẽ điểm với điểm đánh dấu.
  • quiver(): Vẽ vector.
  • barbs(): Vẽ mũi gió.
  • drawgreatcircle(): Vẽ đường tròn lớn.

Chúng ta sẽ thấy một số ví dụ về một số điểm này khi chúng ta tiếp tục.Để biết thêm thông tin về những chức năng này, bao gồm một số biểu đồ ví dụ, xem tài liệu trực tuyến về Basemap.

Tên mẫu: Các thành phố ở California

Nhớ rằng trong Tùy chỉnh Huy hiệu đồ thị, chúng ta đã chứng minh việc sử dụng kích thước và màu sắc trong một biểu đồ phân tán để truyền tải thông tin về vị trí, kích thước và dân số của các thành phố California.Ở đây, chúng ta sẽ tạo lại biểu đồ này, nhưng sử dụng Basemap để đặt dữ liệu vào bối cảnh.

Chúng ta bắt đầu bằng việc tải dữ liệu, như chúng ta đã làm trước đây:

import pandas as pdcities = pd.read_csv('data/california_cities.csv')# Extract the data we're interested inlat = cities['latd'].valueslon = cities['longd'].valuespopulation = cities['population_total'].valuesarea = cities['area_total_km2'].values

Tiếp theo, chúng ta thiết lập hệ thống chiếu bản đồ, tạo ra các điểm dữ liệu và sau đó tạo một colorbar và hướng dẫn:

# 1. Draw the map backgroundfig = plt.figure(figsize=(8, 8))m = Basemap(projection='lcc', resolution='h',             lat_0=37.5, lon_0=-119,            width=1E6, height=1.2E6)m.shadedrelief()m.drawcoastlines(color='gray')m.drawcountries(color='gray')m.drawstates(color='gray')# 2. scatter city data, with color reflecting population# and size reflecting aream.scatter(lon, lat, latlon=True,          c=np.log10(population), s=area,          cmap='Reds', alpha=0.5)# 3. create colorbar and legendplt.colorbar(label=r'$\log_{10}({\rm population})$')plt.clim(3, 7)# make legend with dummy pointsfor a in [100, 300, 500]:    plt.scatter([], [], c='k', alpha=0.5, s=a,                label=str(a) + ' km$^2$')plt.legend(scatterpoints=1, frameon=False,           labelspacing=1, loc='lower left');
ảnh ví dụ - data science lại blog của lưu

Đoạn mã HTML trên cho chúng ta thấy đâu là những nơi có dân số đông đúc ở California: họ tập trung gần bờ biển ở vùng Los Angeles và San Francisco, xoay quanh các tuyến đường cao tốc ở thung lũng trung tâm phẳng bằng và hoàn toàn tránh các vùng núi dọc theo biên giới của tiểu bang.

Ví dụ: Dữ liệu Nhiệt độ Mặt đất

Như một ví dụ về việc trực quan hóa một số dữ liệu địa lý liên tục hơn, hãy xem xét “vòng xoáy cực” tác động vào nửa phía đông của Hoa Kỳ vào tháng 1 năm 2014.Một nguồn tài nguyên tuyệt vời cho bất kỳ loại dữ liệu khí hậu nào là Goddard Institute for Space Studies của NASA.Ở đây, chúng ta sẽ sử dụng dữ liệu nhiệt độ GIS 250, mà chúng ta có thể tải xuống bằng cách sử dụng các lệnh dòng lệnh (những lệnh này có thể phải được sửa đổi trên các máy tính Windows).Dữ liệu được sử dụng ở đây đã được tải xuống vào ngày 12/06/2016 và kích thước tệp tin là khoảng 9MB:

# !curl -O http://data.giss.nasa.gov/pub/gistemp/gistemp250.nc.gz# !gunzip gistemp250.nc.gz

Dữ liệu được lưu dưới định dạng NetCDF, có thể đọc trong Python bằng thư viện netCDF4.Bạn có thể cài đặt thư viện này như được minh họa dưới đây

$ conda install netcdf4

Chúng tôi đọc dữ liệu như sau:

from netCDF4 import Datasetdata = Dataset('gistemp250.nc')

Tệp chứa nhiều giá trị nhiệt độ toàn cầu trên nhiều ngày khác nhau; chúng ta cần chọn chỉ mục của ngày mà chúng ta quan tâm – trong trường hợp này, ngày 15 tháng 1 năm 2014:

from netCDF4 import date2indexfrom datetime import datetimetimeindex = date2index(datetime(2014, 1, 15),                       data.variables['time'])

Bây giờ chúng ta có thể tải dữ liệu vĩ độ và kinh độ, cũng như nhiệt độ bất thường cho chỉ số này:

lat = data.variables['lat'][:]lon = data.variables['lon'][:]lon, lat = np.meshgrid(lon, lat)temp_anomaly = data.variables['tempanomaly'][timeindex]

Cuối cùng, chúng ta sẽ sử dụng phương thức pcolormesh() để vẽ một lưới màu của dữ liệu.Chúng ta sẽ xem bản đồ vùng Bắc Mỹ và sử dụng một bản đồ nền có hiệu ứng đổ bóng.Lưu ý rằng đối với dữ liệu này chúng ta đã chọn một bản đồ màu phân tán, có một màu trung lập tại giá trị không và hai màu tương phản tại các giá trị âm và dương.Chúng ta cũng sẽ nhẹ nhàng vẽ đường bờ biển trên các màu cho tham khảo:

fig = plt.figure(figsize=(10, 8))m = Basemap(projection='lcc', resolution='c',            width=8E6, height=8E6,             lat_0=45, lon_0=-100,)m.shadedrelief(scale=0.5)m.pcolormesh(lon, lat, temp_anomaly,             latlon=True, cmap='RdBu_r')plt.clim(-8, 8)m.drawcoastlines(color='lightgray')plt.title('January 2014 Temperature Anomaly')plt.colorbar(label='temperature anomaly (°C)');
ảnh ví dụ - data science lại blog của lưu

Dữ liệu vẽ nên một hình ảnh về các hiện tượng nhiệt độ cực đoan và địa phương đã xảy ra trong tháng đó.Nửa phía đông của Hoa Kỳ lạnh hơn bình thường nhiều, trong khi nửa phía tây và Alaska ấm hơn rất nhiều.Các vùng không có nhiệt độ ghi lại được hiển thị trên nền bản đồ.