การเปลี่ยน“ ความถี่ติ๊ก” บนแกน x หรือ y ใน matplotlib?


477

ฉันพยายามที่จะแก้ไขวิธีที่หลามวางแผนข้อมูลของฉัน

พูด

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

และ

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

จากนั้นฉันจะทำ:

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

และเครื่องหมายแกนของแกน x ถูกพล็อตเป็นช่วง ๆ 5 มีวิธีที่จะทำให้มันแสดงช่วงเวลา 1 หรือไม่?


6
แม้ว่าเห็บเป็นคำที่เหมาะสมที่นี่การเปลี่ยนเห็บเป็นขนาดขั้นตอนจะแนะนำมือใหม่เพิ่มเติมสำหรับคำถามนี้
การพนัน Sibbs

9
คำถามที่เกี่ยวข้องอย่างใกล้ชิด: stackoverflow.com/questions/6682784/…และทางออกที่ยอดเยี่ยม:pyplot.locator_params(nbins=4)
Dr. Jan-Philip Gehrcke

nbins ดูเหมือนว่าจะเลิกใช้แล้วใน matplotlib2.x น่าเสียดาย
jeremy_rutman

คำตอบ:


583

คุณสามารถตั้งค่าตำแหน่งที่คุณต้องการทำเครื่องหมายอย่างชัดเจนด้วยplt.xticks:

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

ตัวอย่างเช่น,

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ใช้มากกว่าrangeฟังก์ชั่นของ Python ในกรณีmin(x)และmax(x)ลอยแทน ints)


plt.plot(หรือax.plot) ฟังก์ชั่นจะตั้งค่าเริ่มต้นโดยอัตโนมัติxและyข้อ จำกัด หากคุณต้องการที่จะรักษาขีด จำกัด เหล่านั้นและเพียงแค่เปลี่ยน stepize ของเครื่องหมายติ๊กคุณสามารถใช้ax.get_xlim()เพื่อค้นหาข้อ จำกัด Matplotlib ที่ตั้งไว้แล้ว

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

ตัวจัดรูปแบบเห็บเริ่มต้นควรทำหน้าที่ที่เหมาะสมในการปัดเศษค่าเป็นจำนวนหลักที่สมเหตุสมผล อย่างไรก็ตามหากคุณต้องการควบคุมรูปแบบมากขึ้นคุณสามารถกำหนดฟอร์แมตเตอร์ของคุณเอง ตัวอย่างเช่น,

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

นี่คือตัวอย่างของ runnable:

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
ไม่มีวิธีใดที่จะทำให้มันยังคงตัดสินใจว่าเป็นขีด จำกัด ของตัวเอง แต่เพียงแค่เปลี่ยนขนาดขั้นตอนหรือไม่ วิธีนี้ไม่ดีมากถ้าค่าต่ำสุดเป็น 3523.232512!
Korone

3
@Corone เป็นเวลานานแล้วที่คุณถาม แต่ฉันโพสต์คำตอบด้านล่างเพื่อให้ง่ายต่อการควบคุมขนาดขั้นตอนในขณะที่ยังคงใช้การกำหนดขอบเขตอัตโนมัติ
jthomas

3
โปรดทราบว่าจำเป็นต้องมีเครื่องหมาย+1ในplt.xticks(np.arange(min(x), max(x)+1, 1.0))เพื่อแสดงเครื่องหมายติ๊กสุดท้าย
Alex Willison

1
ใช่np.arange(start, stop)สร้างค่าในครึ่งเปิดช่วงเวลา[start, stop)รวมถึงแต่ไม่รวมstart stopดังนั้นฉันใช้max(x)+1เพื่อให้แน่ใจว่าmax(x)รวมอยู่
unutbu

4
มีอะไรที่เทียบเท่ากับ datetime plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1)หรือไม่ ดูเหมือนว่าจะมีการวางแผนเพียงปี
WBM

207

อีกวิธีคือการตั้งตัวระบุตำแหน่งแกน:

import matplotlib.ticker as plticker

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

มีหลายประเภทที่ตั้งขึ้นอยู่กับความต้องการของคุณ

นี่คือตัวอย่างเต็มรูปแบบ:

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
สิ่งนี้ไม่ทำงานตามที่คาดไว้ โดยเฉพาะเมื่อใช้วันที่จะไม่ใช้วันที่ที่เหมาะสม
Chris Fonnesbeck

35
เมื่อใช้วันที่คุณควรใช้วิธีการในโมดูล matplotlib.dates ตัวอย่างเช่นmatplotlib.dates.AutoDateLocator()
robochat

3
มันทำงานได้ตามที่คาดไว้สำหรับฉันพร้อมวันที่ วิธีนี้ง่ายกว่าวิธีที่ยอมรับ
Pablo Suau

สิ่งที่ไม่base=1.0จริงหมายถึง / ทำอย่างไร
javadba

base = 1.0 หมายความว่าจะมี locator สำหรับจำนวนเต็มทั้งหมด เอกสารระบุว่า MultipleLocator "ตั้งค่า [s] ขีดบนแต่ละจำนวนเต็มของฐานภายในช่วงเวลาการดู" ดังนั้นถ้า base = 2 จะมีการทำเครื่องหมายสำหรับตัวเลขคู่และฉันคิดว่าคุณสามารถใส่เหตุการณ์ = 2.5
robochat

124

ฉันชอบวิธีนี้ (จากMatplotlib Plotting 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()

วิธีการแก้ปัญหานี้ช่วยให้คุณสามารถควบคุมระยะห่างของเห็บได้อย่างชัดเจนผ่านทางหมายเลขที่กำหนดticker.MultipleLocater()อนุญาตการกำหนดขีด จำกัด อัตโนมัติและอ่านได้ง่ายในภายหลัง


3
วิธีการทำเช่นนี้โดยไม่คำนวณเห็บอย่างชัดเจน!
Zelphir Kaltstahl

4
นี่คือคำตอบเดียวกับคนนี้ มันไม่สมเหตุสมผลที่จะเพิ่มคำตอบเหมือนกันในอีกสองปีต่อมา
ImportanceOfBeingErnest

6
จับดี. ฉันไม่รู้จักพวกเขาเหมือนกันเมื่อฉันโพสต์คำตอบ ถึงกระนั้นฉันคิดว่างานนำเสนอนี้เป็นเรื่องง่ายที่จะเข้าใจ
jthomas

การอ้างอิงหนังสือในคำตอบนี้ยังให้แหล่งข้อมูลที่เป็นประโยชน์สำหรับข้อมูลเพิ่มเติม
สตีเวนซีโฮเวล

1
นี่เป็นคำตอบเดียวกับ robochat ซึ่งมาเมื่อสามปีก่อน
ลดราคา

90

ในกรณีที่ใครก็ตามที่สนใจซับทั่วไปเพียงแค่ได้รับเห็บปัจจุบันและใช้มันเพื่อตั้งค่าเห็บใหม่โดยการสุ่มเลือกเห็บอื่น ๆ

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

3
นี่เป็นคำตอบทั่วไปสำหรับประเภทเห็บที่แตกต่างกัน (str, float, datetime)
Ryszard Cetnarski

2
ลบเห็บที่ไม่ใช่จำนวนเต็ม: ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
2839288

โซลูชันรายละเอียดมากมายด้านบน แต่ฉันเห็นด้วยว่านี่เป็นคำย่อที่กระชับที่สุด คุณสามารถแยกความยาวของ ax.get_xticks () และตั้งความถี่การแบ่งตามความยาวนี้หารด้วยจำนวนเห็บที่ต้องการ
เลน D

ฉันคิดว่านี่เป็นคำตอบที่ดีที่สุด คำตอบอื่น ๆ ส่วนใหญ่ซับซ้อนเกินไปและยากที่จะนำไปใช้ / พูดคุยทั่วไป ขอบคุณ!
Seankala

2
มันสามารถลดจำนวนไม้ในขณะที่คำถาม (และเป้าหมายของฉันว่าฉันพบมัน) คือการเพิ่มขึ้น
Alexei Martianov

36

นี่มันค่อนข้างแฮ็กแต่ทว่าตัวอย่างที่ชัดเจนที่สุดที่เข้าใจได้ง่ายที่สุดที่ฉันเคยพบมา มันมาจากคำตอบของ SO ที่นี่:

วิธีที่ปลอดภัยที่สุดในการซ่อนป้ายเห็บทุกอันที่แถบสี matplotlib?

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

จากนั้นคุณสามารถวนรอบฉลากเพื่อให้สามารถมองเห็นได้หรือไม่ขึ้นอยู่กับความหนาแน่นที่คุณต้องการ

แก้ไข: โปรดทราบว่าบางครั้ง matplotlib ตั้งป้ายกำกับ == ''ดังนั้นจึงอาจดูเหมือนไม่มีป้ายกำกับอยู่ แต่ในความเป็นจริงแล้วและไม่แสดงอะไรเลย เพื่อให้แน่ใจว่าคุณวนลูปผ่านฉลากที่มองเห็นได้จริงคุณสามารถลอง:

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
นี่คือทางออกที่ง่ายที่สุดและทั่วไป การปรับเล็กน้อย: โดยปกติแล้วax.get_xticklabels()[1::2]ฉลากจะถูกซ่อนไว้
jolvi

สิ่งนี้ใช้ไม่ได้กับ matplotlib.finance.candlestick2
BCR

@BCR อาจเป็นไปได้ว่าบางส่วนของ xticklabels ถูกตั้งค่าไว้เพื่อ''ให้เมื่อคุณวนรอบพวกเขาคุณกำลังทำ xticklabels ที่มองไม่เห็นว่างเปล่า (ซึ่งจะไม่มีผลต่อการสร้างภาพ แต่อาจหมายความว่าคุณไม่ได้ดึง ฉลากที่ถูกต้อง) คุณสามารถลอง: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
choldgraf

15

นี่เป็นหัวข้อเก่า แต่ฉันสะดุดในทุก ๆ คราวและทำฟังก์ชั่นนี้ มันสะดวกมาก:

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)

ข้อแม้หนึ่งในการควบคุมเห็บเช่นนี้ก็คือว่าไม่สนุกกับการปรับปรุงอัตโนมัติสูงสุดของสเกลสูงสุดหลังจากบรรทัดเพิ่ม จากนั้นทำ

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

และเรียกใช้ฟังก์ชั่นการปรับใหม่อีกครั้ง


11

ฉันพัฒนาวิธีแก้ปัญหาที่ไม่เหมาะสม พิจารณาว่าเรามีแกน X และรายการฉลากสำหรับแต่ละจุดใน X

ตัวอย่าง:
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']
สมมติว่าฉันต้องการแสดงป้ายเห็บเฉพาะสำหรับ 'feb' และ 'jun'
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
ดีตอนนี้เรามีรายการป้ายกำกับปลอม อันดับแรกเราวางแผนเวอร์ชันดั้งเดิม
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
ตอนนี้รุ่นที่แก้ไขแล้ว
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()

6

หากคุณเพียงแค่ต้องการตั้งค่าระยะห่างหนึ่งซับง่าย ๆ กับ boilerplate น้อยที่สุด

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

ยังใช้งานได้ง่ายสำหรับเห็บย่อย:

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

บิตของปากเต็มไปด้วยขนาดกะทัดรัด แต่สวย


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

plt.xticks(xmarks)

สิ่งนี้ใช้ได้สำหรับฉัน

หากคุณต้องการเห็บระหว่าง [1,5] (รวม 1 และ 5) จากนั้นแทนที่

length = 5

1
fyi, คุณสามารถเขียนxmarks = range(1, length+1, 1)ได้ ค่อนข้างแน่ใจว่าความเข้าใจในรายการนั้นซ้ำซ้อน
Neal

2

การใช้งาน Python อย่างแท้จริง

ด้านล่างเป็นการใช้งานไพ ธ อนอย่างแท้จริงของฟังก์ชันที่ต้องการซึ่งจัดการกับชุดตัวเลขใด ๆ (int หรือ float) ด้วยค่าบวกลบหรือผสมและอนุญาตให้ผู้ใช้ระบุขนาดขั้นตอนที่ต้องการ:

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)

ตัวอย่างผลลัพธ์

# 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]

ตัวอย่างการใช้งาน

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()

แปลงตัวอย่างการใช้งาน

ขอให้สังเกตว่าแกน x มีค่าจำนวนเต็มเว้นระยะเท่ากันทั้งหมด 5 โดยแกน y มีช่วงเวลาที่แตกต่างกัน ( matplotlibพฤติกรรมเริ่มต้นเนื่องจากเห็บไม่ได้ระบุไว้)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.