Regenmenge visualsieren mit Pandas und Matplotlib
Der Regensensor" arbeitet nach dem Tipping-Bucket Prinzip und zählt wie oft die Wippe kippt. Die Rohdaten zeigen also eine stetig ansteigende Kurve:
Diese Darstellung macht zwar auch Sinn, denn sie zeigt wieviel Regen insgesamt gefallen ist. Da der Regen aber versickert wollte ich eine Darstellung die zeigt wann genau es geregnet hat.
Niederschlag in 10 Minuten
Das Auswertescript loggt den Zählerstand, also brauchen wir auf jeder Zeile die Differenz zum vorangehenden Stand. Pandas berechnet das mühelos:
df["diff"] = df[2].diff()
Bei dieser Berechnung entsteht aber ein NaN-Value am Anfang, weil die erste Zeile keinen Vorgänger hat. Das muss gefiltert werden damit es später keine Exceptions gibt. Nach etwas Feinbearbeitung kriegen wir dann die gewünschte Darstellung:
Das Python-Script
import pandas as pd import matplotlib.pyplot as plt from matplotlib.ticker import MaxNLocator from matplotlib.dates import DateFormatter plt.style.use( "ggplot" ) # Read the logfile df = pd.read_csv( "rainyday.csv", header=None ) # Convert the datetime column df[0] = pd.to_datetime(df[0]) # Determine difference between rows df["diff"] = df[2].diff() # Drop the first difference which is NaN df = df.dropna() # Group the differences and sum the groups sums = df.groupby( pd.Grouper(key=0,freq="10min",axis=0) ).sum().reset_index() # One tip means 0.45 liters sums["rain"] = sums["diff"] * 0.45 # Create a new column with formatted time sums["time"] = sums[0].dt.strftime( "%H:%M" ) # Create the plot ax = sums.plot( x="time", y="rain", kind="bar", width=1, legend=None ) # Reduce the ticks to keep them readable ax.xaxis.set_major_locator( MaxNLocator(40) ) # Set title and labels plt.title( "Regenmenge pro 10min, August 2024" ) plt.xlabel( None ) plt.ylabel( "Regen [Liter]" ) # Search the midnight rows midnights = sums[sums["time"] == "00:00"].index # Add separators and date strings left = 0 day = sums.iloc[0,0].day for m in midnights: plt.axvline( m, color="blue" ) plt.text( (left + m) / 2, 3.9, f"{day}. August", color="blue", horizontalalignment="center", size="x-large" ) left = m day += 1 # Save the plot as SVG plt.savefig( "rain.svg", bbox_inches="tight" )
Nachbearbeitung
Damit das SVG schön skalierbar wird müssen noch die Attribute **width** und **height** aus dem svg-Element geputzt werden. Dafür habe ich bisher keinen Weg gefunden, deshalb habe ich sie einfach mit dem Editor entfernt...
Ja. ich weiss das man das mit XSLT hinkriegt, aber das war mir zu mühsam. Mit dem Editor ging es einfach schneller.