2010-03-09 15 views
6

Obecnie eksperymentuję z matplotlib. Jakiś czas temu użyłem kodu Excel VBA do tworzenia obrazów takich jak ten dołączony.Jak mogę tworzyć wykresy ucznia za pomocą matplotlib?

Będzie to zauważyć nie są prezentowane w stylu naukowej/badawczej, ale raczej jakby wyprodukowany przez studenta szkoły na papierze milimetrowym - z trzema różnymi stylami siatki linii.

Czy istnieje dość prosty sposób na osiągnięcie tego rodzaju rzeczy z matplotlib?

alt text

Odpowiedz

8

Tak, można użyć spines do tego.

import matplotlib.pyplot as plt 
from matplotlib.ticker import MultipleLocator, FormatStrFormatter 
import numpy as np 

fig = plt.figure(1) 
ax = fig.add_subplot(111) 

# set up axis 
ax.spines['left'].set_position('zero') 
ax.spines['right'].set_color('none') 
ax.spines['bottom'].set_position('zero') 
ax.spines['top'].set_color('none') 
ax.xaxis.set_ticks_position('bottom') 
ax.yaxis.set_ticks_position('left') 

# draw curve 
x = np.arange(-2.5,2.5,0.01) 
line, = ax.plot(x, x**2) 

#set bounds 
ax.set_ybound(-1,7) 

# create grid 
#ax.xaxis.set_major_locator(MultipleLocator(1)) 
#ax.xaxis.set_minor_locator(MultipleLocator(0.2)) 
#ax.yaxis.set_major_locator(MultipleLocator(1)) 
#ax.yaxis.set_minor_locator(MultipleLocator(0.2)) 
#ax.xaxis.grid(True,'minor') 
#ax.yaxis.grid(True,'minor') 
#ax.xaxis.grid(True,'major',linewidth=2) 
#ax.yaxis.grid(True,'major',linewidth=2) 

#adjust grid on the 2s 
#for idx,loc in enumerate(ax.xaxis.get_majorticklocs()): 
    #if loc !=0 and loc % 2 == 0: ax.get_xgridlines()[idx].set_c('r') 
#for idx,loc in enumerate(ax.yaxis.get_majorticklocs()): 
    #if loc !=0 and loc % 2 == 0: ax.get_ygridlines()[idx].set_c('r') 

## THIS IS THE EDIT 
ax.xaxis.set_minor_locator(MultipleLocator(0.2)) 
ax.yaxis.set_minor_locator(MultipleLocator(0.2)) 
ax.xaxis.grid(True,'minor',linewidth=2) 
ax.yaxis.grid(True,'minor',linewidth=2) 

minor_grid_lines = [tick.gridline for tick in ax.xaxis.get_minor_ticks()] 
for idx,loc in enumerate(ax.xaxis.get_minorticklocs()): 
    if loc % 2.0 == 0: minor_grid_lines[idx].set_c('r') 
    elif loc % 1.0 == 0: minor_grid_lines[idx].set_c('g') 
    else: minor_grid_lines[idx].set_c('b') 

plt.show() 

alt text http://i42.tinypic.com/a1pcw3.png

+0

Superb !!! Wygląda na to, o co mi chodziło. Wielkie dzięki! – Geddes

+0

Moje ostatnie pytanie brzmi: czy istnieje sposób na uzyskanie trzech różnych stylów linii siatki? Chcę jeden styl za * 0.2, inny za * 1, a jeszcze inny za * 2 (jak na papierze graficznym). Wydaje się to trudne, ponieważ wydaje się, że matplotlib nakłada tylko duże/małe tyknięcia. Dzięki jeszcze raz! – Geddes

+0

@Geddes, patrz zmiany powyżej. Myślę, że najłatwiej byłoby po prostu dostosować linie siatki na podstawie ich pozycji (tj. Na wielokrotnościach 2). – Mark

1

Kolejna myśl - Próbowałem również zrobić to wszystko z drobnych linii siatki (oprócz cokolwiek innego to pomoże moim rozumieniu), ale to nie wyliczanie prawidłowo, nie ma wątpliwości ze względu na get_minorticklocs i ax.get_xgridlines. Niestety, i z góry dzięki ...

Geddes

import matplotlib.pyplot as plt 
from matplotlib.ticker import MultipleLocator, FormatStrFormatter 
import numpy as np 

fig = plt.figure(1) 
ax = fig.add_subplot(111) 

# set up axis 
ax.spines['left'].set_position('zero') 
ax.spines['right'].set_color('none') 
ax.spines['bottom'].set_position('zero') 
ax.spines['top'].set_color('none') 
ax.xaxis.set_ticks_position('bottom') 
ax.yaxis.set_ticks_position('left') 

# draw curve 
x = np.arange(-2.5,2.5,0.01) 
line, = ax.plot(x, x**2) 

#set bounds 
ax.set_ybound(-1,7) 

# create grid 
ax.xaxis.set_minor_locator(MultipleLocator(0.2)) 
ax.yaxis.set_minor_locator(MultipleLocator(0.2)) 
ax.xaxis.grid(True,'minor',linewidth=2) 
ax.yaxis.grid(True,'minor',linewidth=2) 

#adjust grid on the 2s 
for idx,loc in enumerate(ax.xaxis.get_minorticklocs()): 
    if loc % 2 == 0: ax.get_xgridlines()[idx].set_color('r') 
    if loc % 1 == 0: ax.get_xgridlines()[idx].set_color('g') 
    if loc % 0.2 == 0: ax.get_xgridlines()[idx].set_color('b') 

for idx,loc in enumerate(ax.yaxis.get_majorticklocs()): 
    if loc % 2 == 0: ax.get_ygridlines()[idx].set_c('b') 

plt.savefig('spines3.png',dpi=300) 
+0

@Geddes, że ax.get_xgridlines() zwraca tylko główne linie siatki. Zobacz zmiany w powyższej odpowiedzi. – Mark

+0

Fantastyczna - dziękuję bardzo za całą pomoc dzisiaj Mark - Wiem, że jestem wymagającym klientem! Wszystkie moje najlepsze życzenia, Geddes – Geddes

0

Jest to zmodyfikowana wersja zaakceptowanej odpowiedzi powyżej. Może ktoś znajdzie to pomocne

import matplotlib.pyplot as plt 
from matplotlib.ticker import MultipleLocator, FormatStrFormatter 
import numpy as np 
from matplotlib.ticker import FormatStrFormatter 

_fontsize_legend = 10 
_fontsize = 15 

DP = 2 

fig = plt.figure(figsize=(12, 12), dpi=100, facecolor='w', edgecolor='k') 
##fig = plt.figure() 
fig.canvas.draw() 
ax = plt.gca() 

# set up axis 
ax.spines['left'].set_position('zero') 
ax.spines['right'].set_color('none') 
ax.spines['bottom'].set_position('zero') 
ax.spines['top'].set_color('none') 
ax.xaxis.set_ticks_position('bottom') 
ax.yaxis.set_ticks_position('left') 

# draw curve 
x = np.arange(-2.5,2.5,0.01) 
line, = ax.plot(x, x**2) 

#set bounds 
ax.set_ybound(-1,7) 

## THIS IS THE EDIT 
ax.xaxis.set_major_locator(MultipleLocator(1/4)) 
ax.yaxis.set_major_locator(MultipleLocator(1/4)) 
ax.xaxis.grid(True,'major',linewidth=2/DP,linestyle='-',color='#d7d7d7',zorder=0) 
ax.yaxis.grid(True,'major',linewidth=2/DP,linestyle='-',color='#d7d7d7') 

ax.xaxis.set_minor_locator(MultipleLocator((1/4)/5)) 
ax.yaxis.set_minor_locator(MultipleLocator((1/4)/5)) 
ax.xaxis.grid(True,'minor',linewidth=0.5/DP,linestyle='-',color='#d7d7d7') 
ax.yaxis.grid(True,'minor',linewidth=0.5/DP,linestyle='-',color='#d7d7d7') 

ax.set_axisbelow(True) 
ax.set_aspect('equal') 

##ax.axhline(linewidth=0) 
##ax.axvline(linewidth=0) 

ax.xaxis.set_major_formatter(FormatStrFormatter('%i')) 
xticks = ax.xaxis.get_major_ticks() 
for i,l in enumerate(xticks): 
    if not (i - 1) % 4 == 0: 
     xticks[i].label1.set_visible(False) 
    else: 
     xticks[i].label1.set_fontsize(_fontsize) 

ax.yaxis.set_major_formatter(FormatStrFormatter('%i')) 
yticks = ax.yaxis.get_major_ticks() 
for i,l in enumerate(yticks): 
    if not (i - 1) % 4 == 0: 
     yticks[i].label1.set_visible(False) 
    else: 
     yticks[i].label1.set_fontsize(_fontsize)  

figManager = plt.get_current_fig_manager() 
figManager.window.showMaximized() 
plt.show() 

This is how this sample looks [picture]