用 pandas.plotting.parallel_coordinates 表示非数字(位置)排名的问题

Problems representing non-numerical (positional) rankings with pandas.plotting.parallel_coordinates

这个问题让我像一只无头鸡一样到处乱跑,时间比我想承认的要长。

我在数据框中有一个排名,格式如下(这是一个总结示例)

+---------+-------+-------+-------+-------+-------+--+
| ranking | Day 1 | Day 2 | Day 3 | Day 4 | Day 5 |  |
+---------+-------+-------+-------+-------+-------+--+
| 1       | adria | adria | marta | marta | adria |  |
+---------+-------+-------+-------+-------+-------+--+
| 2       | marta | marta | dani  | dani  | marta |  |
+---------+-------+-------+-------+-------+-------+--+
| 3       | dani  | dani  | adria | adria | dani  |  |
+---------+-------+-------+-------+-------+-------+--+
| 4       | abel  | abel  | abel  | abel  | abel  |  |
+---------+-------+-------+-------+-------+-------+--+
| 5       |       | joan  | joan  |       |       |  |
+---------+-------+-------+-------+-------+-------+--+

总之,有几个选手,排名上下浮动。最后还有一个球员(Joan)只打了两天就消失了

第一冲动是用pandas.plotting.parallel_coordinates(https://pandas.pydata.org/docs/reference/api/pandas.plotting.parallel_coordinates.html)

使用以下代码:

plt.figure(figsize = (20,5)) # Plot Width & Height
pd.plotting.parallel_coordinates(
  df, 'ranking',
  axvlines = False,
  marker='o', # Show marker
  markersize=12, #The Marker Size
  linewidth=6, # The Line Width
  alpha=0.9, # Opacity of lines
  )

plt.gca().invert_yaxis() # This inverts the Y aixs.
plt.legend('')
plt.style.use('fivethirtyeight') # This is the style
plt.show()

但结果完全不是预期的那样:

Link转为图片:link

请注意,我已经反转 Y 轴以显示上面的位置 #1

问题 1: 行不遵循 table 的顺序。如您所见,玩家“dani”永远不会排在第一位,但在表示中,您会看到它在排名中上升了两个位置,到达顶部。如果将 table 中的数据与可视化进行比较,您会发现其他玩家也发生了同样的事情。他们不遵循 table.

的位置

问题 2: 我不知道如何表示 Joan。这条线应该只代表他上场的日子。

问题 3: 这是一个非常简单的可视化,但假设我们有数百名玩家。这会使跟随颜色变得复杂。我想过把玩家的名字作为标签放在线条的每个点上,但一直没找到方法...

我的假设范围很广,从我没用的简单事实 (奥卡姆剃刀盛行),到无法使用此库以这种方式表示此数据。

我很想为此使用类似于桑基图的东西……但我认为这也不是我所需要的,而且它使代码变得非常复杂。

如果你能帮我解决这个问题,我将不胜感激,因为我真的已经到了尝试了很多次都没有解决问题的地步。

欢迎提出任何想法。

谢谢!

我不知道如何在 pandas 中执行此操作,但可以在 Altair if you first melt 您的 DataFrame 中执行类似的操作:

import altair as alt

alt.Chart(
    df.melt("ranking", var_name="day", value_name="player").dropna()
    , width=500
).mark_line(
    strokeWidth=5,
    opacity=0.5
).encode(
    alt.X('day:N', title=""),
    alt.Y('ranking:Q', scale=alt.Scale(domain=[1, 5], reverse=True)),
    color='player:N',
    tooltip='player:N',
)

这让你:

或者您可以向图中的每个点添加文本,例如:

import altair as alt

base = alt.Chart(
    df.melt("ranking", var_name="day", value_name="player").dropna()
    , width=500
).encode(
    alt.X('day:N', title=""),
    alt.Y('ranking:Q', scale=alt.Scale(domain=[1, 5], reverse=True)),
)

base.mark_line(
    strokeWidth=5,
    opacity=0.5
).encode(
    color='player:N',
    tooltip='player:N',
) + base.mark_text(
    fontSize=16
).encode(
    text='player:N'
)