Как изменить пределы оси для разброса после создания фигуры в python - PullRequest
0 голосов
/ 09 июля 2020

Я хочу создать график поля НФЛ, а затем нанести на него диаграмму рассеяния. Вот мой код для поля (просто скопируйте и вставьте все это. Вопрос не в этом):

import matplotlib.pyplot as plt
import pylab as pl


# Create figure
fig, ax = pl.subplots(figsize=(15,10))

# Set field dimensions
plt.xlim(0, 120)  # Field length including endzones
plt.ylim(0, 53.3)  # field width

# Set field color green
ax.set_facecolor('#79af75')
ax.set_alpha(0.5)

# Print lines
for i in range(0, 120, 10):
    plt.axvline(i, color='white', linewidth=3, alpha=0.4, zorder=1)
    if i == 10 or i == 110:  # Make endzone lines
        plt.axvline(i, color='white', linewidth=5, alpha=0.4, zorder=1)

# Paint numbers
yds_from_sideline = 12
for i in range(10, 50, 10):
    plt.text(i+10, 53.3-yds_from_sideline, str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)
    plt.text(110-i, 53.3-yds_from_sideline,  str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)

    plt.text(i+10, yds_from_sideline, str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')
    plt.text(110-i, yds_from_sideline, str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')

# Paint 50 yard line numbers
plt.text(60, 53.3-yds_from_sideline, str(50), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)
plt.text(60, yds_from_sideline, str(50), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')

# Print something in the endzones

plt.text(5, 26.5, 'Vikings', color='#4F2683', fontsize=30, verticalalignment='center', horizontalalignment='center', rotation=90)
plt.text(115, 26.5, 'Opponent', color='black', fontsize=30, verticalalignment='center', horizontalalignment='center', rotation=270)


# Fix the aspect ratio (optional)
plt.gca().set_aspect(1)

# Display the figure
plt.show()

Если вы запустите это, все должно работать отлично! Теперь у меня есть набор данных, который я хочу построить поверх него. Вот его образец:

data

  posteam   yardline_100    epa
0   MIN         1.0       0.343304
1   MIN         2.0       0.340690
2   MIN         3.0       0.128643
3   MIN         4.0       0.747664
4   MIN         5.0      -0.190321
5   MIN         6.0       0.265953
6   MIN         7.0      -0.362923
7   MIN         8.0      -0.684526
8   MIN         9.0      -0.107560
9   MIN         10.0      0.263269
10  MIN         11.0     -0.042605
11  MIN         12.0      0.126719
12  MIN         13.0     -0.531782
13  MIN         14.0     -0.329170
14  MIN         15.0      0.608268

Я попытался добавить следующий код в график поля, но ничего не вышло.

Добавленный код:


plt.title('The gridiron', fontsize=14)
plt.ylabel('EPA', fontsize=12)
plt.xlabel('Yardline', fontsize=12)

ax.set_yticks(np.arange(-5, 6,1))

ax.scatter(x='yardline_100',y='epa',data=data)

Всё это и на выходе:

# Create figure
fig, ax = pl.subplots(figsize=(15,10))

# Set field dimensions
plt.xlim(0, 120)  # Field length including endzones
plt.ylim(0, 53.3)  # field width

# Set field color green
ax.set_facecolor('#79af75')
ax.set_alpha(0.5)

# Print lines
for i in range(0, 120, 10):
    plt.axvline(i, color='white', linewidth=3, alpha=0.4, zorder=1)
    if i == 10 or i == 110:  # Make endzone lines
        plt.axvline(i, color='white', linewidth=5, alpha=0.4, zorder=1)

# Paint numbers
yds_from_sideline = 12
for i in range(10, 50, 10):
    plt.text(i+10, 53.3-yds_from_sideline, str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)
    plt.text(110-i, 53.3-yds_from_sideline,  str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)

    plt.text(i+10, yds_from_sideline, str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')
    plt.text(110-i, yds_from_sideline, str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')

# Paint 50 yard line numbers
plt.text(60, 53.3-yds_from_sideline, str(50), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)
plt.text(60, yds_from_sideline, str(50), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')

# Print something in the endzones

plt.text(5, 26.5, 'Vikings', color='#4F2683', fontsize=30, verticalalignment='center', horizontalalignment='center', rotation=90)
plt.text(115, 26.5, 'Opponent', color='black', fontsize=30, verticalalignment='center', horizontalalignment='center', rotation=270)

# Just showing how to set titles and labels
plt.title('The gridiron', fontsize=14)
plt.ylabel('EPA', fontsize=12)
plt.xlabel('Yardline', fontsize=12)

plt.title('The gridiron', fontsize=14)
plt.ylabel('EPA', fontsize=12)
plt.xlabel('Yardline', fontsize=12)

ax.set_yticks(np.arange(-5, 6,1))

ax.scatter(x='yardline_100',y='epa',data=data)


# Fix the aspect ratio (optional)
plt.gca().set_aspect(1)

# Display the figure
plt.show()

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

Что я действительно хотел бы сделать, так это масштабировать ось так, чтобы -5 находилась внизу, а 5 - вверху оси y, вместо того, чтобы сжимать диапазон от -5 до 5 внизу . Кроме того, я хотел бы таким же образом переместить ось x на 10 единиц. То есть я бы хотел, чтобы скаттеры начинались с X = 10 вместо X = 0. Если вам нужны дополнительные разъяснения, дайте мне знать. Спасибо!

1 Ответ

2 голосов
/ 09 июля 2020

Не уверен, что это лучший способ сделать это, но я сначала масштабировал ylim до вашего желаемого диапазона (-5,5), затем масштабировал значения ярдов для plt.text() из диапазона (0,53,3 ) в диапазоне (-5,5), регулируя соответственно верхнее / нижнее значения в plt.text() (от 53,3 до 5, от 0 до -5). Наконец, изменено ax.scatter(), чтобы напрямую ссылаться на столбцы данных, поэтому для смещения по оси x просто добавлено значение 10. Кроме того, удалено set_aspect(1).

Таким образом вы не создадите слишком большую фигуру в начале, который затем необходимо передать.

Код (изменения предшествуют комментарию # CHANGES HERE !!!:

import matplotlib.pyplot as plt
import pylab as pl
import numpy as np

# Create figure
fig, ax = pl.subplots(figsize=(15,10))

# Set field dimensions
plt.xlim(0, 120)  # Field length including endzones

# CHANGES HERE !!!
# set ylim respective to your data
plt.ylim(-5, 5)  # field width

# Set field color green
ax.set_facecolor('#79af75')
ax.set_alpha(0.5)

# Print lines
for i in range(0, 120, 10):
    plt.axvline(i, color='white', linewidth=3, alpha=0.4, zorder=1)
    if i == 10 or i == 110:  # Make endzone lines
        plt.axvline(i, color='white', linewidth=5, alpha=0.4, zorder=1)

# Paint numbers
yds_from_sideline = 12
for i in range(10, 50, 10):
#   CHANGES HERE !!!
#   change y values because ylim has changed (top-ylim - yds_from_sideline translated to scale of ylim)
    plt.text(i+10, 5-10*(yds_from_sideline/53.3), str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)
    plt.text(110-i, 5-10*(yds_from_sideline/53.3),  str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)

    plt.text(i+10, -5 + 10*(yds_from_sideline/53.3), str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')
    plt.text(110-i, -5 + 10*(yds_from_sideline/53.3), str(i), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')

# Paint 50 yard line numbers
# CHANGES HERE !!!
# change y values here as well
plt.text(60, 5-10*(yds_from_sideline/53.3), str(50), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center', rotation=180)
plt.text(60, -5+10*(yds_from_sideline/53.3), str(50), color='white', fontsize=20, verticalalignment='bottom', horizontalalignment='center')

# Print something in the endzones

plt.text(5, 0, 'Vikings', color='#4F2683', fontsize=30, verticalalignment='center', horizontalalignment='center', rotation=90)
plt.text(115, 0, 'Opponent', color='black', fontsize=30, verticalalignment='center', horizontalalignment='center', rotation=270)

# Just showing how to set titles and labels
plt.title('The gridiron', fontsize=14)
plt.ylabel('EPA', fontsize=12)
plt.xlabel('Yardline', fontsize=12)

plt.title('The gridiron', fontsize=14)
plt.ylabel('EPA', fontsize=12)
plt.xlabel('Yardline', fontsize=12)

ax.set_yticks(np.arange(-5, 6,1))

# CHANGES HERE !!!
# increase x by 10 to start at x = 10
ax.scatter(x=data['yardline_100']+10,y=data['epa'])



# # Fix the aspect ratio (optional)
# plt.gca().set_aspect(1)

# Display the figure
plt.show()

Вывод (с использованием данных вашего примера) :

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

...