首页 > 解决方案 > Matplotlib 子图使用嵌套 for 循环

问题描述

第一次发帖,所以提前为错误道歉。

我正在尝试为嵌套的 for 循环创建一个 matplotlib 子图。

我的数据是广告数据关键字、点击次数、出价、day_of_week 列

我想为每个关键字创建 8 个图,x = 出价,y = 点击。我希望第一个情节有该关键字的出价和点击次数,其他 7 个情节有一周中的每一天的出价和点击次数(一周中的每一天一个情节)

现在,我可以将第一个图放到子图网格上(格式看起来很奇怪),其他 7 个图单独出现,而不是显示在子图中。我创建了一个假 df 并包含了我在下面使用的代码。

我想做的事:

  1. 要修复的第一个绘图的格式
  2. 我希望星期一的情节在第二个子情节点

我将不胜感激任何和所有提示。谢谢!

我的数据图像

我当前的输出

我的代码:

#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)

标签: pythonmatplotlibvisualizationnested-loopssubplot

解决方案


我随机生成了你的数据,你可以忽略这个:

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

我稍微修改了你的代码。基本上,如果您正在使用子图,您应该使用axes[row, col]而不是访问它们plt,并且我修改了您ndict以匹配从零开始的索引(0 是您的“一般”图):

#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)

图片


推荐阅读