简体   繁体   中英

Matplotlib subplot using nested for loop

first time poster so apologize in advance for mistakes.

I'm trying to create a matplotlib subplots for a nested for loop.

My data is advertisement data keyword, clicks, bid, day_of_week columns

I want to create 8 plots for each keyword, with x = bids and y = clicks. I would like the first plot to have bids and clicks for that keyword, and 7 others to have bids and clicks for each day of the week (one plot per day of the week)

Right now, I'm able to get the first plot onto the subplot grid (with the formatting looking weird) and the other 7 plots are appearing on their own instead of showing in the subplots. I created a fake df and included the code I'm using below.

What I would like to do:

  1. the formatting of the first plot to be fixed
  2. I would like the plot for Monday to be in the second subplot spot

I would appreciate any and all tips. Thank you!

image of my data

My current output

My code:

#creating a unique list of days for the 
day_list = df['day_of_week'].unique()

#create a plot for each keyword  by day of week

def keyword_plots(x, y):
    #create dict so that each day has a spot on the figure subplot
    ndict = {'Monday': 2, 
         'Tuesday': 3, 
         'Wednesday': 4,
         'Thursday': 5,
         'Friday': 6,
         'Saturday' : 7,
         'Sunday' :8}

    #dealing with colors
    color_labels = y['day_of_week'].unique()
    rgb_values = sns.color_palette("husl", 7)
    color_map = dict(zip(color_labels, rgb_values))

    #loop through each keyword and add it to the plot (first spot)
    for each in x:
    
        #create subset for each keyword
        subset = y[y["keyword"]==each][["clicks","bid", "day_of_week"]]
    
        #create one figure per keyword with 8 spaces
        fig, axes = plt.subplots(2, 4, figsize=(20, 8))
        fig.tight_layout()
    
        #add this keyword plot to the first subplot space
        ax=fig.add_subplot(4,4,1)
        plt.scatter(subset['bid'], subset['clicks'], c = subset['day_of_week'].map(color_map), alpha=0.5)
    
        #labels
        plt.title(each)
        plt.xlabel("bid")
        plt.ylabel("clicks")
    
        #trendlines
        z = np.polyfit(subset["bid"], subset['clicks'], 1)
        p = np.poly1d(z)
        pylab.plot(subset['bid'],p(subset['bid']),"r--")
        plt.show()
    
        #loop through each day of the week and create one plot per week per keyword (7 total for Mon-Sun)
        for i in day_list:
        
            #subset the data
            day_sub = subset[subset["day_of_week"]==i][["clicks","bid", "day_of_week"]]
        
            #add the plot to the space corresponding to day of week (in ndict)
            ax=fig.add_subplot(4, 4, ndict[i])
        
            #create plot
            plt.scatter(day_sub['bid'], day_sub['clicks'], c = day_sub['day_of_week'].map(color_map), alpha=0.5)
        
            #plot lables
            plt.title(each + " " + i)
            plt.xlabel("bid")
            plt.ylabel("clicks")
        
            #trendline
            z = np.polyfit(day_sub["bid"], day_sub['clicks'], 1)
            p = np.poly1d(z)
            pylab.plot(day_sub['bid'],p(day_sub['bid']),"r--")
            plt.show()

keyword_plots(list_of_keywords_I_want, keywords_df)

I generated your data randomly, you can just ignore this:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from itertools import cycle, islice

size = 40
clicks = np.random.randint(6, size=size)
bids = np.random.rand(size)*6
day_of_week = ['Friday', 'Monday', 'Saturday', 'Sunday', 'Thursday', 'Tuesday', 'Wednesday']
day_of_week = list(islice(cycle(day_of_week), size))
day_of_week.sort()
day_of_week
keywords = ['lobsters']*40
df = pd.DataFrame([keywords, clicks, bids, day_of_week], index=['keyword', 'clicks', 'bid', 'day_of_week']).T
df['clicks'] = df['clicks'].astype(int)
df['bid'] = df['bid'].astype(float)

#creating a unique list of days for the 
day_list = df['day_of_week'].unique()
list_of_keywords_I_want = ['lobsters']
keywords_df = df

I modified your code a little bit. Basically if you are working with subplots you should access them with the axes[row, col] instead of plt , and I modified your ndict to match zero-based indexing (with 0 being your 'general' plot):

#create a plot for each keyword  by day of week

def keyword_plots(x, y):
    #create dict so that each day has a spot on the figure subplot
    ndict = {'Monday': 1, 
         'Tuesday': 2, 
         'Wednesday': 3,
         'Thursday': 4,
         'Friday': 5,
         'Saturday' : 6,
         'Sunday' :7}

    #dealing with colors
    color_labels = y['day_of_week'].unique()
    rgb_values = sns.color_palette("husl", 7)
    color_map = dict(zip(color_labels, rgb_values))

    #loop through each keyword and add it to the plot (first spot)
    for each in x:
        #create subset for each keyword
        subset = y[y["keyword"]==each][["clicks","bid", "day_of_week"]]
    
        #create one figure per keyword with 8 spaces
        fig, axes = plt.subplots(2, 4, figsize=(20, 8))
        fig.tight_layout()
    
        axes[0,0].scatter(subset['bid'], subset['clicks'], c = subset['day_of_week'].map(color_map), alpha=0.5)
        
        #labels
        axes[0,0].set_title(each)
        axes[0,0].set_xlabel("bid")
        axes[0,0].set_ylabel("clicks")
        
        #trendlines
        z = np.polyfit(subset["bid"], subset['clicks'], 1)
        p = np.poly1d(z)
        axes[0,0].plot(subset['bid'],p(subset['bid']),"r--")
    
        #loop through each day of the week and create one plot per week per keyword (7 total for Mon-Sun)
        for i in day_list:
            #subset the data
            day_sub = subset[subset["day_of_week"]==i][["clicks","bid", "day_of_week"]]
        
            #create plot
            axes[ndict[i] // 4, ndict[i] % 4].scatter(day_sub['bid'], day_sub['clicks'], c = day_sub['day_of_week'].map(color_map), alpha=0.5)
        
            #plot lables
            axes[ndict[i] // 4, ndict[i] % 4].set_title(each + " " + i)
            axes[ndict[i] // 4, ndict[i] % 4].set_xlabel("bid")
            axes[ndict[i] // 4, ndict[i] % 4].set_ylabel("clicks")
        
            #trendline
            z = np.polyfit(day_sub["bid"], day_sub['clicks'], 1)
            p = np.poly1d(z)
            axes[ndict[i] // 4, ndict[i] % 4].plot(day_sub['bid'],p(day_sub['bid']),"r--")
        plt.show()
keyword_plots(list_of_keywords_I_want, keywords_df)

图片

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM