COVID-19 NA MAPACH MATLABa

W tym wpisie zajmę się wizualizacją danych dotyczących rozwoju pandemii COVID-19 na mapie świata uzyskując obrazy, które na co dzień widzimy w Internecie lub telewizji. Za pomocą toolboxu ‘Mapping’ pakietu MATLAB każdy będzie mógł uzyskać aktualny obraz sytuacji na podstawie danych Uniwersytetu John’a Hopkins’a.
MATLAB, COVID-19 i Uniwersytet John’a Hopkins’a

Agregacją danych, które dotyczą rozwoju pandemii COVID-19 zajmuje się Uniwersytet John’a Hopkins’a w Baltimore.  Więcej na temat tego repozytorium możecie przeczytać w poprzednich wpisach TUTAJ oraz TU, w których pokazałem jak wykorzystać MATLABa do analizy danych i wizualizacji na wykresach liczby przypadków osób chorych, tych, które wyzdrowiały oraz liczby zgonów. To niewątpliwie ciekawe wykresy, które umożliwiają analizę dynamiki rozwoju pandemii w poszczególnych krajach. Jednak w mediach możemy częściej zobaczyć grafikę ukazującą ogólną liczbę przypadków COVID-19 na tle mapy danego kraju lub kontynentu. Taki obraz da się również wygenerować w MATLABie i poniżej pokażę jak to zrobić samemu. Efekt końcowy będzie wyglądał tak:

Jak uzyskać powyższy obraz? Oczywiście z wykorzystaniem ‘Mapping Toolbox’ MATLABa oraz programu, który pobiera bieżące dane z bazy Uniwersytetu John’a Hopkins’a. Sam program był szczegółowo omawiany w poprzednich wpisach - tu jest użyta jego modyfikacja, która nie wymaga głębszego komentarza. Cały program znajdziecie na końcu tego postu.

Przyjrzyjmy się bliżej samemu toolboxowi ‘mapping’ – jego funkcje umożliwiają analizę i wizualizację danych geograficznych o różnorakim charakterze, a w szczególności map oraz danych GPS. Mapy w MATLABie mogą być rysowane na podstawie danych wektorowych lub rastrowych. Podstawowa baza map jest dostarczana razem z toolboxem, ale można również korzystać z danych zapisanych w plikach zewnętrznych bądź z map z Internetu. Możliwości jest wiele i wszystkie opisane są w systemie pomocy MATLABa. Toolbox umożliwa tworzenie wielu rodzajów rysunków z wykorzystaniem map, ale do czterech podstawowych należą:

  • basemaps – czyli wizualizacja samej mapy i współrzędnych geograficznych,
  • rysunki we współrzędnych geograficznych – takie jak położenie konkretnych punktów, linii, dróg, itp.
  • rysunki bąbelkowe – umożliwiające wizualizację danych statystycznych na tle mapy w postaci kół, tak zwanych bąbęlków,
  • rysunki gęstości – przeznaczone do wizualizacji częstości/gęstości występowania danego zjawiska na danym obszarze.

Na potrzeby wizualizacji danych obrazujących pandemię COVID-19 idealnie nadają się rysunki bąbelkowe wpisane we współrzędne geograficzne mapy. Po pobraniu danych tworzona jest tabela ‘Dane’ zawierająca w kolejnych kolumnach szerokość geograficzną, długość geograficzną , nazwę kraju oraz liczbę potwierdzonych przypadków COVID-19. Na potrzeby funkcji rysującej mapę, nazwę kraju ze typu 'string' zmieniamy na 'categorical', a do narysowania mapy i zobrazowania danych w postaci bąbelków używamy funkcji geobubble.

% Dla wybranych danych tworzymy nową tabelę:
Dane = [Lat, Long, Country, Confirmed];

% Na potrzeby funkcji geobubble nazwę kraju ze 'string' zmieniamy na
% 'categorical'
Dane.CountryRegion = categorical(Dane.CountryRegion);

% Dane w postaci bąbelkowej
cov_bubble = geobubble(Dane,'Lat','Long');

Takie wywołanie funkcji narysuje na mapie bąbelki o jednakowej wielkości w punktach geograficznych ze zmiennych 'Lat’ i ‘Long’. Aby uzależnić wielkość bąbelków od liczby przypadków COVID-19 w danym kraju musimy ustawić właściwość 'SizeVariable' jako zmienną ‘Confirmed’. Dodatkowo aby kolor bąbelków dla każdego kraju był inny należy zdefiniować właściwość ‘ColorVariable’:

cov_bubble = geobubble(Dane,'Lat','Long','SizeVariable','Confirmed','ColorVariable', 'CountryRegion');

Obiekt ‘cov_bubble’ przechowuje cechy utworzonej mapy, a do konkretnych właściwości można odnosić się za pomocą kropki. Zmieńmy więc opisy legendy oraz zwiększmy rozmiar bąbelków:

% Opis rysunku
title('COVID-19 w Europie');
cov_bubble.SizeLegendTitle = 'Liczba chorych';
cov_bubble.ColorLegendTitle = 'Kraj';

% Zmiana rozmiaru bąbelków aby obraz był bardziej czytelny
cov_bubble.BubbleWidthRange = [10 30]

Po wywołaniu funkcji geobubble rysowana jest mapa bazowa (basemap) w odcieniach szarości, tzw. ‘darkwater’, która zawiera jedynie granice Państw i landów. Jeżeli chcemy zobaczyć nasz rysunek na tle mapy innego rodzaju, np. obrazującej topologię terenu należy skorzystać z funkcji geobasemap i wybrać jedną z pięciu innych map dostępnych w MATLABie, na przykład:

geobasemap colorterrain

Należy pamiętać, że mapy inne niż ‘darkwater’ są pobierane każdorazowo z Internetu. W efekcie powyższego programu otrzymamy rysunek umieszczony na początku tego wpisu.

Mapy w MATLABie to przyjemne narzędzie dające wiele możliwości wizualizacji danych. Zachęcam do indywidualnej eksploracji tego toolboxa. Poniżej znajduje się cały program.

clear all; close all; clc

% Pierwsza część programu to zmodyfikowany program E. Cheynet'a i funkcji:
% [tableConfirmed,tableDeaths,tableRecovered,time] = getDataCOVID()
% Program pobiera dane dotyczące liczby zachorowań na COVID-19 z bazy
% danych uniwersytetu John'a Hopkins'a oraz obrazuje ich liczbę na mapie.
% 
% Referencje:
% [1] https://github.com/CSSEGISandData/COVID-19


%% Parametry importu danych

% Liczba dni do analizy od początku rejestracji danych
Ndays = floor(datenum(now))-datenum(2020,01,22)-1; % minus jeden dzień bo baza danych jest odświeżana co 24h

% Ustawienie parametrów importu danych
opts = delimitedTextImportOptions("NumVariables", Ndays+5);

% Dzięki użyciu tabeli, każdej zmiennej można nadać nazwę symboliczną 
% i się nią posługiwać w programie
opts.VariableNames = ["ProvinceState", "CountryRegion", "Lat", "Long", repmat("data",1,Ndays+1)];

% Definicja typu każdej zmiennej, dwie pierwsze to stringi, reszta wartości numeryczne: 
opts.VariableTypes = ["string", "string", repmat("double",1,Ndays+3)];

% Pozostałe ustawienia importu danych
opts.ExtraColumnsRule = "ignore";   % w przypadku występowania dodatkowych kolumn - ignorujemy je
opts.EmptyLineRule = "read";        % jeżeli w danych występują puste linie to je odczytujemy

%% Import danych

% Dane podzielone na trzy grupy: zarażeni, zgony i wyleczenia
status = {'confirmed','deaths','recovered'};

% Adres repozytorium Uniwersytetu John'a Hopkins'a
address = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/';
ext = '.csv';

% Odczyt danych 
for ii = 1:numel(status)
    
    filename = ['time_series_covid19_',status{ii},'_global'];
    fullName = [address,filename,ext];
    urlwrite(fullName,'dummy.csv');     % import danych do pliku, którego zawartość
    % będzie następnie konwertowana na tabelę:
        
    if strcmpi(status{ii},'Confirmed')
        tableConfirmed =readtable('dummy.csv', opts);
        
    elseif strcmpi(status{ii},'Deaths')
        tableDeaths =readtable('dummy.csv', opts);
        
    elseif strcmpi(status{ii},'Recovered')
        tableRecovered =readtable('dummy.csv', opts);
    else
        error('Unknown status')
    end
end

% Odczyt daty i jej konwersja na postać standardową
fid = fopen('dummy.csv');
time = textscan(fid,repmat('%s',1,size(tableRecovered,2)), 1, 'Delimiter',',');
time(1:4)=[];
time = datetime([time{1:end}])+years(2000);
fclose(fid);

% delete('dummy.csv'); % plik można skasować lub zostawić (przydatne przy
% braku połączenia z Internetem


%% Analiza danych 

%% Dane dla Polski
Poland_population = 38*10^6;

% Szerokość geograficzna 
Lat = tableConfirmed(tableConfirmed.CountryRegion == 'Poland' | ...
    tableConfirmed.CountryRegion == 'Italy' | ...
    tableConfirmed.CountryRegion == 'Switzerland' | ...
    tableConfirmed.CountryRegion == 'Sweden' | ...
    tableConfirmed.CountryRegion == 'Slovakia' | ...
    tableConfirmed.CountryRegion == 'Belgium' |...
    tableConfirmed.CountryRegion == 'Czechia' |...
    tableConfirmed.CountryRegion == 'Finland' |...
    tableConfirmed.CountryRegion == 'Spain' |...
    tableConfirmed.CountryRegion == 'Ukraine', ...
    'Lat');

% Długość geograficzna 
Long = tableConfirmed(tableConfirmed.CountryRegion == 'Poland' | ...
    tableConfirmed.CountryRegion == 'Italy' | ...
    tableConfirmed.CountryRegion == 'Switzerland' |...
    tableConfirmed.CountryRegion == 'Sweden' | ...
    tableConfirmed.CountryRegion == 'Slovakia' | ...
    tableConfirmed.CountryRegion == 'Belgium' |...
    tableConfirmed.CountryRegion == 'Czechia' |...
    tableConfirmed.CountryRegion == 'Finland' |...
    tableConfirmed.CountryRegion == 'Spain' |...
    tableConfirmed.CountryRegion == 'Ukraine', ...
    'Long');

% Nazwa kraju
Country = tableConfirmed(tableConfirmed.CountryRegion == 'Poland' | ...
    tableConfirmed.CountryRegion == 'Italy' | ...
    tableConfirmed.CountryRegion == 'Switzerland' |...
    tableConfirmed.CountryRegion == 'Sweden' | ...
    tableConfirmed.CountryRegion == 'Slovakia' | ...
    tableConfirmed.CountryRegion == 'Belgium' |...
    tableConfirmed.CountryRegion == 'Czechia' |...
    tableConfirmed.CountryRegion == 'Finland' |...
    tableConfirmed.CountryRegion == 'Spain' |...
    tableConfirmed.CountryRegion == 'Ukraine', ...
    'CountryRegion');

% Liczba osób zakażonych
Confirmed = tableConfirmed(tableConfirmed.CountryRegion == 'Poland' | ...
    tableConfirmed.CountryRegion == 'Italy' | ...
    tableConfirmed.CountryRegion == 'Switzerland' | ...
tableConfirmed.CountryRegion == 'Sweden' | ... 
tableConfirmed.CountryRegion == 'Slovakia' | ... 
tableConfirmed.CountryRegion == 'Belgium' |...
tableConfirmed.CountryRegion == 'Czechia' |...
tableConfirmed.CountryRegion == 'Finland' |...
tableConfirmed.CountryRegion == 'Spain' |...
tableConfirmed.CountryRegion == 'Ukraine', ...
end);
Confirmed.Properties.VariableNames = {'Confirmed'};

% Dla wybranych danych tworzymy nową tabelę:
Dane = [Lat, Long, Country, Confirmed];

% Na potrzeby funkcji geobubble nazwę kraju ze 'string' zmieniamy na
% 'categorical'
Dane.CountryRegion = categorical(Dane.CountryRegion);

% Dane w postaci bąbelkowej
cov_bubble = geobubble(Dane,'Lat','Long','SizeVariable','Confirmed','ColorVariable', 'CountryRegion');

% Opis rysunku
title('COVID-19 w Europie');
cov_bubble.SizeLegendTitle = 'Liczba chorych';
cov_bubble.ColorLegendTitle = 'Kraj';

% Zmiana rozmiaru bąbelków aby obraz był bardziej czytelny
cov_bubble.BubbleWidthRange = [10 30]

% Zmiana rodzaju mapy
geobasemap colorterrain


(Visited 409 times, 1 visits today)

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *