2017-04-12 123 views
0

我想在网格中绘制一系列的seaborn坐标图。我知道小区的数量(可以是奇数或偶数)。 热图将显示“星期几”(y轴)和“一小时”(x轴)的平均“占有率”,例如,他们都共享相同的x/y域。共享坐标轴并移除未使用的matplotlib子图

这里是我当前的代码:

df2 = df[['name','openLots','occupationRatio','DoW','Hour']] 
fig, axs = plt.subplots(figsize=(24,24), nrows=7, ncols=6) 
axs = axs.flatten() 
locations = df2['name'].sort_values().unique() 


def occupation_heatmap (name, ax): 
    dfn = df2[df2['name'] == name] 
    dfn = dfn.groupby(['DoW', 'Hour']).mean()['occupationRatio'].unstack() 
    dfn = dfn.reindex(['Mon', 'Tue', 'Wed','Thu','Fri','Sat','Sun']) 
    sns.heatmap(data=dfn, cmap="coolwarm", vmin=0, vmax=1.0, ax= ax) 
    ax.set_title(name) 


i = 0 
for n in locations: 
    occupation_heatmap (n, axs[i]) 
    i = i+1 

plt.tight_layout() 

它看起来几乎像什么,我想(最后几行): note axis labels, legend and "empty" subplots 但是要我要:

  • 有y轴的标签(DoW)每行只有一次(最左边的图)
  • 只在每行最右边的图上有colormap图例(或者不要完全,颜色是很好的自我explainatory)
  • 删除“空阴谋”的最后一排,因为奇数总数的

非常感谢任何提示

+1

只是为了帮助提高你怎么心智模型事情正在起作用,这些不是“seaborn subplots”,它们是matplotlib subplots,你碰巧使用seaborn函数来绘制数据。 – mwaskom

回答

1

你可以更加灵活只为每个现名轴,像这样:

import matplotlib.pyplot as plt 
import pandas as pd 
import numpy as np 
import seaborn as sns 
import string 

days = ['Mon','Tue','Wed','Thurs','Fri','Sat','Sun'] 
names = [string.lowercase[i] for i in range(22)] 

nItems = 1000 

df = pd.DataFrame() 
df['name'] = [names[i] for i in np.random.randint(0,len(names),nItems)] 
df['openLots'] = np.random.randint(0,100,nItems) 
df['occupationRatio'] = np.random.randint(0,100,nItems) 
df['DoW'] = [days[i] for i in np.random.randint(0,7,nItems)] 
df['Hour'] = np.random.randint(0,12,nItems) 




fig = plt.figure(figsize=(12,12)) 
for index, name in enumerate(names): 
    ax = fig.add_subplot(4,6,index+1) 
    dfn = df.loc[df.name==name] 
    dfn = dfn.groupby(['DoW','Hour']).mean()['occupationRatio'].unstack() 
    dfn = dfn.reindex(days) 

    # Now we can operate on each plot axis individually 
    if index%6!=5: #i.e. 
     # Don't draw a colorbar 
     sns.heatmap(data = dfn, cmap='coolwarm', ax=ax, cbar=False) 
    else: 
     sns.heatmap(data = dfn, cmap='coolwarm', ax=ax) 

    if index%6!=0: 
     # Remove the y-axis label 
     ax.set_ylabel('') 
     ax.set_yticks(()) 

    ax.set_title(name) 

fig.tight_layout() 
fig.show() 

结果: enter image description here 你也可以玩与x轴(例如删除啦贝尔和蜱虫,除了最下面一排)。

+0

谢谢,这对我来说工作得非常好......除了我有一些数据片是完整的NaN,所以不得不包装sns.heatmap(...)变成 '尝试: ... 除了ValueError: pass ' –

1
  • 有y轴标签(DOW)每行(最左边的图)只有一次
    这可以使用sharey = True作为参数传递给plt.subplots完成。
  • 只有每行最右边的图中的颜色表传奇(或离开它完全,颜色是很好的自我explainatory)
    使用cbar = False参数seaborn.heatmap为了不显示彩条。这可以根据子图的实际数量作为绘图函数的输入给出。
  • 除去最后一排的“空阴谋”,因为奇数总数的
    循环创建情节您可以添加另一个循环删除未使用的轴之后。

    for j in range(len(locations), ncols*nrows): 
        axs[j].axis("off") 
    

下面是一个完整的例子(在这里我借了鳕鱼,以从@Robbie一个数据帧):

import matplotlib.pyplot as plt 
import pandas as pd 
import numpy as np 
import seaborn as sns 

days = ['Mon','Tue','Wed','Thurs','Fri','Sat','Sun'] 
names = ["Parkhaus {:02}".format(i+1) for i in range(22)] 

nItems = 1000 

df = pd.DataFrame() 
df['name'] = [names[i] for i in np.random.randint(0,len(names),nItems)] 
df['openLots'] = np.random.randint(0,100,nItems) 
df['occupationRatio'] = np.random.rand(nItems) 
df['DoW'] = [days[i] for i in np.random.randint(0,7,nItems)] 
df['Hour'] = np.random.randint(0,12,nItems) 

df2 = df[['name','openLots','occupationRatio','DoW','Hour']] 
nrows = 4; ncols=6 
fig, axs = plt.subplots(nrows=nrows, ncols=ncols, figsize=(15,9), sharey=True) 
axs = axs.flatten() 
locations = df2['name'].sort_values().unique() 


def occupation_heatmap (name, ax, cbar=False, ylabel=False): 
    dfn = df2[df2['name'] == name] 
    dfn = dfn.groupby(['DoW', 'Hour']).mean()['occupationRatio'].unstack() 
    dfn = dfn.reindex(['Mon', 'Tue', 'Wed','Thu','Fri','Sat','Sun']) 
    sns.heatmap(data=dfn, cmap="coolwarm", vmin=0, vmax=1.0, ax=ax, cbar=cbar) 
    ax.set_title(name) 
    plt.setp(ax.get_yticklabels(), rotation=0) 
    if not ylabel: ax.set_ylabel("") 


for i, n in enumerate(locations): 
    occupation_heatmap (n, axs[i], cbar=i%ncols==ncols-1, ylabel=i%ncols==0) 
for j in range(len(locations), ncols*nrows): 
    axs[j].axis("off") 

plt.tight_layout() 
plt.show() 

enter image description here

相关问题