Thay đổi tần số đánh dấu vào các điểm khác trên trục x hoặc y trong matplotlib?


477

Tôi đang cố gắng khắc phục cách python vẽ dữ liệu của tôi.

Nói

x = [0,5,9,10,15]

y = [0,1,2,3,4]

Sau đó tôi sẽ làm:

matplotlib.pyplot.plot(x,y)
matplotlib.pyplot.show()

và các dấu tick của trục x được vẽ trong các khoảng 5. Có cách nào để làm cho nó hiển thị các khoảng 1 không?


6
Mặc dù tick là từ thích hợp ở đây, thay đổi tick theo kích thước bước chắc chắn sẽ hướng dẫn nhiều người mới hơn cho câu hỏi này.
Đánh bạc Sibbs 18/11/13

9
Câu hỏi liên quan chặt chẽ: stackoverflow.com/questions/6682784/ và một giải pháp tuyệt vời:pyplot.locator_params(nbins=4)
Tiến sĩ Jan-Philip Gehrcke

nbins dường như không được dùng nữa trong matplotlib2.x, thật không may
jeremy_rutman

Câu trả lời:


583

Bạn có thể đặt rõ ràng nơi bạn muốn đánh dấu bằng plt.xticks:

plt.xticks(np.arange(min(x), max(x)+1, 1.0))

Ví dụ,

import numpy as np
import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.show()

( np.arangeđã được sử dụng thay vì rangechức năng của Python chỉ trong trường hợp min(x)max(x)là float thay vì ints.)


Hàm plt.plot(hoặc ax.plot) sẽ tự động đặt mặc định xygiới hạn. Nếu bạn muốn giữ các giới hạn đó và chỉ cần thay đổi các bước của dấu tick, thì bạn có thể sử dụng ax.get_xlim()để khám phá giới hạn mà Matplotlib đã đặt ra.

start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, stepsize))

Trình định dạng đánh dấu mặc định sẽ thực hiện một công việc tốt làm tròn các giá trị đánh dấu thành một số có thể có các chữ số có nghĩa. Tuy nhiên, nếu bạn muốn có nhiều quyền kiểm soát định dạng hơn, bạn có thể xác định trình định dạng của riêng mình. Ví dụ,

ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))

Đây là một ví dụ có thể chạy được:

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

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, 0.712123))
ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
plt.show()

72
Không có cách nào để khiến nó vẫn quyết định giới hạn của riêng nó, mà chỉ thay đổi kích thước bước? Phương pháp này không tốt lắm nếu min giống như 3523,232512!
Korone

3
@Corone, đã được một thời gian kể từ khi bạn hỏi, nhưng tôi đã đăng một câu trả lời dưới đây cho phép dễ dàng kiểm soát kích thước bước trong khi vẫn sử dụng xác định giới hạn tự động.
jthomas

3
Lưu ý rằng +1in plt.xticks(np.arange(min(x), max(x)+1, 1.0))là bắt buộc để hiển thị dấu tick cuối cùng.
Alex Willison

1
Có, np.arange(start, stop)tạo các giá trị trong khoảng thời gian nửa mở[start, stop) , bao gồm startnhưng loại trừ stop. Vì vậy, tôi sử dụng max(x)+1để đảm bảo max(x)được bao gồm.
unutbu

4
Có tương đương với datetime plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1)không? có vẻ như chỉ âm mưu trong năm
WBM

207

Một cách tiếp cận khác là đặt bộ định vị trục:

import matplotlib.ticker as plticker

loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)

Có một số loại định vị khác nhau tùy thuộc vào nhu cầu của bạn.

Dưới đây là một ví dụ đầy đủ:

import matplotlib.pyplot as plt
import matplotlib.ticker as plticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)
plt.show()

7
Điều này không hoạt động như mong đợi. Cụ thể, khi sử dụng ngày, nó không sử dụng ngày thích hợp.
Chris Fonnesbeck

35
Khi sử dụng ngày, bạn nên sử dụng các phương thức trong mô-đun matplotlib.dates. Ví dụmatplotlib.dates.AutoDateLocator()
robochat

3
Nó làm việc như mong đợi đối với tôi, với ngày tháng. Giải pháp này dễ dàng hơn nhiều so với giải pháp được chấp nhận.
Pablo Suau

Không gì base=1.0thực sự có ý nghĩa / làm gì?
javadba

cơ sở = 1.0 có nghĩa là sẽ có một bộ định vị cho mọi số. Tài liệu nói rằng ManyLocator "Đặt [s] một đánh dấu vào từng bội số nguyên của một cơ sở trong khoảng thời gian xem." Vì vậy, nếu cơ sở = 2 thì sẽ có một đánh dấu cho các số chẵn và tôi nghĩ rằng bạn có thể đặt sự kiện đặt cơ sở = 2,5.
robochat

124

Tôi thích giải pháp này (từ Matplotlib Plote Cookbook ):

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]

tick_spacing = 1

fig, ax = plt.subplots(1,1)
ax.plot(x,y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()

Giải pháp này cung cấp cho bạn quyền kiểm soát rõ ràng khoảng cách đánh dấu thông qua số được cung cấp cho ticker.MultipleLocater() , cho phép xác định giới hạn tự động và dễ đọc sau này.


3
Một cách để làm điều này mà không tính toán các dấu tick một cách rõ ràng!
Zelphir Kaltstahl

4
Đây là câu trả lời tương tự như câu hỏi này . Không có nghĩa gì để thêm một câu trả lời giống hệt hai năm sau đó.
ImportanceOfByingErnest

6
Nắm bắt tốt. Tôi đã không nhận ra chúng giống nhau khi tôi đăng câu trả lời. Tuy nhiên, tôi nghĩ rằng bài thuyết trình này là một chút dễ hiểu hơn.
jthomas

Tài liệu tham khảo trong câu trả lời này cũng cung cấp một nguồn hữu ích để biết thêm thông tin.
Steven C. Howell

1
Đây là câu trả lời tương tự như của robochat, xuất hiện ba năm trước đó.
MERose

90

Trong trường hợp bất cứ ai quan tâm đến một lớp lót chung, chỉ cần lấy các dấu hiện tại và sử dụng nó để đặt các dấu tick mới bằng cách lấy mẫu mọi dấu tick khác.

ax.set_xticks(ax.get_xticks()[::2])

3
Đây là câu trả lời chung chung duy nhất cho các loại đánh dấu khác nhau (str, float, datetime)
Ryszard Cetnarski

2
Xóa các dấu tick không nguyên: ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
user2839288

Rất nhiều giải pháp chi tiết ở trên nhưng tôi đồng ý đây là cách ngắn gọn nhất. Bạn thậm chí có thể trích xuất độ dài của ax.get_xticks () và đặt tần số cắt theo độ dài này chia cho số lượng dấu yêu cầu.
Iain D

Tôi nghĩ rằng đây là câu trả lời tốt nhất. Hầu hết các câu trả lời khác là quá phức tạp và khó áp dụng / khái quát hóa. Cảm ơn bạn!
Seankala

2
Nó chỉ có thể giảm số lượng gậy, trong khi trong câu hỏi (và mục tiêu của tôi làm thế nào tôi tìm thấy nó) là tăng nó.
Alexei Martianov

36

Đây là một chút hack, nhưng cho đến nay là ví dụ rõ ràng / dễ hiểu nhất mà tôi đã tìm thấy để làm điều này. Đó là từ một câu trả lời trên SO ở đây:

Cách sạch nhất để ẩn mọi nhãn tick thứ n trong thanh màu matplotlib?

for label in ax.get_xticklabels()[::2]:
    label.set_visible(False)

Sau đó, bạn có thể lặp qua các nhãn để đặt chúng hiển thị hay không tùy thuộc vào mật độ bạn muốn.

chỉnh sửa: lưu ý rằng đôi khi matplotlib đặt nhãn == '', vì vậy nó có thể trông giống như một nhãn không có mặt, trong khi thực tế nó là và không hiển thị bất cứ thứ gì. Để đảm bảo bạn đang lặp qua các nhãn hiển thị thực tế, bạn có thể thử:

visible_labels = [lab for lab in ax.get_xticklabels() if lab.get_visible() is True and lab.get_text() != '']
plt.setp(visible_labels[::2], visible=False)

3
Đây là giải pháp đơn giản và chung chung nhất. Một điều chỉnh nhỏ: thường ax.get_xticklabels()[1::2]là các nhãn được ẩn.
jolvi

Điều này không hoạt động với matplotlib.finance.candlestick2
BCR

@BCR có thể là một số xticklabels chỉ được đặt thành để ''khi bạn lặp qua chúng, bạn đang tạo xticklabels trống rỗng (sẽ không ảnh hưởng đến trực quan hóa, nhưng có thể có nghĩa là bạn không kéo các nhãn chính xác). Bạn có thể thử: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
choldgraf

15

Đây là một chủ đề cũ, nhưng tôi vấp phải điều này mọi lúc và thực hiện chức năng này. Nó rất tiện lợi:

import matplotlib.pyplot as pp
import numpy as np

def resadjust(ax, xres=None, yres=None):
    """
    Send in an axis and I fix the resolution as desired.
    """

    if xres:
        start, stop = ax.get_xlim()
        ticks = np.arange(start, stop + xres, xres)
        ax.set_xticks(ticks)
    if yres:
        start, stop = ax.get_ylim()
        ticks = np.arange(start, stop + yres, yres)
        ax.set_yticks(ticks)

Một lưu ý của việc kiểm soát các bọ ve như thế này là người ta không còn thích cập nhật tự động tương tác ở quy mô tối đa sau một dòng được thêm vào. Sau đó làm

gca().set_ylim(top=new_top) # for example

và chạy chức năng resadjust một lần nữa.


11

Tôi đã phát triển một giải pháp không phù hợp. Hãy xem xét rằng chúng ta có trục X và cũng là danh sách các nhãn cho từng điểm trong X.

Thí dụ:
import matplotlib.pyplot as plt

x = [0,1,2,3,4,5]
y = [10,20,15,18,7,19]
xlabels = ['jan','feb','mar','apr','may','jun']
Hãy nói rằng tôi muốn hiển thị nhãn tick chỉ cho 'feb' và 'jun'
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Tốt, bây giờ chúng tôi có một danh sách giả của nhãn. Đầu tiên, chúng tôi âm mưu phiên bản gốc.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Bây giờ, phiên bản sửa đổi.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()

6

nếu bạn chỉ muốn đặt khoảng cách một lớp lót đơn giản với bản tóm tắt tối thiểu:

plt.gca().xaxis.set_major_locator(plt.MultipleLocator(1))

cũng hoạt động dễ dàng đối với bọ ve nhỏ:

plt.gca().xaxis.set_minor_locator(plt.MultipleLocator(1))

một chút vui miệng, nhưng nhỏ gọn


2
xmarks=[i for i in range(1,length+1,1)]

plt.xticks(xmarks)

Điều này làm việc cho tôi

nếu bạn muốn đánh dấu giữa [1,5] (bao gồm 1 và 5) thì thay thế

length = 5

1
fyi, bạn có thể chỉ cần viết xmarks = range(1, length+1, 1). khá chắc chắn việc hiểu danh sách là dư thừa.
Neal

2

Thực hiện Python thuần túy

Dưới đây là triển khai python thuần túy của chức năng mong muốn xử lý bất kỳ chuỗi số nào (int hoặc float) với các giá trị dương, âm hoặc hỗn hợp và cho phép người dùng chỉ định kích thước bước mong muốn:

import math

def computeTicks (x, step = 5):
    """
    Computes domain with given step encompassing series x
    @ params
    x    - Required - A list-like object of integers or floats
    step - Optional - Tick frequency
    """
    xMax, xMin = math.ceil(max(x)), math.floor(min(x))
    dMax, dMin = xMax + abs((xMax % step) - step) + (step if (xMax % step != 0) else 0), xMin - abs((xMin % step))
    return range(dMin, dMax, step)

Đầu ra mẫu

# Negative to Positive
series = [-2, 18, 24, 29, 43]
print(list(computeTicks(series)))

[-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

# Negative to 0
series = [-30, -14, -10, -9, -3, 0]
print(list(computeTicks(series)))

[-30, -25, -20, -15, -10, -5, 0]

# 0 to Positive
series = [19, 23, 24, 27]
print(list(computeTicks(series)))

[15, 20, 25, 30]

# Floats
series = [1.8, 12.0, 21.2]
print(list(computeTicks(series)))

[0, 5, 10, 15, 20, 25]

# Step – 100
series = [118.3, 293.2, 768.1]
print(list(computeTicks(series, step = 100)))

[100, 200, 300, 400, 500, 600, 700, 800]

Sử dụng mẫu

import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(computeTicks(x))
plt.show()

Lô sử dụng mẫu

Lưu ý trục x có các giá trị nguyên cách đều nhau 5, trong khi trục y có một khoảng khác nhau ( matplotlibhành vi mặc định, vì các dấu tick không được chỉ định).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.