Python matplotlib将df打印为矩形

Python matplotlib将df打印为矩形,python,pandas,dataframe,matplotlib,plot,Python,Pandas,Dataframe,Matplotlib,Plot,我想通过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'

我想通过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形象化。我想要一个长方形,NUMBE向上,TIMEDLTA向右-每一行都有一个新的绘图

例如,行=0:

rectangle (overall):
width  = timedelta (=01:15:00)
hight = numb2 (=10) 
在此矩形内-两个不同颜色的较小矩形(所有矩形应从左下角的同一点开始)

我还需要一个轴(高度和宽度)和矩形的标签

编辑

通过下面的代码,我成功地创建了所需的矩形

如何根据各个矩形标记轴(最好使用花括号)。我不需要这里的值,但需要使用的列的名称

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
)标记每个矩形的宽度和高度(最好用一个卷曲的括号)


以下是我使用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_值(按='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(秒):
分钟=整数(秒/60)
remSec=int(秒-60*分钟)
如果(remSec==0):
remSec='00'
其他:
remSec=str(remSec)
返回str(分钟)+':'+remSec
def minSec_arr(第二节arr):
输出=[]
对于范围内的i(截面阵列形状[0]):
输出追加(minSec(sec_arr[i]))
返回输出
最后,我们循环遍历
df
的所有行,并用标签绘制适当的矩形图

将熊猫作为pd导入
将matplotlib.pyplot作为plt导入
从matplotlib.patches导入矩形
将numpy作为np导入
#创建多个图形
对于范围内的i(df.shape[0]):
#获取初始数据
row=df.iloc[i,:]
高度=最大值(第1行,第2行)
宽度=row.timedelta
#塑造形象
图,ax=plt.子批次()
currentAxis=plt.gca()
#设置基本布局
plt.xlim(0,最大值(df.timedelta))
plt.ylim(0,最大值(测向2))
项目名称(行+街(一))
plt.xlabel('时间[mm:ss]”)
plt.ylabel('编号')
#创建正确的x记号
空格=np.linspace(0,最大值(df.timedelta),9)
VAL=minSec_arr(空格)
plt.xticks(空间、VAL)
#创建主矩形
currentAxis.add_patch(矩形((0,0),宽度,高度,填充=True,color='r',alpha=1,ec='k'))
axLabel='('+str(minSec(width))+','+str(height)+')
产品说明(axLabel,(宽度、高度))
#创建一个矩形
宽度=row.timedelta1
高度=第1行
currentAxis.add_patch(矩形((0,0),宽度,高度,填充=True,color='b',alpha=1,ec='k'))
axLabel='('+str(minSec(width))+','+str(height)+')
产品说明(axLabel,(宽度、高度))
#创建2个矩形
宽度=row.timedelta2
高度=第2行
currentAxis.add_patch(矩形((0,0),宽度,高度,填充=True,color='g',alpha=0.4,ec='k'))
axLabel='('+str(minSec(width))+','+str(height)+')
产品说明(axLabel,(宽度、高度))
plt.show()
这是一个示例输出图

我希望我完全理解了你的问题

以下是我的答案:

我唯一没有做的事情就是以类似表格的方式排列子图,比如
fig,axes=plt.subplot(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()

谢谢@Jacob的回答。这个不错,但不是我想要的。我已经在上面的问题中添加了到目前为止我已经实现的绘图,现在我想标记矩形边(宽度和高度),而不添加完整的轴标签(如您的示例中)。你能帮我吗?谢谢你的链接。我在创建花括号时发现了这一点:但在我的例子中,我不知道为轴设置什么-通过使用
ax[0]
我得到了一个“axes”对象不可下标的错误。这会起作用,但我宁愿使用花括号(类似于curlyBrace)代替轴标签,它标记每个矩形的高度和宽度。使用链接的示例代码,我得到了一个错误,我现在尝试按照您的指示操作,但是对于子图,我无法创建我的图。我还没来得及插上花括号……对不起,我无法根据你的提示调整我的for循环。到目前为止,我取得的最好结果是我的循环,我将其作为编辑附加到我的问题上。很好。关于子图的分布-在计算需要多少行和列后,如何从图形中删除未使用的
ax
元素
col=int(sqrt(len(df)/1.414))
为您提供了一个近似的A4布局。感谢您的帮助@T先生-现在我有了我的矩形:)
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()