Как нарисовать ось в середине фигуры?

Я хочу нарисовать фигуру в Matplotib, где оси отображаются в самом графике, а не на стороне

Я попробовал следующий код отсюда:

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

def sigmoid(x):
    a = []
    for item in x:
        a.append(1/(1+math.exp(-item)))
    return a

x = np.arange(-10., 10., 0.2)
sig = sigmoid(x)

plt.plot(x,sig)
plt.show()

Приведенный выше код отображает рисунок следующим образом:

То, что я хотел бы нарисовать что-то следующее (изображение из Wiki)

Посмотрев на этот вопрос, он рисует контрольную линию в середине, но без оси.

Ответ 1

Один из способов сделать это - spines:

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

def sigmoid(x):
    a = []
    for item in x:
        a.append(1/(1+math.exp(-item)))
    return a


x = np.arange(-10., 10., 0.2)
sig = sigmoid(x)

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

# Move left y-axis and bottim x-axis to centre, passing through (0,0)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('center')

# Eliminate upper and right axes
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

# Show ticks in the left and lower axes only
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')

plt.plot(x,sig)
plt.show()

показывает:  enter image description here

Ответ 2

В принципе, я хочу прокомментировать принятый ответ (но мой представитель этого не допускает). Использование

ax.spines['bottom'].set_position('center')

рисует оси x таким образом, что пересекает оси y в своем центре. В случае асимметричного ylim это означает, что ось x проходит через y = 0. Ответ Jblasco имеет этот недостаток, пересечение находится при y = 0,5 (центр между ymin = 0,0 и ymax = 1,0) Однако ссылочный график исходного вопроса имеет оси, которые пересекаются друг с другом в 0,0 (что является как-то обычным или, по крайней мере, общим). Чтобы достичь этого,

ax.spines['bottom'].set_position('zero')

. См. Следующий пример, где "ноль" делает оси пересекающимися на 0,0, несмотря на асимметричные диапазоны как для x, так и для y.

import numpy as np
import matplotlib.pyplot as plt

#data generation
x = np.arange(-10,20,0.2)
y = 1.0/(1.0+np.exp(-x)) # nunpy does the calculation elementwise for you


fig, [ax0, ax1] = plt.subplots(ncols=2, figsize=(8,4))

# Eliminate upper and right axes
ax0.spines['top'].set_visible(False)
ax0.spines['right'].set_visible(False)
# Show ticks on the left and lower axes only
ax0.xaxis.set_tick_params(bottom='on', top='off')
ax0.yaxis.set_tick_params(left='on', right='off')

# Move remaining spines to the center
ax0.set_title('center')
ax0.spines['bottom'].set_position('center') # spine for xaxis 
#    - will pass through the center of the y-values (which is 0)
ax0.spines['left'].set_position('center')  # spine for yaxis 
#    - will pass through the center of the x-values (which is 5)

ax0.plot(x,y)


# Eliminate upper and right axes
ax1.spines['top'].set_visible(False)
ax1.spines['right'].set_visible(False)
# Show ticks on the left and lower axes only (and let them protrude in both directions)
ax1.xaxis.set_tick_params(bottom='on', top='off', direction='inout')
ax1.yaxis.set_tick_params(left='on', right='off', direction='inout')

# Make spines pass through zero of the other axis
ax1.set_title('zero')
ax1.spines['bottom'].set_position('zero')
ax1.spines['left'].set_position('zero')

ax1.set_ylim(-0.4,1.0)

# No ticklabels at zero
ax1.set_xticks([-10,-5,5,10,15,20])
ax1.set_yticks([-0.4,-0.2,0.2,0.4,0.6,0.8,1.0])

ax1.plot(x,y)

plt.show() 

Заключительное замечание: если используется ax.spines['bottom'].set_position('zero'), но ноль не входит в график y-диапазона, то оси показаны на границе графика ближе к нулю.

Ответ 3

Название этого вопроса - как нарисовать позвоночник посередине, и принятый ответ делает именно это, но вы, ребята, рисуете сигмовидную функцию, которая проходит через у = 0,5. Поэтому я думаю, что вы хотите, чтобы позвоночник был в центре, согласно вашим данным. Для этого Matplotlib предлагает данные о положении позвоночника (см. Документацию)

import numpy as np
import matplotlib.pyplot as plt
def sigmoid(x):
    return 1 / (1 + np.exp(-x))
sigmoid = np.vectorize(sigmoid) #vectorize function
values=np.linspace(-10, 10) #generate values between -10 and 10
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

#spine placement data centered
ax.spines['left'].set_position(('data', 0.0))
ax.spines['bottom'].set_position(('data', 0.0))
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

plt.plot(values, sigmoid(values))
plt.show()

Похоже на это (Github):

enter image description here