下面的代码示例绘制了一个虚线Barh图,其中包含在一段时间内加入和离开音乐乐队的人员列表:

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

result = pd.DataFrame([['Bill', 1972, 1974],
                       ['Bill', 1976, 1978],
                       ['Bill', 1967, 1971],
                       ['Danny', 1969, 1975],
                       ['Danny', 1976, 1977],
                       ['James', 1971, 1972],
                       ['Marshall', 1967, 1975]],
                      columns=['Person', 'Year_start', 'Year_left'])

fig, ax = plt.subplots()

names = sorted(result['Person'].unique())

colormap = plt.get_cmap('plasma')
slicedColorMap = colormap(np.linspace(0, 1, len(names)))

height = 0.5
for y, (name, g) in enumerate(result.groupby('Person')):
    ax.broken_barh(list(zip(g['Year_start'],
                            g['Year_left']-g['Year_start'])),
                   (y-height/2, height),
                   facecolors=slicedColorMap[y]
                   )

ax.set_ylim(0-height, len(names)-1+height)
ax.set_xlim(result['Year_start'].min()-1, result['Year_left'].max()+1)
ax.set_yticks(range(len(names)), names)

ax.grid(True)
plt.show()

The output result is this diagram: enter image description here

我需要按‘Year_Start’和‘Year_Left’对条形图(以及y轴上的人员)进行排序,两者都是按升序排列的.

我知道如何在数据分组后对DataFrame中的值进行聚合和排序,并且应该在之后重置索引:

sorted_result = result.groupby('Person').agg({'Year_start': min, 'Year_left': max})
sorted_result = sorted_result.sort_values(['Year_start', 'Year_left'], ascending=[True, True]).reset_index()
print(sorted_result)

但是,在绘制ax.rupt_barh时,我很难将这种排序嵌入到现有的"for in"循环中(正如我所理解的,这也是因为不可能在单个迭代中使用"agg"使用"groupby"来执行"sortValues"). 在这个脚本中是否可以进行这种排序,或者我应该完全重新考虑脚本 struct ? 非常感谢!

推荐答案

IIIC,您所需要做的就是在使用groupby()时使用sort=False,并且以前以您想要的方式对数据帧进行排序.代码的其余部分可以保持不变:

编辑:然而,由于排序是非常具体的,并且不容易在sort_values()中涵盖,我建议在外部数据帧中进行,然后将其合并回原始数据帧以进行排序.

result = pd.DataFrame([['Bill', 1972, 1974],
                       ['Bill', 1976, 1978],
                       ['Bill', 1967, 1971],
                       ['Danny', 1969, 1975],
                       ['Danny', 1976, 1977],
                       ['James', 1971, 1972],
                       ['Marshall', 1967, 1975]],
                      columns=['Person', 'Year_start', 'Year_left'])

sorter = result.groupby('Person').agg({'Year_start':'min','Year_left':'max'})\
    .sort_values(['Year_start','Year_left'],
                 ascending=[True,True])\
        .index.to_frame().\
            assign(sorter = range(result['Person'].nunique()))\
                .set_index('Person').to_dict()['sorter']
                                                               
result['sorter'] = result['Person'].map(sorter)
result = result.sort_values('sorter',ascending=True)

fig, ax = plt.subplots()

colormap = plt.get_cmap('plasma')
slicedColorMap = colormap(np.linspace(0, 1, result['Person'].nunique()))

height = 0.5
names = []
for y, (name, g) in enumerate(result.groupby('Person',sort=False)): #Here I'm using sort=False to avoid groupby from sorting it differently
    print(name)
    ax.broken_barh(list(zip(g['Year_start'],
                            g['Year_left']-g['Year_start'])),
                   (y-height/2, height),
                   facecolors=slicedColorMap[y]
                   )
    names.append(name)

代码的其余部分保持不变.这会产生以下结果:

我还做了一个小小的改进,不是静态地定义names,稍后将传递它,而是在循环经过时创建列表,以便名称始终与栏匹配.这就是为什么我也使用result['Person'].nunique()而不是len(names)

编辑:根据与OP的讨论编辑代码 [1]:https://i.stack.imgur.com/6epWQ.png

Python相关问答推荐

在Windows上启动新Python项目的正确步骤顺序

如何将Matplotlib的fig.add_axes本地坐标与我的坐标关联起来?

如何防止Plotly在输出到PDF时减少行中的点数?

根据网格和相机参数渲染深度

根据给定日期的状态过滤查询集

如何根据日期和时间将状态更新为已过期或活动?

使用plotnine和Python构建地块

试图找到Python方法来部分填充numpy数组

如何在箱形图中添加绘制线的传奇?

Python上的Instagram API:缺少client_id参数"

查找两极rame中组之间的所有差异

不理解Value错误:在Python中使用迭代对象设置时必须具有相等的len键和值

基于字符串匹配条件合并两个帧

"使用odbc_connect(raw)连接字符串登录失败;可用于pyodbc"

Godot:需要碰撞的对象的AdditionerBody2D或Area2D以及queue_free?

mypy无法推断类型参数.List和Iterable的区别

在www.example.com中使用`package_data`包含不包含__init__. py的非Python文件

如何在Python请求中组合多个适配器?

一个telegram 机器人应该发送一个测验如何做?""

Python将一个列值分割成多个列,并保持其余列相同