简体   繁体   English

Matplotlib:具有两个不同 y 轴的二维子图

[英]Matplotlib: 2D subplots with two different y-axis

I want to make a combination of two solutions.我想结合两种解决方案。

I have data like this:我有这样的数据:

db = np.array([('Billboard', 1, 520.0, 3),
           ('Billboard', 2, 520.0, 2),
           ('Billboard', 3, 612.0, 0),
           ('Billboard', 4, 410.0, 4),
           ('Careerbuilder', 1, 410.0, 0),
           ('Careerbuilder', 2, 820.0, 0),
           ('Careerbuilder', 3, 410.0, 1),
           ('Careerbuilder', 4, 820.0, 0),
           ('Monster.com', 1, 500.0, 3),
           ('Monster.com', 2, 500.0, 4),
           ('Monster.com', 3, 450.0, 0),
           ('Monster.com', 4, 450.0, 7),
           ('Ads', 1, 120.0, 0),
           ('Ads', 2, 0.0, 1),
           ('Ads', 3, 50.0, 1),
           ('Ads', 4, 100.0, 0),
          ], dtype=[('Source', 'U20'), ('Month', int), ('Spent', float), ('count', int)])
db = pd.DataFrame(db)

Solution 1: good layout but blue plots are not readable because values are too small compared to bars.解决方案 1:良好的布局,但蓝色图不可读,因为与条形图相比,值太小。

plt.figure(figsize=(10, 5))

for i, sourse in enumerate(db['Source'].unique()):
    plt.subplot(2, 2, i+1)
    plt.title(db['Source'].unique()[i]) 
    subdf = db[db['Source'] == sourse][['Month','count', 'Spent']].set_index('Month')
    plt.plot(subdf.index, subdf['count'], color='blue')  
    plt.bar(subdf.index, subdf['Spent'], color='red', alpha=0.5)

plt.show()

Solution 1解决方案 1

Solution 2: blue plots are showed correctly with the addition of another y-axis, but the layout is vertical and not very nice.解决方案 2:添加另一个 y 轴后,蓝色图正确显示,但布局是垂直的,不是很好。

for i, sourse in enumerate(db['Source'].unique()):
    fig, ax = plt.subplots()
    plt.title(db['Source'].unique()[i]) 
    subdf = db[db['Source'] == sourse][['Month','count', 'Spent']].set_index('Month')
    
    ax.bar(subdf.index, subdf['Spent'], color='red', alpha=0.5)
    ax.set_xlabel("Months",fontsize=14)
    ax.set_ylabel("Money spent",color="red",fontsize=14)
    ax.set_xticks(list(range(1,5)))

    ax2 = ax.twinx()
    ax2.plot(subdf.index, subdf['count'], color='blue')
    ax2.yaxis.set_major_locator(ticker.MultipleLocator(1.00))
    ax2.set_ylabel('People hired', color='blue',fontsize=14)
    plt.ylim(0)
    
plt.show()

Solution 2解决方案 2

So I have more than 20 subplots, so the vertical layout is not the best solution.所以我有20多个子图,所以垂直布局不是最好的解决方案。 But I can't think of a way to use these both solutions together... The best what I could come up with is但我想不出同时使用这两种解决方案的方法......我能想到的最好的办法是

m = 0
n = 0
fig, ax = plt.subplots(2, 2, sharex='col', sharey=False, figsize=(10, 5))

for i, sourse in enumerate(db['Source'].unique()):
    plt.title(db['Source'].unique()[i]) 
    subdf = db[db['Source'] == sourse][['Month','count', 'Spent']].set_index('Month')
    
    ax[i+m,i+n].bar(subdf.index, subdf['Spent'], color='red', alpha=0.5)
    ax.set_xlabel("Months",fontsize=14)
    ax.set_ylabel("Money spent",color="red",fontsize=14)

    ax2 = ax.twinx()
    ax2[i+m,i+n].plot(subdf.index, subdf['count'], color='blue')
    ax2.yaxis.set_major_locator(ticker.MultipleLocator(1.00))
    ax2.set_ylabel('People hired', color='blue',fontsize=14)
    plt.xticks(list(range(1, 13)))
    plt.ylim(0)
    
    n += 1
    if n == 2:
        m += 1
        n == 0
    
plt.show()

But it showes an error但它显示一个错误

AttributeError                            Traceback (most recent call last)
<ipython-input-142-aa24c581b7bf> in <module>
      8 
      9     ax[i+m,i+n].bar(subdf.index, subdf['Spent'], color='red', alpha=0.5)
---> 10     ax.set_xlabel("Months",fontsize=14)
     11     ax.set_ylabel("Money spent",color="red",fontsize=14)
     12 

AttributeError: 'numpy.ndarray' object has no attribute 'set_xlabel'

For this I found this answer AttributeError: 'numpy.ndarray' object has no attribute 'plot' but don't know how to apply it here!为此,我找到了这个答案AttributeError: 'numpy.ndarray' object has no attribute 'plot'但不知道如何在这里应用它!

I slightly modified your solution #1 and applied the double y-axes plot.我稍微修改了您的解决方案 #1 并应用了双 y 轴 plot。

plt.figure(figsize=(10, 5))

for i, sourse in enumerate(db['Source'].unique()):
  plt.subplot(2, 2, i+1)
  plt.title(db['Source'].unique()[i]) 
  subdf = db[db['Source'] == sourse][['Month','count', 'Spent']].set_index('Month')
  plt.bar(subdf.index, subdf['Spent'], color='red', alpha=0.5)
  ax = plt.gca()  # get current axis
  twin_ax = ax.twinx()
  twin_ax.plot(subdf.index, subdf['count'], color='blue')  

plt.tight_layout()
plt.show()

I can also explain the error in your last solution.我还可以解释您上一个解决方案中的错误。 In the following line在下一行

fig, ax = plt.subplots(2, 2, sharex='col', sharey=False, figsize=(10, 5))

the ax is an numpy array. ax是 numpy 阵列。 Its shape is (2, 2) , and it is something like,它的形状是(2, 2) ,它类似于,

ax = np.array([
    [ax_row_0_col_0, ax_row_0_col1],
    [ax_row_1_col_0, ax_row_1_col1],
])

In this case, we can not do在这种情况下,我们不能做

ax.set_xlabel("Months",fontsize=14)

but we have to do something like但我们必须做类似的事情

row, col = 0, 0
ax[row, col].set_xlabel("Months",fontsize=14)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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