matplotlib — нарисуйте более приятный график этой функции (x * x * x) / (x * x — 3 * x 2)

#python #matplotlib

#python #matplotlib

Вопрос:

Я пытаюсь визуализировать график этой функции с помощью matplotlib.

f(x) = (x*x*x) / (x*x - 3*x 2)

Эта функция обладает довольно интересными свойствами и графиком.

В качестве вертикальных асимптот она имеет линии x=1 и x=2 .
Кроме того, у него есть другая асимптота, y=x 3 которая f(x) приближается
поскольку x стремится к плюсовой и минусовой бесконечности.

Он имеет локальный максимум на 3-sqrt(3) и локальный минимум на 3 sqrt(3) .

Но график выглядит очень некрасиво, потому что масштаб по оси Y
получается намного больше, чем масштаб по оси X. Я предполагаю, что это
потому, что функция не определена для x=1 и x=2 .

Смотрите (немного) лучший график здесь:
https://www.wolframalpha.com/input/?i=x *x* x / % 28x * x — 3* x+2)

Как я могу сделать этот график более красивым с помощью matplotlib?
Или … это невозможно, и я должен использовать вместо этого какую-то другую библиотеку?

Вот мой код.

 import math as mt
import numpy as np
import matplotlib.pyplot as plt

a = -7
b =  7

x = np.linspace(a, b, 5000)
y1 = ( x*x*x ) / (x*x - 3*x   2)

plt.plot(x, y1, color = 'red')

plt.show()
  

СЛЕДУЮЩАЯ ПОПЫТКА:

Здесь я пытаюсь сказать matplotlib, чтобы он ничего не отображал в интервалах (1-EPS, 1 EPS) и (2-EPS, 2 EPS) . Тем не менее, он продолжает строить там график. Почему?!

 import math as mt
import numpy as np
import matplotlib.pyplot as plt

a = -10
b =  10

EPS = 0.1

x1 = np.linspace(a, 1-EPS, 2000)
x2 = np.linspace(1   EPS, 2 - EPS, 2000)
x3 = np.linspace(2   EPS, b, 2000)
x = np.concatenate((x1, x2, x3))

fig, ax = plt.subplots()

y1 = ( x*x*x ) / (x*x - 3*x   2)
y2 = (x 3)

ax.plot(x, y1, color = 'red')
ax.plot(x, y2, color = 'green')

# plt.plot(x, y1, color = 'red')
# plt.plot(x, y2, color = 'green')

plt.axis([a,b,-100,100])

ax.grid(True, which='both')

ax.axhline(y=0, color='k')
ax.axvline(x=0, color='k')

plt.axvline(x=1, color = 'green')
plt.axvline(x=2, color = 'green')

plt.show()
  

Ответ №1:

Вы можете убедиться, что оси имеют одинаковый масштаб, используя

 plt.axis('equal')
  

Перед plt.show() строкой.


Попробуйте это тогда вместо:

 plt.axis([a,b,-100,100])
  

Вы можете вручную изменить пределы x и y на то, что вам нужно.


Если вы хотите избежать линии между положительным и отрицательным «бесконечными» значениями, вы можете вместо того, чтобы отображать функцию в виде непрерывной линии, отобразить ее в виде ряда точек, используя:

 plt.plot(x, y1, '.', color = 'red')
  

Это, однако, выглядит не так красиво.

Другой альтернативой является разделение массива значений в на несколько частей, а затем построение их одного за другим.


Окончательное решение:

 import math as mt
import numpy as np
import matplotlib.pyplot as plt

alpha = mt.acos(mt.sqrt(11.0/12.0))

a = -3.5
b =  3.5

# a = -1.5
# b = 1.5

x = np.linspace(a, b, 5000)
y1 = ( x*x*x ) / (x*x - 3*x   2)
# y2 = x * x

dy1  = np.diff(y1)
pos = np.where(abs(dy1) > 1000)[0]   1
plot_y1 = np.split(y1, pos)
plot_x = np.split(x, pos)

print(pos)

for x_line, y_line in zip(plot_x, plot_y1):
    plt.plot(x_line, y_line, color = 'red')

plt.grid()
plt.axis([a,b,-100,100])
plt.show()
  

Теперь вместо этого он находит, где есть большие различия, и автоматически разбивает массив.

Комментарии:

1. Хм … это делает ситуацию еще хуже. Попробуйте, пожалуйста.

2. Спасибо. Да, это несколько лучше. Но почему вертикальные асимптоты также выделены красным, как будто они являются частью графика функции?

3. Ну, они являются частью функции? В этом случае они не являются асимметриями функции, они являются ее частью? Вот почему ее называют асимптотой, потому что функция будет сходиться к ней, то есть следовать за ней.

4. О, извините, неважно, я пропустил прочитанный вами вопрос. Python построит график функции по координате, и поскольку отрицательная и положительная точки находятся рядом друг с другом в массиве точек, между ними будет линия.

5. Да, спасибо! Теперь ваш код работает лучше. Почему моя вторая попытка ведет себя не так, как я ожидаю? Пожалуйста, посмотрите мою правку, где я использую concatenate и я составляю x , чтобы объединить 3 интервала. По-прежнему безуспешно.

Ответ №2:

Вы можете обмануть его с помощью большого количества точек, которые будут нанесены без линии между ними:

 x = linspace(-10,10,100000)
def f(x): 
    return x**3/(x**2-3*x 2) 
plt.plot(x, f(x), '.', ms=1) 
plt.xlim(-10,10) 
plt.ylim(-20,25)         
  

введите описание изображения здесь

Или, если вы не хотите, чтобы на вашем графике было слишком много точек, вы можете определить x1 x2 x3 интервалы, где нет разрыва, и нанести их отдельно линиями ( plot(x1, f(x1), 'k-') , plot(x2, f(x2), 'k-') и т.д.). Это похоже на то, что вы делаете, но не объединяйте их в один x .

Комментарии:

1. Спасибо! Я, наконец, понял это.