Mengubah "frekuensi centang" pada sumbu x atau y di matplotlib?

477

Saya mencoba memperbaiki bagaimana python memplot data saya.

Mengatakan

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

dan

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

Maka saya akan melakukan:

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

dan tanda centang sumbu x diplot dalam interval 5. Apakah ada cara untuk membuatnya menunjukkan interval 1?

Dax Feliz
sumber
6
Meskipun kutu adalah kata yang tepat di sini, mengubah kutu ke ukuran langkah pasti akan memandu lebih banyak pemula untuk pertanyaan ini.
Sibbs Gambling
9
Pertanyaan yang terkait erat: stackoverflow.com/questions/6682784/… dan solusi yang bagus:pyplot.locator_params(nbins=4)
Dr. Jan-Philip Gehrcke
nbins tampaknya telah usang di matplotlib2.x, sayangnya
jeremy_rutman

Jawaban:

584

Anda dapat secara eksplisit mengatur di mana Anda ingin menandai tanda dengan plt.xticks:

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

Sebagai contoh,

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.arangeDigunakan daripada rangefungsi Python untuk berjaga-jaga min(x)dan max(x)mengapung bukan ints.)


Fungsi plt.plot(atau ax.plot) akan secara otomatis menetapkan standar xdan ybatas. Jika Anda ingin mempertahankan batas-batas itu, dan hanya mengubah ukuran langkah dari tanda centang, maka Anda dapat menggunakan ax.get_xlim()untuk menemukan batas apa yang telah ditetapkan oleh Matplotlib.

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

Formatter tick default harus melakukan pekerjaan yang layak membulatkan nilai tick ke sejumlah digit signifikan yang masuk akal. Namun, jika Anda ingin memiliki kontrol lebih besar atas format, Anda dapat menentukan formatter Anda sendiri. Sebagai contoh,

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

Berikut ini adalah contoh 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()
unutbu
sumber
72
Apakah tidak ada cara untuk mendapatkannya untuk tetap memutuskan batasnya sendiri, tetapi hanya mengubah ukuran langkah? Metode ini tidak terlalu baik jika min adalah sesuatu seperti 3523,232512!
Korone
3
@Corone, Sudah lama sejak Anda bertanya, tapi saya telah memposting jawaban di bawah ini yang memungkinkan kontrol mudah ukuran langkah saat masih menggunakan penentuan batas otomatis.
jthomas
3
Perhatikan bahwa +1in plt.xticks(np.arange(min(x), max(x)+1, 1.0))diperlukan untuk menunjukkan tanda centang terakhir.
Alex Willison
1
Ya, np.arange(start, stop)menghasilkan nilai dalam interval setengah terbuka[start, stop) , termasuk starttetapi tidak termasuk stop. Jadi saya biasa max(x)+1memastikan max(x)sudah termasuk.
unutbu
4
apakah ada yang setara untuk datetime misalnya plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1)? tampaknya hanya merencanakan tahun
WBM
207

Pendekatan lain adalah mengatur locator sumbu:

import matplotlib.ticker as plticker

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

Ada beberapa jenis locator tergantung pada kebutuhan Anda.

Ini adalah contoh lengkapnya:

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()
robochat
sumber
7
Ini tidak berfungsi seperti yang diharapkan. Khususnya, ketika menggunakan tanggal, itu tidak menggunakan tanggal yang sesuai.
Chris Fonnesbeck
35
Saat menggunakan tanggal, Anda harus menggunakan metode dalam modul matplotlib.dates. Misalnyamatplotlib.dates.AutoDateLocator()
robochat
3
Itu bekerja seperti yang diharapkan untuk saya, dengan tanggal. Solusi ini jauh lebih mudah daripada yang diterima.
Pablo Suau
Apa yang base=1.0sebenarnya berarti / lakukan?
javadba
base = 1.0 berarti akan ada locator untuk setiap bilangan bulat. Dokumentasi mengatakan bahwa MultipleLocator "Menetapkan tanda pada setiap bilangan bulat dari basis dalam interval tampilan.". Jadi jika basis = 2 maka akan ada tanda centang untuk angka genap dan saya pikir Anda bisa menggunakan basis = 2.5.
robochat
124

Saya suka solusi ini (dari Cookbook Matplotlib Plotting ):

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

Solusi ini memberi Anda kontrol eksplisit terhadap jarak kutu melalui angka yang diberikan ticker.MultipleLocater(), memungkinkan penentuan batas otomatis, dan mudah dibaca nanti.

jthomas
sumber
3
Cara untuk melakukan ini tanpa menghitung kutu secara eksplisit!
Zelphir Kaltstahl
4
Ini jawaban yang sama dengan yang ini . Tidak masuk akal untuk menambahkan jawaban yang identik dua tahun kemudian.
ImportanceOfBeingErnest
6
Tangkapan yang bagus. Saya tidak mengenali mereka sebagai sama ketika saya memposting jawabannya. Tetap saja, saya pikir presentasi ini sedikit lebih mudah dimengerti.
jthomas
Referensi buku dalam jawaban ini juga menyediakan sumber yang bermanfaat untuk informasi lebih lanjut.
Steven C. Howell
1
Ini adalah jawaban yang sama dengan robochat, yang datang tiga tahun sebelumnya.
MERose
90

Jika ada orang yang tertarik pada satu-liner umum, cukup dapatkan kutu saat ini dan gunakan untuk mengatur kutu baru dengan mengambil sampel setiap kutu lainnya.

ax.set_xticks(ax.get_xticks()[::2])
Lereng
sumber
3
Ini adalah satu-satunya jawaban yang dapat digeneralisasikan untuk berbagai jenis centang (str, float, datetime)
Ryszard Cetnarski
2
Hapus ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
centang
Banyak solusi terperinci di atas tapi saya setuju ini yang paling ringkas. Anda bahkan dapat mengekstrak panjang ax.get_xticks () dan mengatur frekuensi slicing dengan panjang ini dibagi dengan jumlah kutu yang diperlukan.
Iain D
Saya pikir ini adalah jawaban terbaik. Sebagian besar jawaban lain terlalu rumit dan sulit untuk diterapkan / digeneralisasi. Terima kasih!
Seankala
2
Itu hanya dapat mengurangi jumlah batang, sedangkan dalam pertanyaan (dan tujuan saya bagaimana saya menemukannya) adalah untuk meningkatkannya.
Alexei Martianov
36

Ini agak hacky, tetapi sejauh ini terbersih / termudah untuk memahami contoh yang saya temukan untuk melakukan ini. Ini dari jawaban pada SO di sini:

Cara terbersih untuk menyembunyikan setiap label centang ke-n di matplotlib colorbar?

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

Kemudian Anda dapat mengulang label pengaturan ke terlihat atau tidak tergantung pada kepadatan yang Anda inginkan.

sunting: perhatikan bahwa kadang-kadang matplotlib menetapkan label == '', sehingga mungkin terlihat seperti label tidak ada, padahal sebenarnya itu dan tidak menampilkan apa-apa. Untuk memastikan Anda mengulang-ulang label yang terlihat, Anda dapat mencoba:

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)
choldgraf
sumber
3
Ini adalah solusi paling sederhana dan generik. Penyesuaian kecil: biasanya ax.get_xticklabels()[1::2]label disembunyikan.
jolvi
Ini tidak berfungsi dengan matplotlib.finance.candlestick2
BCR
@BCR bisa jadi beberapa xticklabels baru saja disetel ''sehingga ketika Anda mengulanginya, Anda membuat xticklabels yang kosong tidak terlihat (yang tidak akan berpengaruh pada visualisasi, tetapi mungkin berarti Anda tidak menarik label yang benar). Anda dapat mencoba: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
choldgraf
15

Ini adalah topik lama, tapi saya sering tersandung dan membuat fungsi ini. Sangat nyaman:

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)

Satu peringatan untuk mengendalikan kutu seperti ini adalah bahwa seseorang tidak lagi menikmati pemutakhiran automagic interaktif skala max setelah penambahan baris. Lalu lakukan

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

dan jalankan kembali fungsi resadjust.

Tompa
sumber
11

Saya mengembangkan solusi yang tidak bagus. Pertimbangkan bahwa kita memiliki sumbu X dan juga daftar label untuk setiap titik di X.

Contoh:
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']
Katakanlah saya ingin menunjukkan label kutu hanya untuk 'feb' dan 'jun'
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Bagus, sekarang kami memiliki daftar label palsu. Pertama, kami merencanakan versi aslinya.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Sekarang, versi yang dimodifikasi.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()
Deninhos
sumber
6

jika Anda hanya ingin mengatur spasi satu liner sederhana dengan boilerplate minimal:

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

juga bekerja dengan mudah untuk kutu minor:

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

sedikit suap, tapi cukup kompak

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

plt.xticks(xmarks)

Ini berhasil untuk saya

jika Anda ingin kutu di antara [1,5] (1 dan 5 inklusif) maka gantilah

length = 5
Piyush Gupta
sumber
1
fyi, Anda bisa menulis xmarks = range(1, length+1, 1). cukup yakin pemahaman daftar itu berlebihan.
Neal
2

Implementasi Python Murni

Di bawah ini adalah implementasi python murni dari fungsionalitas yang diinginkan yang menangani setiap seri numerik (int atau float) dengan nilai-nilai positif, negatif, atau campuran dan memungkinkan pengguna untuk menentukan ukuran langkah yang diinginkan:

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)

Output Sampel

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

Contoh Penggunaan

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

Plot penggunaan sampel

Perhatikan bahwa sumbu x memiliki nilai integer yang semuanya berjarak sama rata dengan 5, sedangkan sumbu y memiliki interval yang berbeda ( matplotlibperilaku default, karena kutu tidak ditentukan).

Tongkat hijau
sumber