Programming project¶
- Name: Simon Häusler
- Matrikelnummer: 12031623
1 2 3 4 5 6 7 8 9 | import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import StrMethodFormatter import doctest import pandas as pd from matplotlib import cm import scipy from scipy import stats from scipy.stats import linregress |
01 - An energy balance model with hysteresis¶
Based on the code we wrote in week 07, code the following extension. For this exercise it's OK to copy-paste my solutions and start from there. Only copy the necessary (no useless code)!
The planetary albedo $\alpha$ is in fact changing with climate change. As the temperature drops, sea-ice and ice sheets are extending (increasing the albedo). Inversely, the albedo decreases as temperature rises. The planetary albedo of our simple energy balance model follows the following equation:
$$ \alpha = \begin{cases} 0.3,& \text{if } T \gt 280\\ 0.7,& \text{if } T \lt 250\\ a T + b, & \text{otherwise} \end{cases} $$
01-01: Compute the parameters $a$ and $b$ so that the equation is continuous at T=250K and T=280K.
1 2 3 4 5 6 7 8 9 10 | values1 = np.array([[250,1],[280,1]]) values2 = np.array([[0.7],[0.3]]) a, b = np.linalg.solve(values1, values2) a = float(a) b = float(b) print(a,b) |
-0.013333333333333324 4.0333333333333306
01-02: Now write a function called alpha_from_temperature
which accepts a single positional parameter T
as input (a scalar) and returns the corresponding albedo. Test your function using doctests to make sure that it complies to the instructions above.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | def alpha_from_temperature(T): """Albedo Parameters ---------- alpha : float, optional the planetary albedo Returns ------- Examples >>> alpha_from_temperature(249) 0.7 >>> alpha_from_temperature(281) 0.3 """ if T < 250: alpha = 0.7 elif 250 <= T <= 280: alpha = a * T + b elif T > 280: alpha = 0.3 return alpha doctest.testmod() |
TestResults(failed=0, attempted=2)
01-03: Adapt the existing code from week 07 to write a function called temperature_change_with_hysteresis
which accepts t0
(the starting temperature in K), n_years
(the number of simulation years) as positional arguments and tau
(the atmosphere transmissivity) as keyword argument (default value 0.611). Verify that:
- the stabilization temperature with
t0 = 292
and default tau is approximately 288K - the stabilization temperature with
t0 = 265
and default tau is approximately 233K
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | C = 4.0e+08 t_0 = 292 dt = 60 * 60 * 24 * 365 def olr(t, tau=0.611): sigma = 5.67E-8 return sigma * tau * t**4 def asr(alpha): s0 = 1362 return (1 - alpha) * s0 / 4 def temperature_change_with_hysteresis(t0, n_years, tau=0.611): years = np.arange(n_years + 1) temperature = np.zeros(n_years + 1) temperature[0] = t0 for i in range(n_years): temperature[i + 1] = temperature[i] + dt / C * (asr(alpha=alpha_from_temperature(temperature[i])) - olr(temperature[i], tau=tau)) return years, temperature print(temperature_change_with_hysteresis(292, 100, tau = 0.611)) print(temperature_change_with_hysteresis(265, 100, tau = 0.611)) |
(array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]), array([292. , 290.93503273, 290.15816267, 289.58946707, 289.17210602, 288.86524238, 288.63931706, 288.47281713, 288.35002266, 288.25941271, 288.19252534, 288.14313541, 288.10665784, 288.0797126 , 288.05980638, 288.04509907, 288.03423218, 288.02620251, 288.02026909, 288.01588456, 288.01264452, 288.01025019, 288.00848081, 288.00717325, 288.00620696, 288.00549287, 288.00496516, 288.00457518, 288.00428698, 288.004074 , 288.00391661, 288.00380029, 288.00371433, 288.00365081, 288.00360386, 288.00356917, 288.00354353, 288.00352458, 288.00351058, 288.00350023, 288.00349259, 288.00348694, 288.00348276, 288.00347967, 288.00347739, 288.00347571, 288.00347446, 288.00347354, 288.00347286, 288.00347236, 288.00347199, 288.00347171, 288.00347151, 288.00347136, 288.00347125, 288.00347117, 288.00347111, 288.00347106, 288.00347103, 288.003471 , 288.00347099, 288.00347097, 288.00347096, 288.00347095, 288.00347095, 288.00347095, 288.00347094, 288.00347094, 288.00347094, 288.00347094, 288.00347094, 288.00347094, 288.00347094, 288.00347094, 288.00347094, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093, 288.00347093])) (array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]), array([265. , 264.95291988, 264.89855772, 264.83578084, 264.76327829, 264.67953203, 264.58278336, 264.47099349, 264.34179726, 264.19244871, 264.01975681, 263.82000934, 263.58888255, 263.32133333, 263.01147009, 262.65239742, 262.2360281 , 261.75285442, 261.19166823, 260.53921583, 259.77976944, 258.8945909 , 257.86125481, 256.65278639, 255.23655306, 253.57282452, 251.61288239, 249.29651024, 246.80042382, 244.72054608, 242.97796545, 241.51143854, 240.27267703, 239.22310148, 238.33154556, 237.57259474, 236.92535958, 236.37255374, 235.89978988, 235.49503452, 235.14818044, 234.85070776, 234.59541237, 234.37618657, 234.18784041, 234.02595515, 233.88676232, 233.76704335, 233.66404597, 233.57541406, 233.49912881, 233.43345905, 233.37691925, 233.32823391, 233.28630734, 233.25019784, 233.21909583, 233.19230501, 233.16922643, 233.14934466, 233.13221613, 233.11745901, 233.10474456, 233.09378972, 233.08435074, 233.0762177 , 233.06920978, 233.06317125, 233.05796793, 233.05348425, 233.04962065, 233.04629135, 233.04342243, 233.04095021, 233.03881983, 233.03698402, 233.03540203, 233.03403877, 233.03286399, 233.03185164, 233.03097924, 233.03022746, 233.02957961, 233.02902133, 233.02854023, 233.02812564, 233.02776837, 233.02746049, 233.02719517, 233.02696653, 233.0267695 , 233.02659971, 233.02645339, 233.0263273 , 233.02621864, 233.026125 , 233.0260443 , 233.02597477, 233.02591484, 233.0258632 , 233.0258187 ]))
01-04: Realize a total of N simulations with starting temperatures regularly spaced between t0
=206K, and t0
=318K and plot them on a single plot for n_years
=50. The plot should look somewhat similar to this example for N=21
.
1 2 3 4 5 6 7 8 9 10 11 | plt.style.use('seaborn') fig, ax = plt.subplots() for i in range(206, 318, 4): ax.plot(*temperature_change_with_hysteresis(i, 50, tau=0.611)) plt.xlabel('Years', fontsize='16') plt.plot(color='k', label='temperature change') plt.ylabel('Temperature(K)', fontsize='16') plt.title('Temperature change with Hysteresis', fontsize='20') plt.show() |
C:\Users\simon\AppData\Local\Temp\ipykernel_15696\1552508001.py:1: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead. plt.style.use('seaborn')
02 - Weather station data files¶
I downloaded 10 min data from the recently launched ZAMG data hub. The data file contains selected parameters from the "INNSBRUCK-FLUGPLATZ (ID: 11804)" weather station.
You can download the data from the following links (right-click + "Save as..."):
- station data
- parameter metadata
- station list from the ZAMG (in a better format than last time)
Let me open the data for you and display its content:
1 2 3 | import pandas as pd import numpy as np import matplotlib.pyplot as plt |
1 2 | df = pd.read_csv('INNSBRUCK-FLUGPLATZ_Datensatz_20150101_20211231.csv', index_col=1, parse_dates=True) df = df.drop('station', axis=1) |
02-01: after reading the documentation of the respective functions (and maybe try a few things yourself), explain in plain sentences:
- what am I asking pandas to do with the
index_col=1, parse_dates=True
keyword arguments? Why am I doing this? - what am I asking pandas to do with
.drop()
? Whyaxis=1
?
index_col=1: An integer index starting from 1 is assigned to the DataFrame by default. We can explicitly define a column to be used as index. For example, we may want to use the first column as index like in the list below.
parse_dates=True: We can use the parse_dates parameter to convince pandas to turn things into real datetime types.
drop(): This function removes rows or columns by specifying label names and corresponding axis. The Index 'Station' is not showen.
axis=1: This drops the column. It's used here, because axis=0 would mean that the index gets dropped.
1 2 | dfmeta = pd.read_csv('ZEHNMIN Parameter-Metadaten.csv', index_col=0) dfmeta.loc[df.columns] |
Kurzbeschreibung | Beschreibung | Einheit | |
---|---|---|---|
DD | Windrichtung | Windrichtung, vektorielles Mittel über 10 Minuten | ° |
FF | vektorielle Windgeschwindigkeit | Windgeschwindigkeit, vektorielles Mittel über ... | m/s |
GSX | Globalstrahlung | Globalstrahlung, arithmetisches Mittel über 10... | W/m² |
P | Luftdruck | Luftdruck, Basiswert zur Minute10 | hPa |
RF | Relative Feuchte | Relative Luftfeuchte, Basiswert zur Minute10 | % |
RR | Niederschlag | 10 Minuten Summe des Niederschlags, Summe der ... | mm |
SO | Sonnenscheindauer | Sonnenscheindauer, Sekundensumme über 10 Minuten | s |
TB1 | Erdbodentemperatur in 10cm Tiefe | Erdbodentemperatur in 10cm Tiefe, Basiswert zu... | °C |
TB2 | Erdbodentemperatur in 20cm Tiefe | Erdbodentemperatur in 20cm Tiefe, Basiswert zu... | °C |
TB3 | Erdbodentemperatur in 50cm Tiefe | Erdbodentemperatur in 50cm Tiefe, Basiswert zu... | °C |
TL | Lufttemperatur in 2m | Lufttemperatur in 2m Höhe, Basiswert zur Minute10 | °C |
TP | Taupunkt | Taupunktstemperatur, Basiswert zur Minute10 | °C |
02-02: again, explain in plain sentences what the dfmeta.loc[df.columns]
is doing, and why it works that way.
.loc[] is primarily label based, but may also be used with a boolean array and accesses a group of rows and columns by label(s) or a boolean array.
1 | dfh = df.resample('H').mean() |
02-03: explore the dfh
dataframe. Explain, in plain words, what the purpose of .resample('H')
followed by mean()
is. Explain what .resample('H').max()
and .resample('H').sum()
would do.
".resample('H')" reduces the dataframe to only the hourly data.
".mean()" returns the average of our data across a specified axis. In our cas the hourly data to the 10-min-data we had before.
".resample('H').max()" would take the 10-min data and display it as a dataframe with the maximums of the hourly values.
".resample('H').sum()" would take the sum and compute the hourly values from the 10-min data.
02-04: Using np.allclose
, make sure that the average of the first hour (that you'll compute yourself from df
) is indeed equal to the first row of dfh
. Now, two variables in the dataframe have units that aren't suitable for averaging. Please convert the following variables to the correct units:
RR
needs to be converted from the average of 10 min sums to mm/hSO
needs to be converted from the average of 10 min sums to s/h
1 2 3 | average_df = df.iloc[:6].mean() average_dfh = dfh.iloc[:1] np.allclose(average_df, average_dfh, atol=0.005) |
True
1 2 | dfh.RR = df['RR'].resample('H').sum() dfh.SO = df.SO.resample('H').sum() |
03 - Precipitation¶
In this section, we will focus on precipitation only.
03-01: Compute the average annual precipitation (m/year) over the 7-year period.
1 | dfwRR = dfh['RR'] |
1 2 3 4 | dfwRR_mean_per_year = (dfwRR*24*365).resample('Y').mean() print(np.average(dfwRR_mean_per_year), 'mm/yr.') print(np.average(dfwRR_mean_per_year)/1000, 'm/yr.') |
919.841881342701 mm/yr. 0.919841881342701 m/yr.
03-02: What is the smallest non-zero precipitation measured at the station? What is the maximum hourly precipitation measured at the station? When did this occur?
1 2 3 4 5 6 7 | dfwRR_values = dfwRR[dfwRR > 0] min_RR = dfwRR_values.min() max_RR = dfwRR_values.max() print(min_RR, 'mm/hr.') print(max_RR, 'mm/hr.') |
0.1 mm/hr. 22.2 mm/hr.
1 2 3 4 5 6 | date_at_min = pd.DataFrame(dfwRR_values[dfwRR_values == min_RR].index.values) date_at_max = pd.DataFrame(dfwRR_values[dfwRR_values == max_RR].index.values) display(date_at_min) display(date_at_max) |
0 | |
---|---|
0 | 2015-01-02 16:00:00 |
1 | 2015-01-11 10:00:00 |
2 | 2015-01-14 16:00:00 |
3 | 2015-01-18 04:00:00 |
4 | 2015-01-24 04:00:00 |
... | ... |
1648 | 2021-12-13 05:00:00 |
1649 | 2021-12-13 06:00:00 |
1650 | 2021-12-13 07:00:00 |
1651 | 2021-12-30 09:00:00 |
1652 | 2021-12-30 11:00:00 |
1653 rows × 1 columns
0 | |
---|---|
0 | 2021-09-16 22:00:00 |
03-03: Plot a histogram of hourly precipitation, with bins of size 0.2 mm/h, starting at 0.1 mm/h and ending at 25 mm/h. Plot the same data, but this time with a logarithmic y-axis. Compute the 99th percentile (or quantile) of hourly precipitation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | dfwRRh = dfwRR[dfwRR >= 0.1] #calculate bin size bs = (25-0.1)/0.2 ax = dfwRRh.plot.hist(bins=round(bs), label="hourly precipitation",color = "green") plt.style.use('seaborn') plt.title('Hourly Precipitation', fontsize='20') plt.xlabel('Precipitation (mm/hr)', fontsize='16') plt.ylabel('Frequency (hrs)', fontsize='16') plt.legend(loc='center right', fontsize='16') plt.show(); |
C:\Users\simon\AppData\Local\Temp\ipykernel_15696\2875675565.py:9: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead. plt.style.use('seaborn')
1 2 3 4 5 6 7 8 9 | ax = dfwRRh.plot.hist(bins=round(bs), label="hourly precipitation",color = "green") plt.style.use('seaborn') plt.title('Hourly Precipitation', fontsize='20') plt.xlabel('precipitation in mm/hr', fontsize='16') plt.ylabel('frequency (of hrs)', fontsize='16') plt.legend(loc='center right', fontsize='16') plt.yscale("log") plt.show(); |
C:\Users\simon\AppData\Local\Temp\ipykernel_15696\3661184671.py:3: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead. plt.style.use('seaborn')
1 2 3 | p = np.percentile(dfwRR, 99) print('The 99th percentile (or quantile) of the hourly precipitation is:',p,'mm/hrs.') |
The 99th percentile (or quantile) of the hourly precipitation is: 2.3330000000001747 mm/hrs.
03-04: Compute daily sums (mm/d) of precipitation (tip: use .resample
again). Compute the average number or rain days per year in Innsbruck (a "rain day" is a day with at least 0.1 mm / d of measured precipitation).
1 2 3 | dfd = dfh.resample('D').sum() rainy_days_year = len(dfd.RR[dfd.RR >= 0.1])/7 print('There are about',round(rainy_days_year),'rainydays per year.') |
There are about 170 rainydays per year.
03-05: Now select (subset) the daily dataframe to keep only daily data in the months of December, January, February (DFJ). To do this, note that dfh.index.month
exists and can be used to subset the data efficiently. Compute the average precipitation in DJF (mm / d), and the average number of rainy days in DJF. Repeat with the months of June, July, August (JJA).
1 2 3 4 5 6 7 8 9 10 11 | dfDJF = dfd[dfd.index.month.isin([12, 1, 2])] dfJJA = dfd[dfd.index.month.isin([6, 7, 8])] DJF_ave_RR_per_day = round(dfDJF.RR.mean(), 0) JJA_ave_RR_per_day = round(dfJJA.RR.mean(), 0) DJF_rainy_days = round(len(dfDJF.RR[dfDJF.RR >= 0.1])/7, 0) JJA_rainy_days = round(len(dfJJA.RR[dfJJA.RR >= 0.1])/7, 0) print('DJF:\n', DJF_ave_RR_per_day, 'mm/d' '\n', DJF_rainy_days, 'rainydays') print('JJA:\n', JJA_ave_RR_per_day, 'mm/d' '\n', JJA_rainy_days, 'rainydays') |
DJF: 2.0 mm/d 38.0 rainydays JJA: 4.0 mm/d 53.0 rainydays
03-06: Repeat the DJF and JJA subsetting, but this time with hourly data. Count the total number of times that hourly precipitation in DJF is above the 99th percentile computed in exercise 03-03. Repeat with JJA.
1 2 3 4 5 | dfDJFh = dfh[dfh.index.month.isin([12, 1, 2])] dfJJAh = dfh[dfh.index.month.isin([6, 7, 8])] print('DJF:', len(dfDJFh[dfDJFh.RR > p].RR), 'hour with more than', p, 'mm/h') print('JJA:', len(dfJJAh[dfJJAh.RR > p].RR), 'hours with more than', p, 'mm/h') |
DJF: 68 hour with more than 2.3330000000001747 mm/h JJA: 308 hours with more than 2.3330000000001747 mm/h
03-07: Compute and plot the average daily cycle of hourly precipitation in DFJ and JJA. I expect a plot similar to this example. To compute the daily cycle, I recommend to combine two very useful tools. First, start by noticing that ds.index.hour
exists and can be used to categorize data. Then, note that df.groupby
exists and can be used exactly for that (documentation).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | DJF = dfh[dfh.index.month.isin([12, 1, 2])] JJA = dfh[dfh.index.month.isin([6, 7, 8])] df_DJF = np.array([np.mean(DJF['RR'][DJF.index.hour == i]) for i in np.array(dfwRR.index.hour[0:24])]) df_JJA = np.array([np.mean(JJA['RR'][JJA.index.hour == i]) for i in np.array(dfwRR.index.hour[0:24])]) plt.subplots(figsize=(8, 5)) xDJF = dfwRR.index.hour[0:24] yDJF = df_DJF*6 plt.plot(xDJF, yDJF, label = 'DJF') xJJA = dfwRR.index.hour[0:24] yJJA = df_JJA*6 plt.plot(xJJA, yJJA, label = 'JJA') plt.style.use('seaborn') plt.title('Precipitation Daily Cycle Innsbruck 2015-2021', fontsize='20') plt.xlabel('hour of day', fontsize='16') plt.ylabel('hourly precipitation (mm/hr)', fontsize='16') plt.legend(loc='center left', fontsize='16') plt.show(); |
C:\Users\simon\AppData\Local\Temp\ipykernel_15696\3152991522.py:17: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead. plt.style.use('seaborn')
04 - A few other variables¶
In this section, we will continue to analyze the weather station data.
04-01: Verify that the three soil temperatures have approximately the same average value over the entire period. Now plot the three soil temperature timeseries in hourly resolution over the course of the year of 2020 (example). Repeat the plot with the month of may 2020.
1 2 3 | dfTB1 = df['TB1'] dfTB2 = df['TB2'] dfTB3 = df['TB3'] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | plt.style.use('seaborn') dfTB1_20 = dfh.TB1[dfh.TB1.index.year == 2020] plt.plot(dfTB1_20, linewidth=0.5, label='10cm') dfTB2_20 = dfh.TB2[dfh.TB2.index.year == 2020] plt.plot(dfTB2_20, linewidth=0.5, label='20cm') dfTB3_20 = dfh.TB3[dfh.TB3.index.year == 2020] plt.plot(dfTB3_20, linewidth=0.5, label='50cm') plt.xlabel('Time (months)', fontsize='16') plt.ylabel('Temperature (°C)',fontsize='16') plt.title('Comparison of Soil Temperatures at 10cm, 20cm and 50cm depth',fontsize='20') plt.legend(loc='center left', fontsize='16') plt.show() |
C:\Users\simon\AppData\Local\Temp\ipykernel_15696\1263263326.py:1: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead. plt.style.use('seaborn')
1 2 3 | TB1_20 = dfTB1[dfTB1.index.year==2020] TB2_20 = dfTB2[dfTB2.index.year==2020] TB3_20 = dfTB3[dfTB3.index.year==2020] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | plt.style.use('seaborn') dfTB1_20_05 = pd.DataFrame({"TB1_20_05": TB1_20[TB1_20.index.month==5]}) plt.plot(dfTB1_20_05, linewidth=1, label='10cm') dfTB2_20_05 = pd.DataFrame({"TB2_20_05": TB2_20[TB2_20.index.month==5]}) plt.plot(dfTB2_20_05, linewidth=1, label='20cm') dfTB3_20_05 = pd.DataFrame({"TB3_20_05": TB3_20[TB3_20.index.month==5]}) plt.plot(dfTB3_20_05, linewidth=1, label='50cm') plt.xlabel('Time (days)', fontsize='16') plt.ylabel('Temperature (°C)',fontsize='16') plt.title('Comparison of Soil Temperatures at 10cm, 20cm and 50cm depth in May',fontsize='20') plt.legend(loc='upper left', fontsize='16') plt.show() |
C:\Users\simon\AppData\Local\Temp\ipykernel_15696\4071913548.py:1: MatplotlibDeprecationWarning: The seaborn styles shipped by Matplotlib are deprecated since 3.6, as they no longer correspond to the styles shipped by seaborn. However, they will remain available as 'seaborn-v0_8-<style>'. Alternatively, directly use the seaborn API instead. plt.style.use('seaborn')
04-02: Plot the average daily cycle of all three soil temperatures.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | dfTB1hm = dfh.TB1.groupby([dfh.index.hour]).mean() plt.plot(dfTB1hm, label='10cm') dfTB2hm = dfh.TB2.groupby([dfh.index.hour]).mean() plt.plot(dfTB2hm, label='20cm') dfTB3hm = dfh.TB3.groupby([dfh.index.hour]).mean() plt.plot(dfTB3hm, label='50cm') plt.xlabel('Time (hours)', fontsize='16') plt.ylabel('Temperature (°C)',fontsize='16') plt.title('Average Daily Cycle of all Soil Temperatures',fontsize='20') plt.legend(loc='upper left', fontsize='16') plt.show() |
04-03: Compute the difference (in °C) between the air temperature and the dewpoint temperature. Now plot this difference on a scatter plot (x-axis: relative humidity, y-axis: temperature difference).
1 2 3 4 5 6 7 8 | temp_diff = df.TL-df.TP plt.scatter(df.RF, temp_diff, s=3) plt.xlabel('Rel. Humidity (%)', fontsize='16') plt.ylabel('Difference in Temperature (°C)',fontsize='16') plt.title('Difference between Air Temperature and Dewpoint Temperature',fontsize='20') plt.show() |
05 - Free coding project¶
1 2 | #!conda install windrose openpyxl from windrose import WindroseAxes |
1 2 3 | %matplotlib inline import matplotlib.cm as cm from math import pi |
1 | df = pd.read_csv('INNSBRUCK-FLUGPLATZ_Datensatz_20150101_20211231.csv', index_col=1, parse_dates=True) |
05-01: Showing the wind direction and the wind speed in a windrose based on the given dataframe of Innsbruck Airport.
1 2 3 4 5 6 7 8 9 | ax = WindroseAxes.from_ax() ax.bar(df.DD, df.FF, normed=True, opening=0.8,bins=[0,5,10,15,20],edgecolor='white') #ax.contourf(df.DD, df.FF, bins=np.arange(0, 8, 1), cmap=cm.hot) #ax.contour(df.DD, df.FF, bins=np.arange(0, 8, 1), colors='black') plt.title('Wind Direction in Degrees Combined with the Speed',fontsize='20') ax.set_legend(loc=4, bbox_to_anchor=(1., -0.07)) plt.show() |