Jak usunąć ramkę z matplotlib (pyplot.figure vs matplotlib.figure) (frameon = False Problematic in matplotlib)


160

Aby usunąć ramkę na rysunku, piszę

frameon=False

działa idealnie z pyplot.figure , ale matplotlib.Figureusuwa tylko szare tło, ramka pozostaje. Poza tym chcę, aby tylko linie były widoczne, a cała reszta rysunku była przezroczysta.

z pyplot mogę robić, co chcę, chcę to zrobić z matplotlib z jakiegoś długiego powodu, wolę nie wspominać o rozszerzaniu mojego pytania.


Czy możesz wyjaśnić, co robisz? (tj. pokaż przykład) Czy używasz savefig? (Jeśli tak, zastępuje to, co ustawiłeś podczas zapisywania rysunku.) Czy ręczne ustawienie fig.patch.set_visible(False)działa?
Joe Kington,

Używam canvas.print_png (odpowiedź), a nie savefig.
Emmet B

Odpowiedzi:


178

Po pierwsze, jeśli używasz savefig, pamiętaj, że podczas zapisywania nadpisuje kolor tła figury, chyba że określisz inaczej (np fig.savefig('blah.png', transparent=True).).

Jednak aby usunąć tło osi i figury na ekranie, musisz ustawić oba te ustawienia ax.patchi fig.patchbyć niewidocznym.

Na przykład

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))

for item in [fig, ax]:
    item.patch.set_visible(False)

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

wprowadź opis obrazu tutaj

(Oczywiście nie widać różnicy na białym tle SO, ale wszystko jest przezroczyste ...)

Jeśli nie chcesz pokazywać niczego poza linią, wyłącz również oś za pomocą ax.axis('off'):

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.plot(range(10))

fig.patch.set_visible(False)
ax.axis('off')

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

wprowadź opis obrazu tutaj

W takim przypadku możesz jednak chcieć, aby osie zajmowały całą figurę. Jeśli ręcznie określisz położenie osi, możesz powiedzieć mu, aby zajął całą figurę (naprzemiennie możesz użyć subplots_adjust, ale jest to prostsze w przypadku pojedynczych osi).

import matplotlib.pyplot as plt

fig = plt.figure(frameon=False)
ax = fig.add_axes([0, 0, 1, 1])
ax.axis('off')

ax.plot(range(10))

with open('test.png', 'w') as outfile:
    fig.canvas.print_png(outfile)

wprowadź opis obrazu tutaj


więc to rozwiązuje połowę problemu. Ale chcę też, żeby ten prostokąt z czarną ramką był niewidoczny. Dlatego widoczna powinna być tylko niebieska linia.
Emmet B

5
No cóż, w takim razie jest to jeszcze prostsze. Po prostu użyj ax.axis('off')(nadal będziesz musiał wyłączyć ramkę figury).
Joe Kington,

dzięki, czy istnieje sposób na zachowanie etykiet z etykietkami, takich jak: Chcę tylko etykietyax.set_yticklabels(('G1', 'G2', 'G3'))
Emmet B

To jest świetne, użyłem go do innej aplikacji tutaj: stackoverflow.com/questions/4092927/ ...
cxrodgers

1
print_png()Rzuca TypeError: write() argument must be str, not byteswyjątek dla mnie na pytona 3. Otwarcie plik jako zapis binarny ( 'wb') jest potrzebne do jego pracy.
Gabriel Jablonski

243

ax.axis('off'), jak wskazał Joe Kington, usunie wszystko z wyjątkiem wykreślonej linii.

Dla tych, którzy chcą tylko usunąć ramkę (obramowanie) i zachować etykiety, paski itp., Można to zrobić, uzyskując dostęp do spinesobiektu na osi. Biorąc pod uwagę obiekt osi ax, poniższe czynności powinny usunąć obramowanie ze wszystkich czterech stron:

ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['left'].set_visible(False)

A w przypadku usunięcia xi ykleszczy z działki:

 ax.get_xaxis().set_ticks([])
 ax.get_yaxis().set_ticks([])

1
Podoba mi się to, że pozbywam się górnego i prawego kolca
Adrian Torrie

5
Wystarczy dodać: Jeśli chcesz również usunąć kleszcze: ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom')
JLT

4
Ponadto użyj ax = gca (), aby utworzyć obiekt osi, jeśli jeszcze go nie masz.
cameronroytaylor

2
To powinna być akceptowana odpowiedź. "ax.axis (" off ")" usuwa wszystko, jak: etykiety x i y, znaczniki x i y oraz wszystkie (4) obramowania z wykresu. W celu lepszego dostosowania każdy element powinien być traktowany inaczej.
Sanchit

66

Najłatwiejszy sposób na pozbycie się brzydkiej ramki w nowszych wersjach matplotlib:

import matplotlib.pyplot as plt
plt.box(False)

Jeśli naprawdę musi zawsze używać podejścia obiektowego, to zrobić: ax.set_frame_on(False).


2
Dziękuję Ci! To chyba najczystsze rozwiązanie!
Kattia

2
Korzystając z podejścia obiektowego, odniosłem sukces ax.set_frame_on(False), który robi to samo. Może uwzględnij w powyższej odpowiedzi.
Floyd4K

58

Opierając się na doskonałej odpowiedzi @ peeol , możesz również usunąć ramkę, wykonując czynność

for spine in plt.gca().spines.values():
    spine.set_visible(False)

Aby podać przykład (cały przykład kodu można znaleźć na końcu tego postu), powiedzmy, że masz taki wykres słupkowy,

wprowadź opis obrazu tutaj

możesz usunąć ramkę za pomocą powyższych poleceń, a następnie zachować etykiety x-i ytick(wykres niepokazany) lub je również usunąć

plt.tick_params(top='off', bottom='off', left='off', right='off', labelleft='off', labelbottom='on')

W takim przypadku można bezpośrednio oznaczyć pręty; ostateczna fabuła mogłaby wyglądać następująco (kod można znaleźć poniżej):

wprowadź opis obrazu tutaj

Oto cały kod, który jest niezbędny do wygenerowania wykresów:

import matplotlib.pyplot as plt
import numpy as np

plt.figure()

xvals = list('ABCDE')
yvals = np.array(range(1, 6))

position = np.arange(len(xvals))

mybars = plt.bar(position, yvals, align='center', linewidth=0)
plt.xticks(position, xvals)

plt.title('My great data')
# plt.show()

# get rid of the frame
for spine in plt.gca().spines.values():
    spine.set_visible(False)

# plt.show()
# remove all the ticks and directly label each bar with respective value
plt.tick_params(top='off', bottom='off', left='off', right='off', labelleft='off', labelbottom='on')

# plt.show()

# direct label each bar with Y axis values
for bari in mybars:
    height = bari.get_height()
    plt.gca().text(bari.get_x() + bari.get_width()/2, bari.get_height()-0.2, str(int(height)),
                 ha='center', color='white', fontsize=15)
plt.show()

1
To rozwiązało mój problem.
Emad Aghayi

6

Jak odpowiedziałem tutaj , możesz usunąć grzbiety ze wszystkich swoich wykresów poprzez ustawienia stylu (arkusz stylów lub rcParams):

import matplotlib as mpl

mpl.rcParams['axes.spines.left'] = False
mpl.rcParams['axes.spines.right'] = False
mpl.rcParams['axes.spines.top'] = False
mpl.rcParams['axes.spines.bottom'] = False

6

Problem

Miałem podobny problem z osiami. Parametrem klasy jest, frameonale kwarg jest frame_on. axes_api
>>> plt.gca().set(frameon=False)
AttributeError: Unknown property frameon

Rozwiązanie

frame_on

Przykład

data = range(100)
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(data)
#ax.set(frameon=False)  # Old
ax.set(frame_on=False)  # New
plt.show()


2

Aby usunąć ramkę wykresu

for spine in plt.gca().spines.values():
  spine.set_visible(False)

Mam nadzieję, że to zadziała


1
df = pd.DataFrame({
'client_scripting_ms' : client_scripting_ms,
 'apimlayer' : apimlayer, 'server' : server
}, index = index)

ax = df.plot(kind = 'barh', 
     stacked = True,
     title = "Chart",
     width = 0.20, 
     align='center', 
     figsize=(7,5))

plt.legend(loc='upper right', frameon=True)

ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)

ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('right')

0
plt.box(False)
plt.xticks([])
plt.yticks([])
plt.savefig('fig.png')

powinien załatwić sprawę.


0
plt.axis('off')
plt.savefig(file_path, bbox_inches="tight", pad_inches = 0)

plt.savefig ma te opcje w sobie, wystarczy wcześniej wyłączyć osie

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.