This article is from Python Big data analysis, written by Feffrey

In this paper, the corresponding code and data has been uploaded to my lot warehouse https://github.com/CNFeffery/DataScienceStudyNotes [1]

Published:

Python letter project | geopandas based spatial data analysis, data JieGouPian

Python letter project | geopandas based spatial data analysis – coordinate frame of reference

Python letter project | geopandas based spatial data analysis – file IO

1 introduction

In previous articles, we have learned more about data structures, coordinate reference frames, and file IO in geopandas.

When you take a piece of vector data and start analyzing it, visualizing it is an important step in the exploration and understanding of the data.

In this fourth article in the series on Spatial data analysis based on geopandas, you will learn about basic visualizations based on geopandas.

Like this:

Case map

2 Basic Visualization

Geopandas uses matplotlib as a plotting back end to visualize a GeoSeries or GeoDataFrame using the plot() method, making basic visualization a simple task.

This is combined with some additional elements of Matplotlib to create even more elegant visualizations, as described below.

2.1 GeoSeries

GeoSeries does not involve the mapping of numerical values to visual elements because there is only a single row of geometric objects, so the visualization is relatively simple.

Let’s take a look at the geoseries.plot () parameters, which will be easier to understand if you already know something about Matplotlib:

Figsize: A tuple or list in the form of (width, height) that controls the width and height of the drawn image, both in inches

Facecolor: Sets the geometry object’s fill color, accepts color name and hexadecimal color, does not fill color when set to ‘None’

Edgecolor: Set the boundary color of geometric objects. The effect of the opposite data and point data is obvious. It is not recommended to set this parameter for line data

Linewidth: Set the boundary width of the geometric object. The effect of the opposite data and point data is obvious. It is not recommended to set this parameter for line data

Linestyle: String type used to set geometric object boundaries and line lines for line data

Markersize: Sets the size of point data

Marker: String type used to set the shape of point data

Alpha: Sets the global color transparency of the corresponding geometry object, 0-1, the larger the more opaque

Label: Applies to pure line data or point data, when legends need to be added, and is used as the name of each object displayed in the legend

Hatch: character type, used to set the fill line style inside the surface data, as detailed in the following examples

Ax: matplotlib axes object. If multiple layers need to be superimposed on the same axis, this parameter is passed to the ax to be superimposed

Let’s take a closer look at each of these parameters with a practical example.

The data we used is China-shapefiles.zip, which is the territory of China + the Nine-dash line of the South China Sea. You can find it in the Github warehouse listed at the beginning of this article.

First, use the method of reading the data in the. Zip file introduced in the previous article to read the land and nine-dash line data we need respectively:

Note: Since each element in the original data China. SHP is not a single province but a plane, that is, some provinces containing many islands will be composed of several lines. Therefore, geopandas is used to fuse the separated planes into multiple planes according to the OWNER column, so that each row is corresponding to a complete province. More geographical operations will be introduced in the subsequent corresponding articles.

import geopandas as gpd
importMatplotlib. pyplot as PLT # set matplotlib plotting mode to embedded %matplotlib inline plt.rcparams ["font.family"] = "SimHei"China = gdp.read_file ()'zip://china-shapefiles.zip! china-shapefiles/china.shp',
                     encoding='utf-8'(resolvent (by=); (resolvent (by=)); (resolvent (by=))'OWNER').reset_index(drop=False) # nine_lines = gpd.read_file('zip://china-shapefiles.zip! china-shapefiles/china_nine_dotted_line.shp',
                          encoding='utf-8')
Copy the code

Plot () method is used to superimpose the original map without any personalized parameters (CRS is EPSG:4326, namely WGS84) :

Ax = PLT. Subplots (figsize=(12.8))
ax = china.geometry.plot(ax=ax)
ax = nine_lines.geometry.plot(ax=ax)
fig.savefig(Figure 1. PNG ', dpi=300)
Copy the code

Figure 1

Step by step, we will demonstrate the parameters that apply to geoseries.plot () :

  • Step1: choose the right projection

In the previous article about coordinate reference system, we learned about the importance of projection when drawing maps. Referring to the suggestions of hypergraph on projection selection for drawing Chinese maps [2], we used Albers Equal Area commonly used in drawing Chinese maps as projection, and found its information in PROJ [3] :

Figure 2

Pass its PROJ information into the to_crs() method (note that the upper central longitude 105 degrees and the standard latitude range 25 to 47 degrees will be added) and unify it into all layers:

# define CRS albers_proj ='+proj=aea +lat_1=25 +lat_2=47 +lon_0=105'

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax)
fig.savefig('FIG. 3. PNG', dpi=300)
Copy the code

Figure 3

The shape is more realistic and looks more natural.

  • Step2: Modify the color

Now let’s adjust the color of the filling and contour of the surface data, and the color of the line data (nine segments).

And set transparency alpha for each of them. Here, the axes are removed for aesthetic purposes:

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  alpha=0.4)
ax.axis('off') # Remove the axis savefig(Figure 4. PNG ', dpi=300)
Copy the code

Figure 4.

  • Step3: modify the line type and line width

Next we modify the line type and line width based on figure 4.

The linear parameters linestyle and Matplotlib are exactly the same, and the corresponding styles of different choices are shown in Figure 5:

Figure 5

Refer to Figure 5, we keep the nine-dash line unchanged but increase its width appropriately to 3, and set the contour of the surface data as ‘–‘ :

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)
ax.axis('off') # Remove the axis savefig(Figure 6. PNG ', dpi=300)
Copy the code

Figure 6.

  • Step4: Modify the face filling shadow line style

Next we use the hatch parameter to modify the face data fill shadow style.

The main styles correspond to the following, such as ‘-‘ for horizontal fill:

Figure 7.

Referring to Figure 7, we set the fill shadow style for the face data to ‘x’.

It is worth mentioning that the hatch parameter can increase the shadow density by increasing the number of characters for the same shadow mode.

Hatch =’x’

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             hatch='x',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)
ax.axis('off') # Remove the axis savefig('figure 8. PNG', dpi=300)
Copy the code

Figure 8.

Hatch =’ XXXX ‘draws the following map:

Figure 9.

Even more interesting, different shadow modes can be mixed together.

For example, we set hatch=’x**’ :

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             hatch='x**',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)
ax.axis('off') # Remove the axis savefig('figure 10. PNG', dpi=300)
Copy the code

Figure 10.

  • Step5: Point data individuation

Markersize and marker in geoseries.plot () are configured specifically for point data, but there is no point data in our data.

To illustrate, let’s generate point data from existing data. My initial idea was to generate the center of gravity for each surface as the central point of each province:

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             hatch='xxxx',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)
ax = china.geometry.centroid.to_crs(albers_proj).plot(ax=ax,
                                                      facecolor='black')
ax.axis('off') # Remove the axis savefig('figure 11. PNG', dpi=300)
Copy the code

Figure 11.

But a closer look reveals that some provinces, such as Gansu, have an awkward outward focus.

Because it is a very typical non-convex polygon (the line between any two points inside a convex polygon does not cross its boundary), the calculated center of gravity falls on the outside.

Geopandas provides us with the Representative_point () method for figuring out a typical point inside any polygon:

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             hatch='xxxx',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)
ax = china.geometry.representative_point() \
                   .to_crs(albers_proj) \
                   .plot(ax=ax, 
                         facecolor='black')
ax.axis('off') # Remove the axis savefig('figure 12. PNG', dpi=300)
Copy the code

Figure 12

At this time, it can be found that the generated points meet our requirements. On this basis, we use marker to adjust the style of point data as shown in Figure 13:

Figure 13

For example, if we change the marker to ‘*’ and adjust other parameters to make the point more obvious,

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             hatch='xxxx',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)
ax = china.geometry.representative_point() \
                   .to_crs(albers_proj) \
                   .plot(ax=ax, 
                         facecolor='white',
                         edgecolor='black',
                         marker=The '*',
                         markersize=200,
                         linewidth=0.5)
ax.axis('off') # Remove the axis savefig('figure 14. PNG', dpi=300)
Copy the code

Figure 14

  • Step6: Legend and text annotation

Next we’ll learn how to add legends and text to a map.

To see clearly we remove the shadow fill and reduce the size of the dot, then add the parameter label for the nine-dash line and the dot data, and finally add the legend with ax.legend() and set the parameters:

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4,
                                                  label=South China Sea nine-dash Line)
ax = china.geometry.representative_point() \
                   .to_crs(albers_proj) \
                   .plot(ax=ax, 
                         facecolor='white',
                         edgecolor='black',
                         marker=The '*',
                         markersize=100,
                         linewidth=0.5,
                         label='Provincial Unit'# set the legend header size separately in advance plt.rcparams ['legend.title_fontsize'] = 14Ax. legend(title=)"Legend", loc='lower left', ncol=1, shadow=True)

ax.axis('off') # Remove the axis savefig('figure 15. PNG', dpi=300)
Copy the code

Figure 15

Next we replace the star that marks each provincial unit with a name text.

The text() method in Matplolib is used here, which passes in the x, y and text content of the corresponding point to the loop. Ha and VA are used to adjust the horizontal and vertical alignment of the text, and size is used to adjust the text size.

More specific parameters can be found in the matplotlib website, which is not covered in this article:

fig, ax = plt.subplots(figsize=(12.8))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4,
                                                  label=South China Sea nine-dash Line) # Add text to the map according to the representative point of the converted projectionforIndependence idx, _ in enumerate (China) geometry) representative_point () to_crs (albers_proj) : # extraction unit at the provincial levelif ('the' in china.loc[idx, 'OWNER'] or ', ' in china.loc[idx, 'OWNER']) \
    and china.loc[idx, 'OWNER'] != Inner Mongolia Autonomous Region:
        region = china.loc[idx, 'OWNER'] [:2]
    else:
        region = china.loc[idx, 'OWNER'].replace('province'.' ') \
                                        .replace('the city'.' ') \
                                        .replace('Autonomous region'.' ')

    ax.text(_.x, _.y, region, ha="center", va="center", size=6# set the legend header size separately in advance plt.rcparams ['legend.title_fontsize'] = 14Ax. legend(title=)"Legend", loc='lower left', ncol=1, shadow=True)

ax.axis('off') # Remove the axis savefig('figure 16. PNG', dpi=300)
Copy the code

Figure 16

  • Step7: Add a minimap

If you pay attention to it, you will remember that the South China Sea area is shown separately in the lower right corner of the map.

Geopandas is very easy to make, just add add_axes() to the submap area in Matplotlib.

Let’s take a look at the function of add_axes(), the most important parameter of which is rect, which creates sub-areas in the graph bed by passing in shapes such as (bottom, left, width, height).

Let’s start with the simple example below, first we created a square canvas using plt.figure() and applied add_axes((0, 0, 1, 1)) on the canvas:

Figure 17

See how it works?

The first two digits of the (0, 0, 1, 1) we pass in actually represent the scale of the lower left corner coordinates of the subimage region on the entire canvas!

The last two represent the width and length of the subimage area relative to the entire canvas!

Then we open up a new subarea for the FIG and write in the center of the new subarea:

Figure 18

The lower left coordinate of the new subimage area is located at the midpoint of the bottom edge of the canvas with a scale of 0.5 in length and width, so the effect is as shown in the picture.

With that in mind, here we can draw a map of China with a small map:

First of all, we need to limit the latitude and longitude range of the Maps of China and the illustrations of the South China Sea respectively. Since there is no strict scope stipulation, here we roughly define the minimum and maximum latitude and longitude of the Map of China and the illustration of south China Sea, generate GeoDataFrame, add vector information, and finally carry out appropriate projection transformation:

from shapely.geometry import Point

bound = gpd.GeoDataFrame({
    'x': [80.150.106.5.123].'y': [15.50.2.8.24.5]}) # add vector column geometry = bound. Apply (lambda row: Point([row])'x'], row['y']]), axis=1CRS bound. CRS ='EPSG:4326'To_crs (albers_proj, inplace=True) boundCopy the code

Figure 19

The next steps are easy to follow. Just transfer the map-drawing techniques from the previous part to the two subgraphs:

fig = plt.figure(figsize=(8.8Create a subgraph that covers the entire canvas1
ax = fig.add_axes((0.0.1.1))
ax = china.geometry.to_crs(albers_proj).plot(ax=ax,
                                             facecolor='grey',
                                             edgecolor='white',
                                             linestyle=The '-',
                                             alpha=0.8)
ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4,
                                                  label=South China Sea nine-dash Line# set the legend header size separately in advance plt.rcparams ['legend.title_fontsize'] = 14Ax. legend(title=)"Legend", loc='lower left', ncol=1, shadow=True)

ax.axis('off'# Remove the axes ax.set_xlim(unbound. Geometry [0].x, bound.geometry[1].x)
ax.set_ylim(bound.geometry[0].y, bound.geometry[1Ax_child = FIG. Add_axes ([ax_child = FIG. Add_axes ([0.75.0.15.0.2.0.2])
ax_child = china.geometry.to_crs(albers_proj).plot(ax=ax_child,
                                                   facecolor='grey',
                                                   edgecolor='white',
                                                   linestyle=The '-',
                                                   alpha=0.8)
ax_child = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax_child,
                                                        edgecolor='grey',
                                                        linewidth=3,
                                                        alpha=0.4,
                                                        label=South China Sea nine-dash Line)

ax_child.set_xlim(bound.geometry[2].x, bound.geometry[3].x)
ax_child.set_ylim(bound.geometry[2].y, bound.geometry[3[] ax_child.set_xticks([]) ax_child.set_yticks([]) FIG. Savefig ([])'figure 20. PNG', dpi=300)
Copy the code

Figure 20

2.2 GeoDataFrame

Following the introduction of mapping around GeoSeries, let’s look at the visualization around GeoDataFrame in geopandas.

Compared with GeoSeries, GeoDataFrame has multi-column data, that is, we can map the numerical information of auxiliary columns to the visual elements of the map. Therefore, more parameters are added based on the common parameters of GeoSeries:

Column: Specifies the numeric information used to map the visual elements of the map. It can be the column name corresponding to the GeoDataFrame, or it can be directly passed in a sequence of values corresponding to the geometry object. The default is None

Cmap: The color scheme used when passing in mapped visual elements, as described below

Categorical: bool. True indicates that the specified mapping object column takes a discrete representation. This is valid for numeric columns and automatically changes to True when the corresponding object is classified

Legend: bool. If True, legends will be added to the map

Scheme: STR type, which is used to specify the numerical partitioning scheme for the hierarchical color setting of the regional distribution map. Details are described in the following sections

K: int, used to specify the number of levels in a layered setting

Vmin: None or float, used to specify the lower limit of the value range of the layered color. The default value is None, which uses the minimum value in the corresponding data as the lower limit

Vmax: None or float, used to specify the upper limit of the value range of the layered color. The default is None, which is the upper limit of the maximum value in the corresponding data

Legend_kwds: word typical, passing in personalization parameters associated with legends

Classification_kwds: Word typical, passed in personalization parameters related to hierarchical color

Missing_kwds: word typical, pass in personalization parameters related to missing value processing, used to personalize the visual mapping of missing value parts

Again, we start with a practical example, where we use COVID-19 epidemic data, data source [4].

Similarly, you can find the data used below in the Github repository listed at the beginning of this article.

First of all, we preprocessed the original data to obtain the latest updated data of each province:

Figure 21

That gives us the data we need.

2.2.1 Regional distribution map and stratified color

Choropleth Map (Choropleth Map) refers to the hierarchical division based on specified attributes, and the corresponding hierarchical mapping to the color of the corresponding geometric object.

Next, we will first associate the table data processed above with China.

Because geopandas supports joining operations for PANDAS, we use pd.merge() to join two tables with provincial unit names called keys:

Note: Since the table will become PANDAS.DataFrame, it will be converted back to GeoDataFrame.

data_with_geometry = pd.merge(left=temp.replace('the'.'Macao Special Administrative Region'),
                              right=china,
                              left_on='provinceName',
                              right_on='OWNER',
                              how='right'
                              ).loc[:, ['provinceName'.'provinceEnglishName'.'province_confirmedCount'.'province_suspectedCount'.'province_curedCount'.'province_deadCount'.'geometry'[] # transform data from DataFrame to GeoDataFrame data_with_geometry = GPD'EPSG:4326')
data_with_geometry.head()
Copy the code

Figure 22

Given the data, we foolhardy passed the province_confirmedCount (number of confirmed confirmations in the region) directly to column as a mapping value, selected CMAP for the classic Reds gradient, and adjusted some of the parameters that we are already familiar with from previous articles.

Let’s see what we get:

Figure 23

Why do we get such strange results? Let’s break down the problems one by one:

  • Where has Taiwan gone?

If you are careful, you will surely find that Taiwan, our treasure island, is missing. This is not because it is missing from our geometric objects. Every inch of China is indispensable.

What really makes it disappear is that the data of Hong Kong and Taiwan are missing in our original data. The right-link method we used in the previous connection process allows us to retain all the land.

However, Taiwan and Hong Kong are missing data and the corresponding data location is NaN, so the value becomes the default white during the mapping to color, in which case the missing_kwds parameter is useful:

fig, ax = plt.subplots(figsize=(12.12To_crs (albers_proj).plot(ax=ax, column='province_confirmedCount',
                                                 cmap='Reds',
                                                 missing_kwds={
                                                     "color": "lightgrey"."edgecolor": "black"."hatch": ""
                                                 })

ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)

ax.axis('off')

fig.savefig('figure 24. PNG', dpi=300)
Copy the code

Figure 24

In the missing_KWDS parameter in dictionary format, we set the base color of the missing value area with color and the line color of the missing value area with edgecolor.

I also used Hatch to set a shadow fill style so that it was clear where missing data was recorded.

  • Why only Hubei province is so dark?

Indeed, such a map gives us the impression that Hubei province is very serious and other places are no different. We add a numerical color reference based on Figure 24:

fig, ax = plt.subplots(figsize=(12.12))

ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,
                                                 column='province_confirmedCount',
                                                 cmap='Reds',
                                                 missing_kwds={
                                                     "color": "lightgrey"."edgecolor": "black"."hatch": ""
                                                 },
                                                 legend=True)

ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)

ax.axis('off')

fig.savefig('figure 25. PNG', dpi=300)
Copy the code

Figure 25

This makes it clear that the original reason is that the data of Hubei province is too large, which makes all data except Hubei province are compressed to very light-colored areas when the value is mapped to the ordered color scale uniformly.

At this point, it comes to the topic of this summary – layered color, which involves the relevant core parameters Scheme and K, scheme determines the method of data layering.

It implements layering in geopandas by calling the methods used to layer data in the third-party package MapClassify).

For example, based on figure 25, let’s take our beloved ‘NaturalBreaks’ parameter and select k=5 as the number of breaks:

fig, ax = plt.subplots(figsize=(12.12))

ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,
                                                 column='province_confirmedCount',
                                                 cmap='Reds',
                                                 missing_kwds={
                                                     "color": "lightgrey"."edgecolor": "black"."hatch": ""
                                                 },
                                                 legend=True,
                                                 scheme='NaturalBreaks',
                                                 k=5)

ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)

ax.axis('off')

fig.savefig('figure 26. PNG', dpi=300)
Copy the code

Figure 26

As you can see, the color distribution in the regions is much milder, allowing us to see the differences in the severity of the disease in different regions.

At this time, it became discrete stratification, so the legend also changed from color card to more standard classification legend, but this legend is in the upper right corner by default, causing obvious occlusion to the map.

Legend_kwds and missing_KWDS labels are used to beautify the legend_KWds and missing_KWDS labels.

fig, ax = plt.subplots(figsize=(12.12))

ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,
                                                 column='province_confirmedCount',
                                                 cmap='Reds',
                                                 missing_kwds={
                                                     "color": "lightgrey"."edgecolor": "black"."hatch": ""."label": "Missing value"
                                                 },
                                                 legend=True,
                                                 scheme='NaturalBreaks',
                                                 k=5,
                                                 legend_kwds={
                                                     'loc': 'lower left'.'title': 'Number of confirmed cases'.'shadow': True
                                                 })

ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)

ax.axis('off')

fig.savefig('figure 27. PNG', dpi=300)
Copy the code

Figure 27

Now that our map is much better looking than it was at the beginning, we’ll add big headings, small headings and data captions.

And here’s a not-so-pretty but decent map of the epidemic:

fig, ax = plt.subplots(figsize=(12.12))

ax = data_with_geometry.to_crs(albers_proj).plot(ax=ax,
                                                 column='province_confirmedCount',
                                                 cmap='Reds',
                                                 missing_kwds={
                                                     "color": "lightgrey"."edgecolor": "black"."hatch": ""."label": "Missing value"
                                                 },
                                                 legend=True,
                                                 scheme='NaturalBreaks',
                                                 k=5,
                                                 legend_kwds={
                                                     'loc': 'lower left'.'title': 'Number of confirmed cases'.'shadow': True
                                                 })

ax = nine_lines.geometry.to_crs(albers_proj).plot(ax=ax,
                                                  edgecolor='grey',
                                                  linewidth=3,
                                                  alpha=0.4)

ax.axis('off')
plt.suptitle('Regional distribution of Cumulative confirmed COVID-19 cases', fontsize=24# add the highest level title plt.title('As at 27 February 2020', fontsize=18# add plt.tight_layout(pad=)4.5Ax.text () # adjust the spacing between headings- 2800000..1000000.'* Original data source: Dxy Garden, \n Missing data for Taiwan and Hong Kong 'FIG. Savefig ()'figure 28. PNG', dpi=300)
Copy the code

Figure 28

2.2.2 Implement creation with Matplotlib

Although Geopandas comes with such rich mapping capabilities, it is often not enough to build a map on its own. In order to achieve a more personalized effect, you need to combine the rich features in Matplotlib.

The following image is a personalized visualization that I made with a few features in Matplotlib, adding many elements. Due to limited space, the code is not released here. You can go to the Github repository at the beginning of this article to see all the code in this article, and try to use your favorite colors for the map:

Figure 29

2.2.3 Learn by imitation

Becoming a data visualization expert is not an easy task, but we can start by imitating the best work of other masters.

For example, Figure 30 is from Github warehouse [5], which contains many excellent works based on R, and Figure 30 is one of them, which visualizes the impact of the Australian fire:

Figure 30

Figure 31 below is a rough imitation of Figure 30 using geopandas.

The original R script used GGText for easy rich text generation, but I haven’t found a wheel of similar functionality in Python yet, so the text part is relatively simple:

Figure 31

The corresponding code is as follows, and the vector data used is the world map data with high accuracy collected by me:

world = gpd.read_file('world')
world['SOVEREI']

smoke_list = ['Denmark'.'France'.'Spain'.'Sweden'.'Norway'.'Germany'.'Finland'.'Poland'.'Italy'.'Greenland']
burnt_list = ['Latvia']

fig, ax = plt.subplots(figsize=(8.8))

crs = '+proj=moll +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'Ax = world[world]'SOVEREI'].isin(smoke_list)] \
                        .to_crs(crs) \
                        .plot(ax=ax,
                              facecolor='#d9c09e',
                              edgecolor='#c49c67',
                              linewidth=0.2Ax = world[world]'SOVEREI'].isin(burnt_list)] \
                        .to_crs(crs) \
                        .plot(ax=ax,
                              facecolor='#c82626',
                              edgecolor='#9d1e1e',
                              linewidth=0.2Ax = world[-(world[)'SOVEREI'].isin(smoke_list) | world['SOVEREI'].isin(burnt_list))] \
                         .to_crs(crs) \
                         .plot(ax=ax,
                               facecolor='lightgrey',
                               edgecolor='grey',
                               linewidth=0.05,
                               alpha=0.7)

ax.set_xlim([- 3200000..2300000])
ax.set_ylim([4100000.9000000])
ax.axis('off'# add plt.text()- 3*10支那6.5.5*10支那6.' ''The 2019/20 Fire in Australia burned bushland, forests and parks larger than Latvia, and the smoke has already covered islands in Denmark (including Greenland and the Faroe Islands), France, Spain, Sweden, Norway, Germany, Finland, Poland and Italy.'' ', 
         fontdict={
             'color': 'black'.'weight': 'bold'.'size': 13
         })

plt.savefig('figure 31. PNG', dpi=500)
Copy the code

This is the end of this article, if there are any errors, I will continue to introduce more advanced map visualization methods in the next article, please look forward to!

The resources

[1]

Github.com/CNFeffery/D… : https://github.com/CNFeffery/DataScienceStudyNotes

[2]

Suggestion: support.supermap.com.cn/datawarehou…

[3]

Proj: proj.org/operations/…

[4]

Data source: github.com/BlankerL/DX…

[5]

Github Repository: github.com/Z3tt/TidyTu…

-END-

“`php

Highlights of past For beginners entry route of artificial intelligence and data download AI based machine learning online manual deep learning online manual download update (PDF to 25 sets) this qq group, 1003271085, to join this site WeChat group please reply “add group” to get a sale standing knowledge star coupons, please reply “knowledge planet like the article, A look at

Copy the code