СЛУЧАЙ 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
Результат
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
введите описание изображения здесь