2015-07-01 10 views
9

Próbowałem działki prostokąt na wykresie z datetime osi x, stosując następujący kod:Jak narysować prostokąt na osi datetime za pomocą matplotlib?

from datetime import datetime, timedelta 
from matplotlib.patches import Rectangle 
import matplotlib.pyplot as plt 

# Create new plot 
fig = plt.figure() 
ax = fig.add_subplot(111) 

# Create rectangle 
startTime = datetime.now() 
width = timedelta(seconds = 1) 
endTime = startTime + width 
rect = Rectangle((startTime, 0), width, 1, color='yellow') 

# Plot rectangle 
ax.add_patch(rect) ### ERROR HERE!!! ### 
plt.xlim([startTime, endTime]) 
plt.ylim([0, 1]) 
plt.show() 

Jednakże pojawia się błąd:

TypeError: unsupported operand type(s) for +: 'float' and 'datetime.timedelta' 

co się dzieje nie tak? (Używam wersji macplotlib 1.0.1)

Odpowiedz

10

Problem polega na tym, że matplotlib używa własnej reprezentacji daty/godziny (floating liczba dni), więc musisz je najpierw przekonwertować. Co więcej, będziesz musiał powiedzieć xaxis, że powinien on mieć znaczniki daty i czasu oraz etykiety. Poniższy kod robi:

from datetime import datetime, timedelta 
from matplotlib.patches import Rectangle 
import matplotlib.pyplot as plt 
import matplotlib.dates as mdates 

# Create new plot 
fig = plt.figure() 
ax = fig.add_subplot(111) 

# Create rectangle x coordinates 
startTime = datetime.now() 
endTime = startTime + timedelta(seconds = 1) 

# convert to matplotlib date representation 
start = mdates.date2num(startTime) 
end = mdates.date2num(endTime) 
width = end - start 

# Plot rectangle 
rect = Rectangle((start, 0), width, 1, color='yellow') 
ax.add_patch(rect) 

# assign date locator/formatter to the x-axis to get proper labels 
locator = mdates.AutoDateLocator(minticks=3) 
formatter = mdates.AutoDateFormatter(locator) 
ax.xaxis.set_major_locator(locator) 
ax.xaxis.set_major_formatter(formatter) 

# set the limits 
plt.xlim([start-width, end+width]) 
plt.ylim([-.5, 1.5]) 

# go 
plt.show() 

Wynik:

enter image description here

UWAGA: matplotlib 1.0.1 jest bardzo stary. Nie mogę zagwarantować, że mój przykład zadziała. Powinieneś spróbować zaktualizować!

+0

Pamiętaj, że jeśli daty na osi X pochodzą z 'pand', musisz najpierw przekonwertować na pythona na datę i godzinę. Wiersz 'start = mdates.date2num (startTime)' miałby wówczas postać 'start = mdates.date2num (startTime.to_pydatetime())'. To samo dotyczy "końca". – Luis

-1

Problem polega na tym, że type(startTime) datetime.datetime nie jest poprawnym typem przekazywanym do prostokąta. Musi to być typecast do obsługiwanego typu, aby użyć łaty prostokątnej.

Jeśli wszystko czego naprawdę chcę to zrobić żółty prostokąt prostu zrobić normalny wykres z żółtym tle:

from datetime import datetime, timedelta 
from matplotlib.patches import Rectangle 
import matplotlib.pyplot as plt 

# Create new plot 
fig = plt.figure() 
ax = fig.add_subplot(111, axisbg='yellow') 
plt.xticks(rotation=15) 
plt.tight_layout() 
# Create rectangle 
startTime = datetime.now() 
width = timedelta(seconds = 1) 
endTime = startTime + width 

#rect = Rectangle((0, 0), 1, 1, color='yellow') 

# Plot rectangle 
#ax.add_patch(rect) ### ERROR HERE!!! ### 

plt.xlim([startTime, endTime]) 
plt.ylim([0, 1]) 
plt.show() 
0

Innym błędem, który można zobaczyć podczas próby utworzenia patches.Rectangle artystę użyciu wartości datetime dla x jest:

TypeError: float() argument must be a string or a number.

Powodem tego jest to, że podczas Rectangle obiektu inicjalizacji x argumentem jest przekształcany wewnętrznie float:

self._x = float(xy[0])

To nie działa na d wartości atakcji. Rozwiązanie zaproponowane przez @hitzg rozwiąże ten problem, ponieważ matplotlib.dates.date2num() zwraca wartość zmiennoprzecinkową.

Powiązane problemy