2014-11-05 21 views
15

Tôi đang vẽ hai bộ dữ liệu với các đơn vị khác nhau trên trục y. Có cách nào để làm cho ve và đường lưới liên kết trên cả hai trục y?Làm cách nào để căn chỉnh đường lưới cho hai thang đo trục y bằng Matplotlib?

Hình ảnh đầu tiên hiển thị những gì tôi nhận được và hình ảnh thứ hai hiển thị những gì tôi muốn nhận.

Đây là mã tôi đang sử dụng để vẽ:

import seaborn as sns 
import numpy as np 
import pandas as pd 

np.random.seed(0) 
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
ax1.plot(pd.Series(np.random.uniform(0, 1, size=10))) 
ax2 = ax1.twinx() 
ax2.plot(pd.Series(np.random.uniform(10, 20, size=10)), color='r') 

Example of unwanted behavior

Example of wanted behavior

+0

Bạn đang tìm kiếm 'ax2.set_ylim ((10, 20))'? – farenorth

+0

Tôi đang tìm cách tổng quát để làm điều đó. tức là nếu tôi nhận được bất kỳ hai tập dữ liệu nào, làm cách nào để thiết lập cốt truyện theo cách mà các đường lưới trùng khớp. –

+0

bạn chỉ cần làm điều đó bằng tay bằng cách đặt giới hạn của bạn và đánh dấu khoảng cách. –

Trả lời

14

Tôi không chắc chắn nếu điều này là cách đẹp nhất để làm điều đó, nhưng nó không sửa chữa nó với một dòng:

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

np.random.seed(0) 
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
ax1.plot(pd.Series(np.random.uniform(0, 1, size=10))) 
ax2 = ax1.twinx() 
ax2.plot(pd.Series(np.random.uniform(10, 20, size=10)), color='r') 

# ADD THIS LINE 
ax2.set_yticks(np.linspace(ax2.get_yticks()[0], ax2.get_yticks()[-1], len(ax1.get_yticks()))) 

plt.show() 
+5

Không quá cầu kỳ, nhưng đường màu xanh hiện dưới lưới và đường màu đỏ nằm phía trên lưới. Vì vậy, tôi thêm 'ax2.grid (None) 'sau dòng ax2.set_yticks và nhận được cùng một dấu tích và đường lưới, nhưng cả hai dòng trên lưới điện bây giờ. – benten

4

tôi có thể giải quyết nó bằng cách khử hoạt ax.grid(None) tại một trong những grid`s trục:

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

fig = plt.figure() 
ax1 = fig.add_subplot(111) 
ax1.plot(pd.Series(np.random.uniform(0, 1, size=10))) 
ax2 = ax1.twinx() 
ax2.plot(pd.Series(np.random.uniform(10, 20, size=10)), color='r') 
ax2.grid(None) 

plt.show() 

Figure Result

+0

Thật không may điều này loại bỏ lưới từ một trong các trục chứ không phải là sắp xếp các ve và lưới. Trong ví dụ của bạn, bạn tình cờ có các ve ở cùng vị trí trên cả hai trục, nhưng nếu trục kia ở vị trí khác thì các dấu tích của trục đó sẽ không thẳng hàng với lưới. –

+0

Nhưng nó trả lời câu hỏi của bạn và tái tạo hình ảnh theo cách bạn muốn. Bạn có thể cụ thể hơn về câu hỏi của bạn. – arnaldo

+0

chạy mã của bạn một vài lần và bạn sẽ thấy những gì tôi có ý nghĩa. –

6

tôi đã viết chức năng này mà mất Matplotlib trục đối tượng ax1, AX2, và nổi minresax1 minresax2:

def align_y_axis(ax1, ax2, minresax1, minresax2): 
    """ Sets tick marks of twinx axes to line up with 7 total tick marks 

    ax1 and ax2 are matplotlib axes 
    Spacing between tick marks will be a factor of minresax1 and minresax2""" 

    ax1ylims = ax1.get_ybound() 
    ax2ylims = ax2.get_ybound() 
    ax1factor = minresax1 * 6 
    ax2factor = minresax2 * 6 
    ax1.set_yticks(np.linspace(ax1ylims[0], 
           ax1ylims[1]+(ax1factor - 
           (ax1ylims[1]-ax1ylims[0]) % ax1factor) % 
           ax1factor, 
           7)) 
    ax2.set_yticks(np.linspace(ax2ylims[0], 
           ax2ylims[1]+(ax2factor - 
           (ax2ylims[1]-ax2ylims[0]) % ax2factor) % 
           ax2factor, 
           7)) 

Nó tính và đặt ve sao cho có bảy bọ ve. Dấu tích thấp nhất tương ứng với dấu tick thấp nhất hiện tại và tăng số lần đánh dấu cao nhất sao cho sự tách biệt giữa mỗi bọ là bội số nguyên của minrexax1 hoặc minrexax2.

Để làm cho nó Nói chung, bạn có thể thiết lập tổng số ve bạn muốn bằng cách thay đổi từng 7 bạn nhìn thấy với tổng số tick, và thay đổi 6 với tổng số tick trừ 1.

tôi đặt một yêu cầu kéo để kết hợp một số này vào matplotlib.ticker.LinearLocator:

https://github.com/matplotlib/matplotlib/issues/6142

trong tương lai (? Matplotlib 2.0 có lẽ), hãy thử:

import matplotlib.ticker 
nticks = 11 
ax1.yaxis.set_major_locator(matplotlib.ticker.LinearLocator(nticks)) 
ax2.yaxis.set_major_locator(matplotlib.ticker.LinearLocator(nticks)) 

Điều đó chỉ hoạt động và chọn các dấu tích thuận tiện cho cả hai trục y.

+1

Nếu chúng ta muốn sử dụng matplotlib.ticker, làm thế nào để chúng ta có được tự động số lượng bọ ve thay vì phải chỉ định nticks? – Spinor8

0

Nếu bạn đang sử dụng nhãn trục, giải pháp của Leo có thể push them off the side, do độ chính xác của các con số trong các dấu tích.

Vì vậy, ngoài một cái gì đó giống như giải pháp của Leo (lặp đi lặp lại ở đây),

ax2.set_yticks(np.linspace(ax2.get_yticks()[0],ax2.get_yticks()[-1],len(ax1.get_yticks()))) 

bạn có thể sử dụng cài đặt autolayout, như đã đề cập trong this answer; ví dụ, trước đó trong kịch bản của bạn, bạn có thể cập nhật rcParams:

from matplotlib import rcParams 
rcParams.update({'figure.autolayout': True}) 

Trong một vài trường hợp thử nghiệm, điều này dường như tạo ra kết quả mong đợi, với cả hai ve lót-up và nhãn chứa đầy đủ trong đầu ra.

0

Mã này sẽ đảm bảo rằng lưới từ cả hai trục thẳng hàng với nhau, mà không phải ẩn đường lưới từ một trong hai nhóm. Trong ví dụ này, nó cho phép bạn kết hợp với bất kỳ đường lưới nào tốt hơn. Điều này tạo nên ý tưởng từ @Leo. Hy vọng nó giúp!

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

fig = plt.figure() 
ax1 = fig.add_subplot(111) 
ax1.plot(pd.Series(np.random.uniform(0,1,size=10))) 
ax2 = ax1.twinx() 
ax2.plot(pd.Series(np.random.uniform(10,20,size=10)),color='r') 
ax2.grid(None) 

# Determine which plot has finer grid. Set pointers accordingly 
l1 = len(ax1.get_yticks()) 
l2 = len(ax2.get_yticks()) 
if l1 > l2: 
    a = ax1 
    b = ax2 
    l = l1 
else: 
    a = ax2 
    b = ax1 
    l = l2 

# Respace grid of 'b' axis to match 'a' axis 
b_ticks = np.linspace(b.get_yticks()[0],b.get_yticks()[-1],l) 
b.set_yticks(b_ticks) 

plt.show() 
0

Tôi gặp vấn đề tương tự, ngoại trừ trường hợp này là trục x thứ cấp. Tôi đã giải quyết bằng cách thiết lập x trung học của tôi trục bằng với giới hạn của các ví dụ axis.The chính của tôi dưới đây là không thiết lập các giới hạn của trục thứ hai bằng đầu tiên: ax2 = ax.twiny() enter image description here

Khi tôi thiết lập giới hạn của trục thứ hai bằng số ax2.set_xlim(ax.get_xlim()) đầu tiên ở đây là kết quả của tôi: enter image description here

Các vấn đề liên quan