У меня проблема с установкой xticks и yticks в matplotlib. Я хочу нарисовать линейный график на основе дат и цен (например, BT C price). Я обновляю цены каждые 30 минут, поэтому я хочу, чтобы набор графика рисовался на основе на каждую цену, которую я имею, но показываю только 4 - 5 цен в xticks и показываю дату только один раз в yticks (извините, мой engli sh плохо, я не могу объяснить лучше)
так, я покажет вам здесь:
Я хочу цены (yticks), как это:
![enter image description here](https://i.stack.imgur.com/wPqtD.png)
и даты (xticks), как:
![enter image description here](https://i.stack.imgur.com/elCQh.png)
но мои данные повреждены:
![enter image description here](https://i.stack.imgur.com/u2Z3p.png)
ПОЛНЫЙ КОД:
class PriceChangePlots:
def __init__(self, session: Session, for_cars: bool):
self.for_cars = for_cars
self.media_path = 'media/'
self.font_nazanin = fm.FontProperties(fname=self.media_path + 'fonts/BNAZANIN.TTF', size=14)
self.font_yekan = fm.FontProperties(fname=self.media_path + 'fonts/BYekan+.ttf', size=14)
self.DB = session
self.chart: Charts = self.DB.query(Charts)
self.cars = self.DB.query(Prices)
def get_model_data(self, model_code):
cars = self.cars
# get model data from database
models = cars.with_entities(
Prices.datetime, Prices.price).filter(
Prices.datetime > datetime.now() - timedelta(weeks=1)).filter_by(
model_code=model_code).all()
# convert datetime to persian dates
JD = jdatetime.date.fromgregorian # make an object of datetime converter
models = list(
map(
lambda details:
(JD(date=details[0].date()), details[1]), # tuple of details
# ^^^ DATE ^^^ PRICE
models
))
# make a dictionary to avoid repeat days
# models = _remove_duplicates(models)
# data = dict(models)
return models
@staticmethod
def fa(persian_text):
reshaped_text = arabic_reshaper.reshape(persian_text)
farsi_text = get_display(reshaped_text)
return farsi_text
def line(self, model_code):
cars = self.cars
for_cars = self.for_cars
model: Prices = cars.filter_by(model_code=model_code).first()
fa = self.fa
data = self.get_model_data(model_code)
plt.style.use('default')
dates = list(map(lambda x: x[0], data)) # dates
prices = list(map(lambda x: x[1], data)) # prices
average = np.average(prices) # average of car price in last 2 weeks
average = round(average, 2) # round it with 2 decimals
# if average is greater than 1M
if average > 10 ** 6:
avg_label = round(average / 10 ** 6, 2)
else:
avg_label = average
# check if average have decimals or not
if avg_label.is_integer():
avg_label = int(avg_label)
# average line
if average > 10 ** 6:
avg_label = f'{fa("میانگین")}={avg_label}M'
else:
avg_label = f'{fa("میانگین")}={avg_label}'
fig: Figure
ax: Axes
fig, ax = plt.subplots()
dates_array = np.arange(len(dates))
# prices axe
a: Line2D = ax.plot(dates_array, prices, linewidth=3)
# print(type(b))
ax.plot(dates_array, [average] * len(prices), linestyle='-.', linewidth=2,
color='#6495ed', label=avg_label)
ax.fill_between(dates_array, prices, average,
where=(prices > average), color='red',
alpha=0.2, interpolate=True, label=fa('بزرگتر از میانگین'))
ax.fill_between(dates_array, prices, average,
where=(prices < average), color='green',
alpha=0.2, interpolate=True, label=fa('کوچکتر از میانگین'))
if for_cars:
title = fa(f"تغییرات قیمت %s %s" % (model.brand, model.model_name))
else:
title = fa(f"تغییرات قیمت %s" % model.model_name)
plt.title(title, fontproperties=self.font_yekan, size=20)
ax.grid(color='k', linewidth=.5, linestyle=':', axis='y')
# shorten prices ( price / 1M )
y_ticks = []
for price in prices:
if price > 10 ** 6:
price = round(price / 10 ** 6, 2)
if price.is_integer(): # if price have no decimals
price = int(price)
price = s(price)
price = f'{price}M'
else:
price = float(round(price, 2))
if price.is_integer(): # if price have no decimals
price = int(price)
price = s(price)
y_ticks.append(price)
# _: Line2D
# y_data = a[0].get_ydata()
# plt.yticks(y_data, y_ticks)
plt.xticks(dates_array, dates, rotation=45)
fig.text(0.5, 0.55, fa("قیمت روزانه خودرو:\nt.me/CPricesBot"), # 't.me/CPricesBot',
fontsize=40, color='gray', fontproperties=self.font_yekan,
ha='center', va='center', alpha=0.30, size=25)
legend: Legend = ax.legend()
# change legend font
text: Text
for text in legend.texts:
text.set_fontproperties(self.font_yekan)
text.set_fontsize(10)
fig.tight_layout(pad=2)
# fig.savefig(self.media_path + 'plots/price_change_plots/' + model_code + '.png')
fig.show()
plt.close()