Это третья из четырех статей, направленных на решение проблемы выявления вспышек заболеваний путем извлечения заголовков новостей из популярных источников новостей.

Эта статья направлена ​​на определение простого способа просмотра кластеров, определенных (во второй статье) в глобальном масштабе и на уровне США. Сначала собирается список больших городов и помещается с соответствующими широтой и долготой в набор данных. Затем создается функция, которая отображает точки кластера на карте с разными цветами для каждого соответствующего кластера. Наконец, функция вызывается для точек в Соединенных Штатах, центров кластеров в Соединенных Штатах, глобальных точек и глобальных центров кластеров.

Ниже показано подробное объяснение того, как это реализовано:

Шаг 1. Составление списка крупнейших городов США.

Сначала название города, широта, долгота и численность населения извлекаются из файла «large_us_cities.csv», содержащего города США с населением более 30 000 человек. Города с населением более 200 000 человек были добавлены в словарь, а Анкоридж и Гонолулу были исключены, поскольку они исказили расположение карты. Затем, используя формулу расстояния гаверсинуса, которая определяет расстояние между парами городов, города, близкие друг к другу, были исключены и использовалась эвристика численности населения, чтобы определить, какой город следует сохранить.

file2 = open('largest_us_cities.csv', 'r') 
large_cities = file2.readlines()

large_city_data = {}
for i in range(1, len(large_cities)):
    large_city_values = large_cities[i].strip().split(';')
    lat_long = large_city_values[-1].split(',')
    if ((int(large_city_values[-2]) >= 200000) and (large_city_values[0] != "Anchorage") and (large_city_values[0] != "Honolulu") and (large_city_values[0] != "Greensboro")):
        large_city_data[large_city_values[0]] = [lat_long[0], lat_long[1], large_city_values[-2]]

def haversine(point_a, point_b):
    lon1, lat1 = point_a[0], point_a[1]
    lon2, lat2 = point_b[0], point_b[1]
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371
    return c * r

for i in list(large_city_data.keys()):
    for j in list(large_city_data.keys()):
        if ((i != j) and haversine((float(large_city_data[i][0]), float(large_city_data[i][1])), (float(large_city_data[j][0]),
            float(large_city_data[j][1]))) < 80.0):
            if (large_city_data[j][2] > large_city_data[i][2]):
                large_city_data[i] = [np.nan, np.nan, large_city_data[i][2]]
            else:
                large_city_data[j] = [np.nan, np.nan, large_city_data[j][2]]
large_city_data['Chicago'] = [41.8781136, -87.6297982, 2718782]

Этап 2. Построение кластеров и центров кластеров методом К-средних с помощью базовой карты

Сначала создается функция с семью параметрами: df1, num_cluster, typeof, path, size, add_large_city и figsize. Используя библиотеку базовых карт, в зависимости от параметра typeof создаются географические модели США и мира. Кроме того, параметр figsize изменяет размер модели в зависимости от его значения. Создается словарь, в котором ключами являются метки кластера, разделенные по широте и долготе. Значения содержат широту и долготу для каждого заголовка для каждой метки кластера.

Список цветов инициализирован, и каждой метке кластера назначаются определенные цвета. Точки широты и долготы нанесены с использованием этих цветовых значений на географических моделях, сделанных выше. Если параметр add_large_city имеет значение true, на график также будут добавлены самые большие города. Рисунок сохраняется в файл «.png» с использованием параметра пути.

def print_k_means(df1, num_cluster, typeof, path, size, add_large_city, figsize):
    if (typeof == "US"):
        map_plotter = Basemap(projection='lcc', lon_0=-95, llcrnrlon=-119, llcrnrlat=22, urcrnrlon=-64, urcrnrlat=49, lat_1=33, lat_2=45)
    else:
        map_plotter = Basemap()
    if (figsize):
        fig = plt.figure(figsize = (24,16))
    else:
        fig = plt.figure(figsize = (12,8))
    coordinates = []
    for index in df1.index:
        coordinates.append([df1['latitude'][index], df1['longitude'][index], df1['cluster_label'][index]])
    
    cluster_vals = {}
    for i in range(num_cluster):
        cluster_vals[str(i)+"_long"] = []
        cluster_vals[str(i)+"_lat"] = []
    
    for index in df1.index:
        cluster_vals[str(df1['cluster_label'][index])+'_long'].append(float(df1['longitude'][index]))
        cluster_vals[str(df1['cluster_label'][index])+'_lat'].append(float(df1['latitude'][index]))
        
    num_list = [i for i in range(num_cluster)]
    color_list = ['rosybrown', 'lightcoral', 'indianred', 'brown',
                 'maroon', 'red', 'darksalmon', 'sienna', 'chocolate', 'sandybrown', 'peru',
                 'darkorange', 'burlywood', 'orange', 'tan', 'darkgoldenrod', 'goldenrod', 'gold', 'darkkhaki',
                 'olive', 'olivedrab', 'yellowgreen', 'darkolivegreen', 'chartreuse',
                 'darkseagreen', 'forestgreen', 'darkgreen', 'mediumseagreen', 'mediumaquamarine',
                 'turquoise', 'lightseagreen', 'darkslategrey', 'darkcyan',
                 'cadetblue', 'deepskyblue', 'lightskyblue', 'steelblue', 'lightslategrey',
                 'midnightblue', 'mediumblue', 'blue', 'slateblue', 'darkslateblue', 'mediumpurple', 'rebeccapurple',
                 'thistle', 'plum', 'violet', 'purple', 'fuchsia', 'orchid', 'mediumvioletred', 'deeppink', 'hotpink',
                 'palevioletred']
    colors = [color_list[i] for i in range(num_cluster+1)]

    for target,color in zip(num_list, colors):
         map_plotter.scatter(cluster_vals[str(target)+'_long'], cluster_vals[str(target)+'_lat'], latlon=True, s = size, c = color)
         map_plotter.shadedrelief()
    if (add_large_city):
        for index in list(large_city_data.keys()):
            if (large_city_data[index][1] != np.nan):
                x, y = map_plotter(large_city_data[index][1], large_city_data[index][0])
                plt.plot(x, y, "ok", markersize = 4)
                plt.text(x, y, index, fontsize = 16)
    plt.show()
    fig.savefig(path)

Шаг 3. Запуск функции

Функция print_k_means запускается в кадре данных df_no_us, чтобы построить диаграмму рассеяния широты и долготы для заголовков, относящихся к США. Затем определяется географический центр каждого кластера и сохраняется в другом фрейме данных, называемом df_center_us. Функция print_k_means запускается в фрейме данных df_center_us и добавляет крупные города для определения городов, ближайших к центрам вспышек заболеваний. Кроме того, размер увеличен для облегчения чтения. Аналогичный процесс выполняется для df_no_world. Каждый из фреймов данных хранится в файле «.csv».

print_k_means(df_no_us, us_clusters, "US", "corona_disease_outbreaks_us.png", 50, False, False)
df_no_us.to_csv("corona_disease_outbreaks_us.csv")


df_center_us = {'latitude': [], 'longitude':[] , 'cluster_label': []}
for i in range(us_clusters):
    df_1 = df_no_us.loc[df_no_us['cluster_label'] == i]
    df_1 = df_1.reset_index()
    del df_1['index']
    latitude = []
    longitude = []
    for index in df_1.index:
        latitude.append(float(df_1['latitude'][index]))
        longitude.append(float(df_1['longitude'][index]))
    df_1['latitude'] = latitude
    df_1['longitude'] = longitude
    sum_latitude = df_1['latitude'].sum()
    sum_longitude = df_1['longitude'].sum()
    if (len(df_1['latitude']) >= 20):
        df_center_us['latitude'].append(sum_latitude/(len(df_1['latitude'])))
        df_center_us['cluster_label'].append(i)
        df_center_us['longitude'].append(sum_longitude/(len(df_1['longitude'])))
df_center_us = pd.DataFrame(data = df_center_us)


for index in df_center_us.index:
    df_center_us['cluster_label'][index] = index

print_k_means(df_center_us, len(df_center_us['latitude']), "US", "corona_disease_outbreaks_us_centers.png", 500, True, True)
df_center_us.to_csv("corona_disease_outbreaks_us_centers.csv")

df_center_world = {'latitude': [], 'longitude':[] , 'cluster_label': []}
for i in range(world_clusters):
    df_1 = df_no_world.loc[df_no_world['cluster_label'] == i]
    df_1 = df_1.reset_index()
    del df_1['index']
    latitude = []
    longitude = []
    for index in df_1.index:
        latitude.append(float(df_1['latitude'][index]))
        longitude.append(float(df_1['longitude'][index]))
    df_1['latitude'] = latitude
    df_1['longitude'] = longitude
    sum_latitude = df_1['latitude'].sum()
    sum_longitude = df_1['longitude'].sum()
    if (len(df_1['latitude']) >= 10):
        df_center_world['latitude'].append(sum_latitude/(len(df_1['latitude'])))
        df_center_world['cluster_label'].append(i)
        df_center_world['longitude'].append(sum_longitude/(len(df_1['longitude'])))
df_center_world = pd.DataFrame(data = df_center_world)


for index in df_center_world.index:
    df_center_world['cluster_label'][index] = index

print_k_means(df_center_world, len(df_center_world['latitude']), "world", "corona_disease_outbreaks_world_centers.png", 500, False, True)
df_center_us.to_csv("corona_disease_outbreaks_world_centers.csv")

Щелкните эту ссылку для доступа к репозиторию Github с подробным объяснением кода: Github.