Как добавить координаты измерений вместо координат обычных графиков в прямоугольники в matplotlib.patches.rectangle - PullRequest
1 голос
/ 02 августа 2020

введите описание изображения здесь Я рисую несколько прямоугольников, используя matplotlib.patches.Rectangle. Мне нужно добавить размеры для каждого. Вместо обычных координат X графика мне нужно указать размеры каждого прямоугольника. На данном рисунке мне нужно показать координаты x на границах не стандартные 250, 500, 750 ..

part1 = matplotlib.patches.Rectangle((ip.iloc[i,7], ip.iloc[i,8]), ip.iloc[i,3], ip.iloc[i,4], color =np.random.rand(3)) 
ax.add_patch(part1)
plt.text(ip.iloc[i,7]+(0.5*ip.iloc[i,4]), (ip.iloc[i,8]+(0.5*ip.iloc[i,3])),ip.iloc[i,0],rotation='vertical', color = 'white',fontsize=8)

1 Ответ

1 голос
/ 02 августа 2020

СЛУЧАЙ 1: ОДНА ГРУППА

Если у вас есть фрейм данных ip со столбцами 'x' и 'y' с координатами ваших прямоугольников, которые принадлежат одной группе, вы можете установить свой галочки с ax.set_xticks(ip['x']) и ax.set_yticks(ip['y']). Таким образом, вы получите все отметки, кроме последнего, который необходимо указать с помощью max(ip['x']) + ip.iloc[np.argmax(ip['x']), ip.columns.get_loc('width')] и max(ip['y']) + ip.iloc[np.argmax(ip['y']), ip.columns.get_loc('height')]. В вашем кадре данных ip эти столбцы должны быть 8-м (7 python индекс) и 9-м (8 python индекс). Для справки проверьте приведенный ниже код.

Код

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

ip = pd.DataFrame({'x': [0, 260, 520, 0, 260, 520],
                   'y': [0, 0, 0, 120, 120, 120],
                   'width': [260, 260, 230, 260, 260, 230],
                   'height': [120, 120, 120, 130, 130, 130],
                   'text': np.random.randint(0, 1000, 6)})

fig, ax = plt.subplots()

for i in range(len(ip)):
    part1 = matplotlib.patches.Rectangle((ip.iloc[i,0], ip.iloc[i,1]), ip.iloc[i,2], ip.iloc[i,3], color=np.random.rand(3))
    ax.add_patch(part1)
    plt.text(ip.iloc[i,0]+(0.5*ip.iloc[i,2]), (ip.iloc[i,1]+(0.5*ip.iloc[i,3])), ip.iloc[i,4], rotation='vertical', color='white', fontsize=8)

xticks = list(ip['x'])
xticks.append(max(ip['x']) + ip.iloc[np.argmax(ip['x']), ip.columns.get_loc('width')])
yticks = list(ip['y'])
yticks.append(max(ip['y']) + ip.iloc[np.argmax(ip['y']), ip.columns.get_loc('height')])
ax.set_xticks(xticks)
ax.set_yticks(yticks)

ax.set_xlim([min(ip['x']), max(ip['x']) + ip.iloc[np.argmax(ip['x']), ip.columns.get_loc('width')]])
ax.set_ylim([min(ip['y']), max(ip['y']) + ip.iloc[np.argmax(ip['y']), ip.columns.get_loc('height')]])
plt.show()

Dataframe

     x    y  width  height  text
0    0    0    260     120   372
1  260    0    260     120   543
2  520    0    230     120   174
3    0  120    260     130   140
4  260  120    260     130    27
5  520  120    230     130   800

Результат

enter image description here


CASE 2: DOUBLE GRUOP

If you have two different groups of areas, as in your image, one below 300 on y and the other above this threshold, you can duplicate the x axis in order to have the lower ticks on the bottom axis (ax1) and the upper ticks on the top axis (ax2). Check the code below for reference.
Please, note that here I used a different approach in order to simplify a bit the code and the readability.

Code

import matplotlib
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

ip = pd.DataFrame({'x': [0, 260, 520, 0, 260, 520, 0, 250, 500, 0],
                   'y': [0, 0, 0, 120, 120, 120, 300, 300, 300, 410],
                   'width': [260, 260, 230, 260, 260, 230, 200, 170, 150, 250],
                   'height': [120, 120, 120, 130, 130, 130, 110, 110, 110, 120],
                   'text': np.random.randint(0, 1000, 10)})

fig, ax1 = plt.subplots()
ax2 = ax1.twiny()

for i in range(len(ip)):
    part1 = matplotlib.patches.Rectangle((ip.iloc[i,0], ip.iloc[i,1]), ip.iloc[i,2], ip.iloc[i,3], color=np.random.rand(3))
    ax1.add_patch(part1)
    ax1.text(ip.iloc[i,0]+(0.5*ip.iloc[i,2]), (ip.iloc[i,1]+(0.5*ip.iloc[i,3])), ip.iloc[i,4], rotation='vertical', color='white', fontsize=8)

lower_ip = ip[ip['y'] < 300]
upper_ip = ip[ip['y'] >= 300]

xticks1 = list(lower_ip['x'] + lower_ip['width']) # select the right-side limit of each lower area
xticks1.extend(lower_ip['x'])                     # add the left-side limit of each lower area
xticks1 = set(xticks1)                            # filter by unique values
xticks1 = list(xticks1)                           # convert back to list
xticks1.sort()                                    # sort in increasing order

xticks2 = list(upper_ip['x'] + upper_ip['width']) # select the right-side limit of each upper area
xticks2.extend(upper_ip['x'])                     # add the left-side limit of each upper area
xticks2 = set(xticks2)                            # filter by unique values
xticks2 = list(xticks2)                           # convert back to list
xticks2.sort()                                    # sort in increasing order

# set equal min value for both axes
if xticks1[0] > xticks2[0]:
    xticks2.append(xticks1[0])
elif xticks1[0] < xticks2[0]:
    xticks1.append(xticks2[0])

# set equal max value for both axes
if xticks1[-1] > xticks2[-1]:
    xticks2.append(xticks1[-1])
elif xticks1[-1] < xticks2[-1]:
    xticks1.append(xticks2[-1])

# set lower and upper x ticks
ax1.set_xticks(xticks1)
ax2.set_xticks(xticks2)

yticks = list(ip['y'] + ip['height']) # select the down-side limit of each area
yticks.extend(ip['y'])                # add the up-side limit of each area
yticks = set(yticks)                  # filter by unique values
yticks = list(yticks)                 # convert back to list
yticks.sort()                         # sort in increasing order
ax1.set_yticks(yticks)                # set y ticks

ax1.set_xlim([min(ip['x']), max(ip['x']) + ip.iloc[np.argmax(ip['x']), ip.columns.get_loc('width')]])
ax1.set_ylim([min(ip['y']), max(ip['y']) + ip.iloc[np.argmax(ip['y']), ip.columns.get_loc('height')]])
plt.show()

Dataframe

     x    y  width  height  text
0    0    0    260     120   457
1  260    0    260     120   217
2  520    0    230     120   467
3    0  120    260     130   495
4  260  120    260     130   941
5  520  120    230     130   998
6    0  300    200     110    50
7  250  300    170     110   623
8  500  300    150     110   934
9    0  410    250     120   366

Result

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...