2012-04-16 34 views
21

Tôi đang tạo một âm mưu trong python. Có cách nào để quy mô lại trục theo một yếu tố không? Các lệnh yscalexscale chỉ cho phép tôi tắt quy mô nhật ký.Thay đổi thang âm mưu bằng một hệ số trong matplotlib

Chỉnh sửa:
Ví dụ: Nếu tôi có một âm mưu khi thang đo x chuyển từ 1 nm đến 50 nm, thang đo x sẽ nằm trong khoảng từ 1x10^(- 9) đến 50x10^(- 9) và tôi muốn nó thay đổi từ 1 đến 50. Vì vậy, tôi muốn các chức năng âm mưu chia các giá trị x đặt trên cốt truyện với 10^(- 9)

+4

Yotam, dường như bạn có nhiều câu hỏi nổi bật đã được trả lời nhưng bạn vẫn chưa chấp nhận câu trả lời. Vui lòng chấp nhận câu trả lời cho các câu hỏi cũ hoặc thêm thông tin bổ sung để chúng tôi có thể giúp bạn! – Hooked

Trả lời

10

Thay vì thay đổi bọ ve, tại sao không thay đổi các đơn vị thay thế? Tạo một mảng riêng biệt X của các giá trị x có đơn vị tính bằng nm. Bằng cách này, khi bạn vẽ dữ liệu, nó đã có định dạng đúng! Chỉ cần đảm bảo bạn thêm xlabel để cho biết các đơn vị (nên luôn luôn được thực hiện sau đó).

from pylab import * 

# Generate random test data in your range 
N = 200 
epsilon = 10**(-9.0) 
X = epsilon*(50*random(N) + 1) 
Y = random(N) 

# X2 now has the "units" of nanometers by scaling X 
X2 = (1/epsilon) * X 

subplot(121) 
scatter(X,Y) 
xlim(epsilon,50*epsilon) 
xlabel("meters") 

subplot(122) 
scatter(X2,Y) 
xlim(1, 50) 
xlabel("nanometers") 

show() 

enter image description here

+0

Đây là những gì tôi muốn làm bây giờ. Tôi nghĩ có cách tao nhã hơn. – Yotam

5

để thiết lập một loạt các trục x, bạn có thể sử dụng set_xlim(left, right), here are the docs

cập nhật:

Có vẻ như bạn muốn một âm mưu giống hệt nhau, nhưng chỉ thay đổi 'giá trị đánh dấu', bạn có thể làm điều đó bằng cách nhận các giá trị đánh dấu và sau đó chỉ cần thay đổi chúng thành bất kỳ điều gì bạn muốn. Vì vậy, cho nhu cầu của bạn, nó sẽ là như thế này:

ticks = your_plot.get_xticks()*10**9 
your_plot.set_xticklabels(ticks) 
+0

Để hiểu biết của tôi, xlim thay đổi phạm vi của cốt truyện và không quy mô nó. Xem ví dụ của tôi. – Yotam

+0

@Yotam - Vì vậy, bạn muốn cốt truyện giống hệt nhau, nhưng các giá trị trên nhãn tỷ lệ x sẽ thay đổi? – fraxel

+0

Giải pháp đơn giản đáng ngạc nhiên. Tuy nhiên, tôi thấy rằng điều này dẫn đến nhãn với số thập phân, ngay cả khi sử dụng một mã mà chỉ nên hiển thị số nguyên (ví dụ: MultipleLocator hoặc MaxNLocator). Tôi thấy rằng điều này có thể được giải quyết bằng cách sử dụng 'ticks.astype (int)' thay vì 'ticks'. –

40

Như các bạn đã thấy, xscaleyscale không hỗ trợ một đơn giản tuyến tính lại tỉ lệ (không may). Để thay thế cho câu trả lời Hooked, thay vì can thiệp vào dữ liệu, bạn có thể đánh lừa các nhãn như vậy:

ticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x*scale)) 
ax.xaxis.set_major_formatter(ticks) 

Một ví dụ hoàn chỉnh cho thấy cả x và y tỉ lệ:

import numpy as np 
import pylab as plt 
import matplotlib.ticker as ticker 

# Generate data 
x = np.linspace(0, 1e-9) 
y = 1e3*np.sin(2*np.pi*x/1e-9) # one period, 1k amplitude 

# setup figures 
fig = plt.figure() 
ax1 = fig.add_subplot(121) 
ax2 = fig.add_subplot(122) 
# plot two identical plots 
ax1.plot(x, y) 
ax2.plot(x, y) 

# Change only ax2 
scale_x = 1e-9 
scale_y = 1e3 
ticks_x = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x/scale_x)) 
ax2.xaxis.set_major_formatter(ticks_x) 

ticks_y = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x/scale_y)) 
ax2.yaxis.set_major_formatter(ticks_y) 

ax1.set_xlabel("meters") 
ax1.set_ylabel('volt') 
ax2.set_xlabel("nanometers") 
ax2.set_ylabel('kilovolt') 

plt.show() 

Và cuối cùng tôi có các khoản tín dụng cho một bức tranh:

Left: ax1 no scaling, right: ax2 y axis scaled to kilo and x axis scaled to nano

Lưu ý rằng, nếu bạn có text.usetex: true như tôi có, bạn có thể muốn kèm theo la bels in $, như sau: '${0:g}$'.

+0

Đây có lẽ là câu trả lời đúng hơn. Cảm ơn bạn @oystein – oche

+0

Đó là hack mà chúng tôi cần –

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