Search code examples
pythonpandasmatplotlibsubplotwindrose

seasonal WindRose subplots


I'm trying to make WindRoses for the four seasons of the year on the same plot. I tried to follow the method from Subplot of Windrose in matplotlib but the method did not work for me.

I also tried the following from https://matplotlib.org/stable/gallery/subplots_axes_and_figures/subplots_demo.html: (the index is in the DateTime format).

df = df.between_time('8:00', '21:00') #day
#df = df.between_time() #night
spring = df[~df.index.month.isin([1,2,6,7,8,9,10,11,12])] #spring
summer = df[~df.index.month.isin([1,2,3,4,5,9,10,11,12])] #summer
fall = df[~df.index.month.isin([1,2,3,4,5,6,7,8,12])] #fall
winter = df[~df.index.month.isin([3,4,5,6,7,8,9,10,11])] #winter


#sonny bono

x = [spring.ws_5408,summer.ws_5408,fall.ws_5408,winter.ws_5408]
y = [spring.dir_5408,summer.dir_5408,fall.dir_5408,winter.dir_5408]
ws1 = spring.ws_5408
wd1 = spring.dir_5408
ws2 = summer.ws_5408
wd2 = summer.dir_5408
ws3 = fall.ws_5408
wd3 = fall.dir_5408
ws4 = winter.ws_5408
wd4 = winter.dir_5408
#fig = 'SonnyBono_rose.png'

ax = WindroseAxes.from_ax()
fig, ax = plt.subplots(2, 2)
ax[0, 0].bar(ws1, wd1, normed=True, opening=0.8, edgecolor='white', bins=np.arange(0, 15, 3),cmap=cm.rainbow, nsector=20)
ax[0, 0].set_title('Spring')
ax[0, 1].bar(ws2, wd2, normed=True, opening=0.8, edgecolor='white', bins=np.arange(0, 15, 3),cmap=cm.rainbow, nsector=20)
ax[0, 1].set_title('Summer')
ax[1, 0].bar(ws3, wd3, normed=True, opening=0.8, edgecolor='white', bins=np.arange(0, 15, 3),cmap=cm.rainbow, nsector=20)
ax[1, 0].set_title('Fall')
ax[1, 1].bar(ws4, wd4, normed=True, opening=0.8, edgecolor='white', bins=np.arange(0, 15, 3),cmap=cm.rainbow, nsector=20)
ax[1, 1].set_title('Winter')
ax.set_legend(decimal_places=1, units='m/s',fontsize='x-large', loc='best')

I get an error message that says AttributeError: 'Rectangle' object has no property 'normed'. This code also doesn't give me four wind roses in a subplot but instead outputs four blank scatterplots. I'm not sure what to do. My dataframe can be found on this link: https://drive.google.com/file/d/1B2SiNfOVZt9zJ_XTHfl61Ngp7UiWAD16/view?usp=sharing


Solution

  • I managed to reproduce your question. Please keep in mind @mozway suggestion about mcve for your next questions.

    Prepare data

    I downloaded locally your data in my working direction.

    import pandas as pd
    import numpy as np
    from matplotlib import pyplot as plt
    import matplotlib.cm as cm
    import windrose 
    
    
    df = pd.read_csv("allregions_wind_hourly.csv")
    
    # I keep only the columns we are going to use
    # you can check with df.memory_usage(deep=True).sum()/1024**2
    # how much RAM is your data using
    cols_to_keep = ["date", "ws_5408", "dir_5408"]
    df = df[cols_to_keep]
    
    # Convert to datetime and extract season
    df["date"] = df["date"].astype("M8")
    df["season"] = df["date"].dt.month%12 //3 +1
    
    season_dict = {1: "winter", 2: "spring", 
                   3: "summer", 4: "autumn"}
    df["season"] = df["season"].map(season_dict)
    # Filter
    df = df.set_index("date")
    df = df.between_time('8:00', '21:00') #day
    

    Regarding seasons I used this answer.

    Plot

    seasons = [v for k,v in season_dict.items()]
    bins=np.arange(0, 15, 3)
    nrows, ncols = 2, 2
    fig = plt.figure(figsize=(15, 15))
    # plt.subplots_adjust(hspace=0.5)
    fig.tight_layout()
    for i, season in enumerate(seasons):
        d =  df[df["season"].eq(season)].reset_index(drop=True)
        ax = fig.add_subplot(nrows, ncols, i + 1, projection="windrose")
        ax.set_title(season.capitalize(),fontsize=14, weight='bold')
        ax.bar(d["dir_5408"], d["ws_5408"],
               normed=True, opening=0.8,
               bins=bins, cmap=cm.rainbow,
               nsector=20)
    

    enter image description here

    EDIT: in case you need a sort of interactive plot you can consider using plotly. Here an example of windrose

    EDIT2: In case you really want to share the dataframe you should consider saving the cleaned one to parquet and push to your github account and share the link so one can read it directly from Jupyter. The cleaned dataframe in parquet it's about 69x smaller than your original csv. Finally here you can find several examples of windrose usage.