At present, the global epidemic is still serious. In order to clearly see the changing trend of the global epidemic from the outbreak to the present, I have drawn a map of the epidemic change with 230 lines of complete code. If you need a friend, you can reply to the map by keyword on the official account. Without further ado, let’s start with the picture above
Let’s focus on the drawing process of the above picture, which is mainly divided into the following three steps:
-
The data collection
-
The data processing
-
drawing
Let’s take it one at a time. The data collection
This is the first step of the Great Wall, as the saying goes “even a clever housewife can not cook a meal without rice”, since it is the map of change, of course, need each country, daily number of existing confirmed cases. Fortunately, major websites now have special pages related to the epidemic, so we can directly capture the data. Take netease as an example
We choose XHR and refresh the page again to see several interfaces, among which the list-total interface is to obtain all the countries currently affected by the epidemic and the corresponding country ID. In addition, we see that there is a list-by-Area-code interface, which is to obtain the historical daily epidemic data of each country. The request for this interface requires the areaCode parameter, which is the country ID we just said. So these two interfaces are the most important ones for us. Let’s look at the code for requesting the list-total interface
def get_and_save_all_countries(a):
""" Get all the country names and their corresponding ids and save them as a file.
url = 'https://c.m.163.com/ug/api/wuhan/app/data/list-total?t=317452696323'
list_total_req = requests.get(url, headers=headers)
if list_total_req.status_code == 200:
area_tree = list_total_req.json()['data'] ['areaTree']
area_dict = {}
for area in area_tree:
country_id = area['id']
name = area['name']
area_dict[country_id] = name
area_json = json.dumps(area_dict, ensure_ascii=False) # ensure_ASCII =False prevents characters starting with \ U after JSON encoding
write_file('./config/countries_id2name.json', area_json)Copy the code
Here the requested data is temporarily stored in a file. With the IDS of all affected countries, we can request the List-by-Area-code interface to get epidemic data for each country. The code is similar to the above, except that the result of the request is stored in mongodb instead of a file, for the purpose of easy to add, delete, change and check. Of course, for your convenience, I imported the mongodb data into the file counties_daily.json, which you can find in the source directory.
The data processing
The processing of this step is mainly to prepare for the drawing of the third step. Because we use pyecharts framework for drawing the map, the country names we need to input for drawing the world map are In English, but the country names we collect are in Chinese, so we need to match the Chinese country names to the English country names. The end result is as follows
You can find this online, but there are two problems you need to solve to make it work. First, the Chinese names on both sides should be unified. For example, the country name we collected is Central African Republic, but the corresponding relationship is Central African Republic, which still does not correspond. Second, we need to increase the mapping relationship by ourselves. The online mapping is generally not complete, so we need to increase it by ourselves according to the data collected. After the above two steps, we should be able to map most country names to English names that Pyechars can recognize. The relevant codes are as follows
def get_cy_properties(a):
Get configuration file information
countries_id2name = read_file('./config/countries_id2name.json')
cy_id2name_dict = json.loads(countries_id2name)
cy_ch2en = {v: k for k, v in countries_dict.items()}
Change the country name to match the configuration file
cy_id2name_dict['879'] = 'Bosnia and Herzegovina'
cy_id2name_dict['8102'] = 'Togo'
cy_id2name_dict['8143'] = 'Democratic Republic of Congo'
cy_id2name_dict['95983'] = 'the'
cy_id2name_dict['8144'] = 'Africa'
cy_id2name_dict['95000011'] = dominica
cy_props = {}
for key in cy_id2name_dict:
cy_name = cy_id2name_dict[key]
if cy_name in cy_ch2en:
cy_props[cy_name] = {}
cy_props[cy_name]['id'] = key
cy_props[cy_name]['en_name'] = cy_ch2en[cy_name]
return cy_propsCopy the code
drawing
This step involves two core processes — constructing data structures and drawing diagrams. First, I constructed three data structures, date_list, cy_name_list, and nCOv_data. Date_list stores a list of dates, which takes a while because we’re drawing giFs; Cy_name_list holds a list of all countries in the collection (English names); Ncov_data is a dictionary where key is the date and value is an array of the number of confirmed cases in each country that day. The code to generate these three data structures is as follows
def parse_ncov_data(start_date, end_date, records):
if not records:
return
date_list = get_date_range(start_date, end_date)
cy_name_list = []
res = {}
# Capture current confirmed cases in each country on a daily basis
for i, record in enumerate(records):
cy_name = record['cy_en_name']
cy_name_list.append(cy_name)
# Analysing daily data and counting existing confirmed cases
existing_case_dict = {}
for ncov_daily in record['data'] ['list']:
date_str = ncov_daily['date']
confirm = ncov_daily['total'] ['confirm'] # Cumulative diagnosis
heal = ncov_daily['total'] ['heal'] # Cumulative diagnosis
dead = ncov_daily['total'] ['dead'] # Cumulative deaths
existing_case = confirm - heal - dead
existing_case_dict[date_str] = existing_case
last_existing_case = 0
# Merge the number of confirmed cases per day into the RES
for date_str in date_list:
if date_str not in res: # initialization
res[date_str] = []
existing_case = existing_case_dict.get(date_str)
if existing_case is None:
existing_case = last_existing_case
res[date_str].append(existing_case)
last_existing_case = existing_case
return date_list, cy_name_list, resCopy the code
The argument records is an array, each element of which represents a country, and the contents are the data we requested from the list-by-Area-code interface in the first step. Finally, use Pyecharts to draw and go directly to the code
def render_map(date_list, cy_name_list, ncov_data):
tl = Timeline() # Create a timeline rotation multi graph, you can make the graph according to the input time to move
# is_auto_play: Auto play
# play_interval: indicates the playback interval, in milliseconds
# is_loop_play: Whether to loop
tl.add_schema(is_auto_play=True, play_interval=50, is_loop_play=False)
for date_str in date_list: # List of iterations
map0 = (
Map() # Create a map chart
# Add country names cy_name_list and nCOv_data [date_str] of confirmed cases in each country that day
.add("Global Epidemic Trends", [list(z) for z in zip(cy_name_list, ncov_data[date_str])],
"world", is_map_symbol_show=False)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # do not display country name
.set_global_opts(
title_opts=opts.TitleOpts(title="% s day" % date_str), # Chart title
visualmap_opts=opts.VisualMapOpts(max_=80), # When confirmed cases are greater than 80, the map color is red
)
)
tl.add(map0, "%s" % date_str) # Add the map status of the day to the timeline
tl.render() Render. HTML file is created in the current directoryCopy the code
The code is commented, so I won’t repeat it here. Running render_map will generate a render. HTML file in the current directory, which will automatically play the epidemic trend, such as the GIF at the beginning of this article. In addition, some friends may ask, can directly output GIF. This point I also tried, Baidu, Google, GitHub tutorial basically tried again, more regret did not find a reliable method. So advise you to give up this road, curve to save the country, record a video into GIF can be convenient and fast. After all, life is short, and the time saved by Python can’t be filled up with meaningless holes. So the whole process is introduced, although the idea is not complex, but the local details still need to spend some time processing. Complete code a total of 230 lines, need friends in the public number to reply to the keyword epidemic map can be.
There have been signs of a rebound in some parts of the country recently. I hope you will continue to be vigilant in both your work and life. Let’s hope this epidemic passes soon and wait for the day when the global map turns white.
Welcome the public account “du Code” to export the dry goods you can’t see elsewhere.