我想通过python中的matplotlib创建一个“ ractangle-plot”。不幸的是我没有图像样本,所以我必须以最好的方式描述我的问题。
输入是具有不同时间增量和数字的df:
df = pd.DataFrame({'timedelta':[75,80,55,20,45],
'numb1':[8,25,11,14,8],
'timedelta1': [55,60,45,15,30],
'numb2':[10,30,15,18,10],
'timedelta2': [45,50,35,10,20]})
df['timedelta'] = pd.to_timedelta(df['timedelta'], unit='T')
df['timedelta1'] = pd.to_timedelta(df['timedelta1'], unit='T')
df['timedelta2'] = pd.to_timedelta(df['timedelta2'], unit='T')
输出:
timedelta numb1 timedelta1 numb2 timedelta2
0 01:15:00 8 00:55:00 10 00:45:00
1 01:20:00 25 01:00:00 30 00:50:00
2 00:55:00 11 00:45:00 15 00:35:00
3 00:20:00 14 00:15:00 18 00:10:00
4 00:45:00 8 00:30:00 10 00:20:00
现在,我想可视化此df。我想有一个矩形,其麻木向上,而timedelta朝右-每行都有一个新图。
例如row = 0:
rectangle (overall):
width = timedelta (=01:15:00)
hight = numb2 (=10)
在此矩形内-两个不同颜色的较小矩形(所有矩形应从左下角的同一点开始)
width1 = timedelta1
hight1 = numb1
width2 = timedelta2
hight2 = numb2
我还需要为轴(高度和宽度)和矩形添加标签。
编辑
使用以下代码,我设法创建了所需的矩形。
如何根据各个矩形(最好使用大括号)标记轴。我不需要这里的值,但需要使用的列的名称。
for row in df.index:
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])
p = patches.Rectangle((0,0), 1, 1, color= 'grey', alpha=0.2)
x1 = df['timedelta1'][row]/df['timedelta'][row]
y1 = df['numb1'][row]/df['numb2'][row]
p1 = patches.Rectangle((0,0), x1, y1, color= 'grey', alpha=0.8)
x2 = df['timedelta2'][row]/df['timedelta'][row]
y2 = df['numb2'][row]/df['numb2'][row]
p2 = patches.Rectangle((0,0), x2, y2, color= 'grey', alpha=0.5)
ax.add_patch(p)
ax.add_patch(p1)
ax.add_patch(p2)
ax.set_axis_off()
plt.show()
这是我以前的情节,现在我想用相应的列名(= timedelta/1/2
和numb1/2
(最好用大括号)标记每个矩形的宽度和高度>
答案 0 :(得分:1)
这是我的答案:
我唯一还没有做的就是以表格形式排列子图-例如fig, axes = plt.subplots(x,y)
...
df = pd.DataFrame({'timedelta':[75,80,55,20,45],
'numb1':[8,25,11,14,8],
'timedelta1': [55,60,45,15,30],
'numb2':[10,30,15,18,10],
'timedelta2': [45,50,35,10,20]})
n = len(df.index)
fig, axes = plt.subplots(n , figsize=(5,20))
for i, ax in enumerate(axes):
p = patches.Rectangle((0,0), 1, 1, color= 'grey', alpha=0.2)
x1 = df['timedelta1'][i]/df['timedelta'][i]
y1 = df['numb1'][i]/df['numb2'][i]
p1 = patches.Rectangle((0,0), x1, y1, color= 'grey', alpha=0.8)
x2 = df['timedelta2'][i]/df['timedelta'][i]
y2 = df['numb2'][i]/df['numb2'][i]
p2 = patches.Rectangle((0,0), x2, y2, color= 'grey', alpha=0.5)
ax.add_patch(p)
ax.add_patch(p1)
ax.add_patch(p2)
#td
pe_a = [0.0, -0.2]
pe_b = [1, -0.2]
#td1
pe_1a = [0.0, -0.1]
pe_1b = [x1, -0.1]
#td2
pe_2a = [0.0, 0.0]
pe_2b = [x2, 0.0]
# fontdict for curly bracket 1 text
font = {'family': 'serif',
'color': 'k',
'weight': 'bold',
'style': 'italic',
'size': 10,
}
# coefficient for curly
k_r1 = 0.02
# td - Brace
curlyBrace.curlyBrace(fig, ax, pe_b, pe_a, k_r1, bool_auto=True, str_text='td', color='black', lw=1, int_line_num=1, fontdict=font)
curlyBrace.curlyBrace(fig, ax, pe_1b, pe_1a, k_r1, bool_auto=True, str_text='td1', color='black', lw=1, int_line_num=1, fontdict=font)
curlyBrace.curlyBrace(fig, ax, pe_2b, pe_2a, k_r1, bool_auto=True, str_text='td2', color='black', lw=1, int_line_num=1, fontdict=font)
# numb1
h_1a = [0.0, y1]
h_1b = [0.0, 0,0]
# numb2
h_2a = [-0.1, y2]
h_2b = [-0.1, 0,0]
# numb - Brace
curlyBrace.curlyBrace(fig, ax, h_1b, h_1a, k_r1, bool_auto=True, str_text='numb1', color='black', lw=1, int_line_num=1, fontdict=font)
curlyBrace.curlyBrace(fig, ax, h_2b, h_2a, k_r1, bool_auto=True, str_text='numb2', color='black', lw=1, int_line_num=1, fontdict=font)
ax.set_axis_off()
ax.legend(bbox_to_anchor=(1.04,1), loc="upper left")
plt.tight_layout()
plt.show()
答案 1 :(得分:0)
这是我使用Matplotlib,Pandas和NumPy的解决方案:
首先我加载数据,但是我将时间增量保留为秒,并从最小到最大排序:
代码:
df = pd.DataFrame({'timedelta':[75,80,55,20,45],
'numb1':[8,25,11,14,8],
'timedelta1': [55,60,45,15,30],
'numb2':[10,30,15,18,10],
'timedelta2': [45,50,35,10,20]})
df = df.sort_values(by='timedelta')
df
运行该代码后,这里是df
:
timedelta numb1 timedelta1 numb2 timedelta2
3 20 14 15 18 10
4 45 8 30 10 20
2 55 11 45 15 35
0 75 8 55 10 45
1 80 25 60 30 50
下一步,我将定义辅助函数,以将秒转换为分钟格式(稍后在xtick标签中使用)
def minSec(sec):
minutes = int(sec/60)
remSec = int(sec - 60*minutes)
if (remSec == 0):
remSec = '00'
else:
remSec = str(remSec)
return str(minutes) + ':' + remSec
def minSec_arr(sec_arr):
output = []
for i in range(sec_arr.shape[0]):
output.append(minSec(sec_arr[i]))
return output
最后,我们遍历df
的所有行,并使用标签绘制适当的矩形图
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
# Create MULTIPLE figures
for i in range(df.shape[0]):
# Get initial data
row = df.iloc[i,:]
height = max(row.numb1, row.numb2)
width = row.timedelta
# Create figure
fig, ax = plt.subplots()
currentAxis = plt.gca()
# Set basic layout
plt.xlim(0, max(df.timedelta))
plt.ylim(0, max(df.numb2))
plt.title('Row ' + str(i))
plt.xlabel('Time [mm:ss]')
plt.ylabel('Number')
# Create proper x ticks
spaces = np.linspace(0, max(df.timedelta), 9)
vals = minSec_arr(spaces)
plt.xticks(spaces, vals)
# Create the main rectangle
currentAxis.add_patch(Rectangle((0, 0), width, height, fill=True, color='r', alpha=1, ec='k'))
axLabel = '(' + str(minSec(width)) + ',' + str(height) + ')'
plt.annotate(axLabel, (width,height))
# Create numb1 rectangle
width = row.timedelta1
height = row.numb1
currentAxis.add_patch(Rectangle((0, 0), width, height, fill=True, color='b', alpha=1, ec='k'))
axLabel = '(' + str(minSec(width)) + ',' + str(height) + ')'
plt.annotate(axLabel, (width,height))
# Create numb2 rectangle
width = row.timedelta2
height = row.numb2
currentAxis.add_patch(Rectangle((0, 0), width, height, fill=True, color='g', alpha=0.4, ec='k'))
axLabel = '(' + str(minSec(width)) + ',' + str(height) + ')'
plt.annotate(axLabel, (width,height))
plt.show()
希望我能完全理解您的问题