2012-01-16 26 views
13

Tôi muốn tạo một ô phân tán trục vuông với matplotlib. Thông thường sử dụng set_scale("log") hoạt động tốt, nhưng nó giới hạn tôi để log10. Tôi muốn làm cho cốt truyện trong log2. Tôi đã thấy giải pháp ở đây: How to produce an exponentially scaled axis?làm ô vuông trục với thang log2 trong matplotlib

nhưng nó khá phức tạp và không hoạt động nếu bạn có 0 giá trị trong mảng, mà tôi làm. Tôi chỉ đơn giản là bỏ qua những người như các chức năng khác.

Ví dụ:

log2scatter(data1, data2) 

nơi data1 và data2 chứa 0s nên có một quy mô lôgarít trên trục x và y, với khoảng cách đều nhau ve logarit. Giống như log10, ngoại trừ log2 ...

Cảm ơn.

+0

Logs được chỉ định cho các đối số tích cực. Điều này giữ không phụ thuộc vào cơ sở, nghĩa là nó giữ cho các log tự nhiên, log base 10, log base 2 vv Do đó bạn không thể vẽ một cái gì đó có số không trong một logscale, trừ khi bạn làm điều gì đó với các giá trị zero này. –

+0

Sử dụng câu trả lời từ câu hỏi đó nhưng lọc ra các giá trị y bằng 0 và các giá trị x tương ứng của chúng trước tiên (đó là cách chúng ta bỏ qua chúng). –

+0

Một cách thanh lịch để làm điều đó trong numpy là gì? Bộ lọc làm phức tạp mã kể từ bây giờ tôi phải có một bản sao của mảng chưa lọc, và một bản sao được lọc ... – user248237dfsf

Trả lời

28

Chỉ cần chỉ định basex=2 hoặc basey=2.

import matplotlib.pyplot as plt 

fig, ax = plt.subplots() 
ax.set_xscale('log', basex=2) 
ax.set_yscale('log', basey=2) 

ax.plot(range(1024)) 
plt.show() 

enter image description here

Đối với hành vi zero-crossing, những gì bạn đang đề cập đến là một "Symmetric Log" cốt truyện (còn gọi là "symlog"). Đối với bất cứ điều gì nó có giá trị, dữ liệu không được lọc ra, nó chỉ là một âm mưu tuyến tính gần 0 và một lô đăng nhập ở khắp mọi nơi khác. Đó là quy mô thay đổi, không phải dữ liệu.

Thông thường bạn chỉ cần thực hiện ax.set_xscale('symlog', basex=2) nhưng sử dụng cơ sở không phải 10 dường như lỗi tại thời điểm này cho các ô giao diện.

Chỉnh sửa: Heh! Lỗi này có vẻ là do lỗi cổ điển: sử dụng đối số mặc định có thể thay đổi.
Tôi đã gửi báo cáo lỗi, nhưng nếu bạn muốn sửa lỗi, bạn cần chỉnh sửa nhỏ thành lib/matplotlib/ticker.py, quanh dòng 1376, theo phương thức __init__ của SymmetricalLogLocator.

Thay vì

def __init__(self, transform, subs=[1.0]): 
    self._transform = transform 
    self._subs = subs 
    ... 

Thay đổi nó một cái gì đó tương tự như:

def __init__(self, transform, subs=None): 
    self._transform = transform 
    if subs is None: 
     self._subs = [1.0] 
    else: 
     self._subs = subs 
    .... 

Với sự thay đổi được thực hiện, nó cư xử như mong đợi ...

import matplotlib.pyplot as plt 
import numpy as np 

fig, ax = plt.subplots() 
ax.set_xscale('symlog', basex=2) 
ax.set_yscale('symlog', basey=2) 

x = np.arange(-1024, 1024) 
ax.plot(x, x) 

plt.show() 

enter image description here

+0

Tôi nhận được các giới hạn x và y mặc định thực sự kỳ lạ khi sử dụng base = 2 (và thậm chí không có nó). Nó không đặt nó là các giá trị nhỏ nhất trong cả hai chiều. Nó chọn giới hạn thực sự kỳ lạ che giấu hầu hết dữ liệu. Làm thế nào điều này có thể được cố định ngoài việc đặt giới hạn x/y theo cách thủ công? – user248237dfsf

+0

Không cần phải ghi đè/hack một lớp trong matplotlib để tạo ra một âm mưu phân tán freakin trong log2 so với log2 ... nó rất buồn và bực bội. : ( – user248237dfsf

+0

Phần symlog là một lỗi. Các giới hạn mà bạn đang đề cập đến chỉ là cách giới hạn hành vi cho một ô lôgíc. Chúng "snap" vào quyền lực gần nhất của cơ sở. Nếu bạn muốn giới hạn kết thúc nghiêm ngặt tại min và max của dữ liệu, sau đó chỉ định 'ax.axis ('tight')'. –

2

Nếu bạn đang sử dụng plt.xscale, bạn vẫn cần phải xác định basex, không base:

plt.figure() 
plt.plot(x, y) 
plt.xscale('log', basex=2) 
plt.show() 
Các vấn đề liên quan