Nachdem es im Augenblick kaum ein anderes Thema gibt als COVID-19 und man mehr oder weniger daheim festsitzt ist es Zeit, wieder einmal was Produktives anzufangen. Ich wollte mich schon lange mal mit pandas und matplotlib beschäftigen. Nun hat man die Daten ja gerne frisch von einem Server – nur zieren die sich in der Regel, mundgerechte Dateien zur Verfügung zu stellen. Also muss man, wenn man denn will – und man will ja – die Daten aus den HTML-Tabellen scrapen. Das war einfacher als gedacht. Es kam dann doch ein hübsches Diagramm dabei heraus (Quelltext unten):
import pandas as pd
from bs4 import BeautifulSoup
import requests
import lxml
from matplotlib import pyplot as plt
import numpy as np
country = []
cases = []
deaths = []
n = 50
# Tabelle von Worldometers scrapen
source = requests.get('https://www.worldometers.info/coronavirus/#countries').text
soup = BeautifulSoup(source, 'lxml')
match = soup.findAll('div', class_='main_table_countries_div')[1]
html = match.prettify()
#dataframe lesen
df = pd.read_html(html)
df = df[0]
df = df.head(n)
bar_width = 0.35
# dataframe formatieren
df["New Cases"] = df["New Cases"].str.replace(',', '')
df["New Cases"] = pd.to_numeric(df["New Cases"])
# Deaths muss zur besseren Sichtbarkeit skaliert werden
df["New Deaths"] = 10 * df["New Deaths"]
df = df.sort_values(by=['New Cases'], ascending=False)
data = df[["Country, Other", "New Cases", "New Deaths"]]
# dataframe2lists
for index, rows in data.iterrows():
country.append(rows["Country, Other"])
appendcases = (str(rows["New Cases"]))
appendcases = appendcases.replace('nan', '0')
cases.append(float(appendcases))
appenddeaths = (str(rows["New Deaths"]))
appenddeaths = appenddeaths.replace('nan', '0')
deaths.append(float(appenddeaths))
# indexes fuer die X-Achse
x_indexes = np.arange(len(country))
bar_width = 0.35
plt.style.use('fivethirtyeight')
# Wir brauchen eine zweite Y-Achse --> Subplot
fig, ax = plt.subplots()
ax.set_xlabel('Country')
ax.set_ylabel('New Infections/Deaths')
ax.bar(x_indexes, cases, label = 'Infected', width = bar_width, color = 'blue')
ax.bar(x_indexes + bar_width, deaths, label = 'Deaths', width = bar_width, color = 'green')
ax.tick_params(axis='y', labelcolor='blue')
# Skalieung Y-Achse abfragen und dividieren für die zweite Y-Achse
bottom, top = plt.ylim()
limity = (top / 10)
# Zweite Axe erstellen mit der selben X-Achse
ax2 = ax.twinx()
# Die Skalierung der zweiten Y-Achse an die erste anpassen
ax2.set_ylim(top = limity)
ax2.tick_params(axis='y', labelcolor='green')
plt.xticks(x_indexes, country)
ax.tick_params(axis='x', labelrotation = 90)
plt.title('New Infections/Deaths in the top ' + str(n) + ' countries')
plt.tight_layout()
ax.legend()
plt.show()
