Ubah teks label centang

215

Saya ingin membuat beberapa modifikasi pada beberapa label centang yang dipilih dalam plot.

Misalnya, jika saya lakukan:

label = axes.yaxis.get_major_ticks()[2].label
label.set_fontsize(size)
label.set_rotation('vertical')

ukuran font dan orientasi label centang diubah.

Namun, jika coba:

label.set_text('Foo')

label centang tidak dimodifikasi. Juga jika saya lakukan:

print label.get_text()

tidak ada yang dicetak.

Inilah beberapa keanehan lainnya. Ketika saya mencoba ini:

 from pylab import *
 axes = figure().add_subplot(111)
 t = arange(0.0, 2.0, 0.01)
 s = sin(2*pi*t)
 axes.plot(t, s)
 for ticklabel in axes.get_xticklabels():
     print ticklabel.get_text()

Hanya string kosong yang dicetak, tetapi plot berisi kutu berlabel '0,0', '0,5', '1,0', '1,5', dan '2,0'.

repoman
sumber
Bisakah Anda memberikan plot yang Anda gunakan untuk mendapatkan label?
Claudio
Anda mendapatkan label kosong karena Anda belum menggambar kanvas. Jika Anda menelepon draw()sebelum mencoba mencetak label, Anda akan mendapatkan apa yang Anda harapkan. Mengatur label centang individual sayangnya merupakan sentuhan yang lebih sulit (apa yang terjadi adalah bahwa locator dan formatter tick belum direset dan menimpa hal-hal ketika Anda set_text). Saya akan menambahkan contoh sedikit, jika seseorang tidak mengalahkan saya untuk itu. Saya harus naik bus, saat ini.
Joe Kington
@ JoKington: Luar biasa! Looking forward untuk melihat perbaikan Anda.
repoman
@repoman - Ya, sepertinya saya berbicara terlalu cepat. Apa yang ada dalam pikiran saya berfungsi untuk versi matplotlib yang lebih lama, tetapi bukan versi terbaru. Saya perlu melakukan sedikit lebih banyak penggalian. Yang telah dikatakan, ini seharusnya tidak serumit ...
Joe Kington

Jawaban:

298

Peringatan: Kecuali jika ticklabels sudah diset ke string (seperti biasanya dalam contoh boxplot), ini tidak akan berfungsi dengan versi matplotlib mana pun yang lebih baru daripada 1.1.0. Jika Anda bekerja dari master github saat ini, ini tidak akan berfungsi. Saya belum yakin apa masalahnya ... Mungkin ini adalah perubahan yang tidak disengaja, atau mungkin tidak ...

Biasanya, Anda akan melakukan sesuatu seperti ini:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

# We need to draw the canvas, otherwise the labels won't be positioned and 
# won't have values yet.
fig.canvas.draw()

labels = [item.get_text() for item in ax.get_xticklabels()]
labels[1] = 'Testing'

ax.set_xticklabels(labels)

plt.show()

masukkan deskripsi gambar di sini

Untuk memahami alasan mengapa Anda harus melewati begitu banyak simpai, Anda perlu memahami sedikit lebih banyak tentang bagaimana matplotlib disusun.

Matplotlib sengaja menghindari melakukan posisi kutu "statis", dll, kecuali jika secara eksplisit disuruh. Asumsinya adalah Anda akan ingin berinteraksi dengan plot, dan batas plot, ticks, ticklabels, dll akan berubah secara dinamis.

Karenanya, Anda tidak bisa hanya mengatur teks dari label centang yang diberikan. Secara default, ini diatur ulang oleh Locator dan Formatter sumbu setiap kali plot digambar.

Namun, jika Locators dan Formatters disetel menjadi statis ( FixedLocatordan FixedFormatter, masing-masing), maka label centang tetap sama.

Ini apa set_*ticklabelsatau ax.*axis.set_ticklabelstidak.

Mudah-mudahan itu membuatnya sedikit lebih jelas mengapa mengubah label centang individu agak berbelit-belit.

Seringkali, apa yang sebenarnya ingin Anda lakukan hanyalah menjelaskan posisi tertentu. Jika demikian, lihatlah ke dalam annotate.

Joe Kington
sumber
10
ini tampaknya tidak berfungsi dengan versi saat ini (1.20)!
Andrew Jaffe
1
Jika ticklabels sudah diset ke string seperti pada misalnya boxplot, ini masih berfungsi. Ini mungkin jelas, tetapi karena baris pertama dari jawabannya adalah tidak bekerja pada versi matplotlib yang lebih baru, pengguna mungkin melewatkannya sepenuhnya (awalnya saya lakukan). Mungkin menyebutkan ini secara singkat.
joelostblom
2
saya pikir Anda dapat menyingkatnya ke plt.gca (). set_xticklabels (label)
alexey
bagaimana jika saya ingin fontweight "testing" dibuat boldsementara yang lain menggunakan fontweight "light". Apakah ada cara untuk melakukannya?
steven
1
bagi mereka yang menggunakan ini dalam notebook jupyter dapat mengambil manfaat dari mencatat yang fig.canvas.draw()sangat penting
wander95
95

Anda juga dapat melakukan ini dengan pylab dan xticks

import matplotlib
import matplotlib.pyplot as plt
x = [0,1,2]
y = [90,40,65]
labels = ['high', 'low', 37337]
plt.plot(x,y, 'r')
plt.xticks(x, labels, rotation='vertical')
plt.show()

http://matplotlib.org/examples/ticks_and_spines/ticklabels_demo_rotation.html

rafaelvalle
sumber
Ini adalah solusi sederhana dan berfungsi dengan pyplot 1.5.1. Ini harus dibatalkan.
wordsmith
Meskipun pertanyaannya tidak menanyakan hal ini, saya menghargai bahwa contoh ini memungkinkan Anda mengatur lokasi kutu pada saat yang sama dengan memodifikasi label mereka.
eclark
Dari dokumen matplotlib modern : "pylab sudah usang dan penggunaannya sangat tidak disarankan karena polusi namespace. Gunakan pyplot sebagai gantinya."
Nathaniel Jones
93

Dalam versi yang lebih baru matplotlib, jika Anda tidak mengatur label kutu dengan sekelompok strnilai, mereka secara ''default (dan ketika plot menggambar, label hanyalah nilai kutu). Mengetahui hal itu, untuk mendapatkan hasil yang diinginkan akan membutuhkan sesuatu seperti ini:

>>> from pylab import *
>>> axes = figure().add_subplot(111)
>>> a=axes.get_xticks().tolist()
>>> a[1]='change'
>>> axes.set_xticklabels(a)
[<matplotlib.text.Text object at 0x539aa50>, <matplotlib.text.Text object at 0x53a0c90>, 
<matplotlib.text.Text object at 0x53a73d0>, <matplotlib.text.Text object at 0x53a7a50>, 
<matplotlib.text.Text object at 0x53aa110>, <matplotlib.text.Text object at 0x53aa790>]
>>> plt.show()

dan hasilnya: masukkan deskripsi gambar di sini

dan sekarang jika Anda memeriksa _xticklabels, mereka tidak lagi banyak ''.

>>> [item.get_text() for item in axes.get_xticklabels()]
['0.0', 'change', '1.0', '1.5', '2.0']

Ini berfungsi di versi dari 1.1.1rc1ke versi saat ini 2.0.

CT Zhu
sumber
Terima kasih, ini adalah jawaban yang saya cari. IMO solusi terbersih; cukup berikan set_xticklabelsdaftar campuran string dan objek centang.
Luke Davis
Ketahuilah bahwa jika label centang ditetapkan sebagai int, ini akan mengubahnya menjadi mengambang. Mudah dikerjakan tetapi perlu diperhatikan.
ApproachingDarknessFish
Yang ini berhasil ( ax.get_xticks().tolist()). Solusi yang paling banyak dipilih tidak ( ax.get_xtickslabels()). Entah bagaimana itu tidak dapat mengekstrak label sebelum plt.show()dikeluarkan, meskipun saya menggunakan fig.canvas.draw()seperti yang disarankan.
CypherX
FYI, dari dokumen matplotlib modern : "pylab sudah usang dan penggunaannya sangat tidak disarankan karena polusi namespace. Gunakan pyplot sebagai gantinya."
Nathaniel Jones
17

Sudah lama sejak pertanyaan ini diajukan. Pada hari ini ( matplotlib 2.2.2) dan setelah beberapa pembacaan dan uji coba, saya pikir cara terbaik / tepat adalah sebagai berikut:

Matplotlib memiliki modul bernama tickeryang "berisi kelas untuk dukungan sepenuhnya dikonfigurasi locating kutu dan format" . Untuk memodifikasi tanda centang tertentu dari plot, berikut ini berfungsi untuk saya:

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

def update_ticks(x, pos):
    if x == 0:
        return 'Mean'
    elif pos == 6:
        return 'pos is 6'
    else:
        return x

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
ax.hist(data, bins=25, edgecolor='black')
ax.xaxis.set_major_formatter(mticker.FuncFormatter(update_ticks))
plt.show()

Histogram dengan nilai acak dari distribusi normal

Peringatan! xadalah nilai centang dan posposisi relatifnya dalam urutan dalam sumbu. Perhatikan bahwa posnilai mengambil mulai 1, tidak 0seperti biasa saat pengindeksan.


Dalam kasus saya, saya mencoba memformat y-axishistogram dengan nilai persentase. mtickermemiliki kelas lain bernama PercentFormatteryang dapat melakukan ini dengan mudah tanpa perlu mendefinisikan fungsi terpisah seperti sebelumnya:

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

data = np.random.normal(0, 1, 1000)
fig, ax = plt.subplots()
weights = np.ones_like(data) / len(data)
ax.hist(data, bins=25, weights=weights, edgecolor='black')
ax.yaxis.set_major_formatter(mticker.PercentFormatter(xmax=1.0, decimals=1))
plt.show()

Histogram dengan nilai acak dari distribusi normal

Dalam hal ini xmaxadalah nilai data yang sesuai dengan 100%. Persentase dihitung sebagai x / xmax * 100, itu sebabnya kami perbaiki xmax=1.0. Juga, decimalsadalah jumlah tempat desimal untuk ditempatkan setelah titik.

iipr
sumber
12

Kelas sumbu memiliki fungsi set_yticklabels yang memungkinkan Anda untuk mengatur label centang, seperti:

#ax is the axes instance
group_labels = ['control', 'cold treatment',
             'hot treatment', 'another treatment',
             'the last one']

ax.set_xticklabels(group_labels)

Saya masih memikirkan mengapa contoh Anda di atas tidak berhasil.

stanri
sumber
3
Tetapi saya hanya ingin mengubah satu label. Trik di atas mengharuskan Anda mengekstrak semua label centang dan mengatur label yang diinginkan ke nilai baru. Tetapi bagaimana saya bisa mengekstrak label centang ketika label.get_text () tidak mengembalikan apa pun?
repoman
11

Ini bekerja:

import matplotlib.pyplot as plt

fig, ax1 = plt.subplots(1,1)

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

ax1.set_xticks(x1)
ax1.set_xticklabels(squad, minor=False, rotation=45)

FEDS

Soham
sumber
7

Ini juga berfungsi di matplotlib 3:

x1 = [0,1,2,3]
squad = ['Fultz','Embiid','Dario','Simmons']

plt.xticks(x1, squad, rotation=45)
MichaelSB
sumber
5

Jika Anda tidak bekerja dengan figdan axdan Anda ingin memodifikasi semua label (misalnya untuk normalisasi) Anda dapat melakukan ini:

labels, locations = plt.yticks()
plt.yticks(labels, labels/max(labels))
dopexxx
sumber
1

Coba ini :

  fig,axis = plt.subplots(nrows=1,ncols=1,figsize=(13,6),sharex=True)
  axis.set_xticklabels(['0', 'testing', '10000', '20000', '30000'],fontsize=22)
Aymen Alsaadi
sumber
-4

Anda dapat melakukan:

for k in ax.get_xmajorticklabels():
    if some-condition:
        k.set_color(any_colour_you_like)

draw()
Hachi Manzur
sumber
Adakah yang bisa menjelaskan mengapa jawaban ini sangat tidak disukai?
Hlynur Davíð Hlynsson
@ HlynurDavíðHlynsson Saya pikir itu tidak benar-benar ada hubungannya dengan pertanyaan. Yah, mungkin dengan beberapa pengeditan ... Harap edit, jika Anda menghubungkannya dengan pertanyaan. ;)
loved.by.Yesus