Matplotlib:在两点之间绘制一条线......但以一种不寻常的方式

Posted

技术标签:

【中文标题】Matplotlib:在两点之间绘制一条线......但以一种不寻常的方式【英文标题】:Matplotlib: Plotting a line between 2 points...but in an unusual fashion 【发布时间】:2021-04-17 23:19:29 【问题描述】:

我正在学习使用 Matplotlib 可视化数据,并且我想以非常定制的方式绘制一条线。我是 Matplotlib 的新手,我不知道我想做的事情是否可行。如下:

设置:假设您有一组用于折线图的随机 (x,y) 点。出于说明目的,我将 4 个不同的折线图压缩成一个图,但想象一下,如果下面的 4 条线中的每一个都被分解成各自的图。

[![在此处输入图片描述][1]][1]

第 1 步)对于 A、B、C、D 线图中的每一个,求全局最大值并将其称为“X”。

第 4 步可能吗?)画一条连接“X”和“Y”的线。是否可以在 matplotlib 中绘制这条线?谢谢。

相关代码如下:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randn(50, 4), 
        index=pd.date_range('1/1/2000', periods=50), columns=list('ABCD'))
df = df.cumsum()
df.plot();

【问题讨论】:

能否包含您的数据和代码? 完成。不幸的是没有静态数据,它是随机生成的。 查看我对您问题的回答。显然有一百万种你可以格式化的东西,但如果我已经回答了你的问题,那么请接受作为解决方案。谢谢! 你对局部最大值的定义是在最大值之后的某个时间点发生的最高点吗?如果您正在寻找其他内容,请提供您将用于查找它的代码或方法。 ^^^ 如果这就是您要寻找的原因,那么很容易在与我当前答案具有相同结构的 pandas 数据框中得到它。我会在锻炼回来后更新我的答案。 【参考方案1】:

我认为需要定义您计算局部最大值的特定逻辑,而不仅仅是使用“时钟”隐喻,但是一旦您使用 scipipandas 或其他库定义了该逻辑,您就可以创建一个数据框为我有。从那里,您应该能够从下面生成结果。

如果您对seaborn(在matplotlib 之上构建)没问题,我认为这会容易一些,因为您可以传递hue 参数来为每个类别创建所有行行代码。您需要使用要绘制的这些 lines 创建一个新数据框。我通过对值进行排序并获取每组的尾值来做到这一点。请参阅下面的可重现示例。

示例 1(绘制局部最大值):

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import seaborn as sns
fig, ax = plt.subplots()
plt.style.use('classic')
df = pd.DataFrame(np.random.randn(50, 4), 
        index=pd.date_range('1/1/2000', periods=50), columns=list('ABCD'))
df = df.cumsum()
df = df.melt(ignore_index=False).reset_index()
sns.lineplot(data=df, x="index", y="value", hue="variable", ax=ax)
lines_max = (df.sort_values('value').groupby("variable").tail(1)).sort_values('variable')
lines_local_max = df[((df['variable'] == lines_max['variable'].iloc[0]) & (df['index'] > lines_max['index'].iloc[0]))
                | ((df['variable'] == lines_max['variable'].iloc[1]) & (df['index'] > lines_max['index'].iloc[1]))
                | ((df['variable'] == lines_max['variable'].iloc[2]) & (df['index'] > lines_max['index'].iloc[2]))
                | ((df['variable'] == lines_max['variable'].iloc[3]) & (df['index'] > lines_max['index'].iloc[3]))]
lines_local_max = (lines_local_max.sort_values(['variable', 'value']).groupby("variable").tail(1))
lines = lines_max.append(lines_local_max).sort_values('variable')
lines
sns.lineplot(data=lines, x="index", y="value", hue="variable", marker="o",
             style='variable', dashes=[(2, 2), (2, 2), (2, 2), (2, 2)], legend=False, ax=ax)
x_dates = pd.to_datetime(df['index'].unique())
plt.xticks(x_dates[0::7], rotation=45, ha='center')
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b-%d-%Y'))

示例 2(只是在末尾画一条线,而不是定义局部最大值 - 目的只是向您展示如何从最大点画一条线到另一个定义的点):

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
plt.style.use('classic')
fmri = sns.load_dataset("fmri")
fmri = fmri.groupby(['event', 'timepoint'], as_index=False)['signal'].mean()
sns.lineplot(data=fmri, x="timepoint", y="signal", hue="event")
lines_max = (fmri.sort_values('signal').groupby("event").tail(1))
lines_last = (fmri.sort_values('timepoint').groupby("event").tail(1))
lines = lines_max.append(lines_last)
sns.lineplot(data=lines, x="timepoint", y="signal", hue="event", marker="o", style='event', dashes=[(2, 2), (2, 2)])

示例 3(另一个示例使用您提供的数据绘制一条线,但未定义局部最大值 - 目的只是向您展示如何从最大点绘制一条线到另一个定义点):您提供的数据示例:

import pandas as pd
import numpy as np
fig, ax = plt.subplots()
df = pd.DataFrame(np.random.randn(50, 4), 
        index=pd.date_range('1/1/2000', periods=50), columns=list('ABCD'))
df = df.cumsum()
df = df.melt(ignore_index=False).reset_index()
sns.lineplot(data=df, x="index", y="value", hue="variable", ax=ax)
lines_max = (df.sort_values('value').groupby("variable").tail(1))
lines_last = (df.sort_values('index').groupby("variable").tail(1))
lines = lines_max.append(lines_last).sort_values('variable')
sns.lineplot(data=lines, x="index", y="value", hue="variable", marker="o",
             style='variable', dashes=[(2, 2), (2, 2), (2, 2), (2, 2)], legend=False, ax=ax)
x_dates = df['index'].dt.strftime('%Y-%m-%d').sort_values().unique()
ax.set_xticklabels(labels=x_dates, rotation=45, ha='center')

【讨论】:

@phan 我以为您对找出问题的matplotib 方面更感兴趣。有多种方法可以找到局部最大值,您可能会使用不同的方法,具体取决于数据和您要实现的其他任何目标。从这个答案 (***.com/questions/48023982/… ) 中,您可以使用投票最多的答案中的两种不同方法。这个问题是不完整的,没有显示计算局部最大值的尝试,以及对于有资格作为局部最大值的点,您想要的输出是什么。 嗯,我很想知道 Matplotlib 是否能够按照我描述的方式从 X 绘制到 Y。我只是不知道。如果答案是肯定的,我可以编写方法以达到局部最大值。我想要的输出只是用一条线连接点“X”和“Y”。让我再考虑一下,看看我是否可以生成用于确定点“Y”的代码 另外,感谢您的帮助。我对 Seaborn 一点也不熟悉,但我愿意去看看并学习它。 @phan 没问题(见第一个例子),但我猜这会给你你正在寻找的东西。我建议显示您尝试生成局部最大值的代码,而不是“时钟”示例和标题中的“但以不寻常的方式”。您需要通过示例输入和预期输出数据更清楚地定义不寻常的时尚,并通过代码展示您的尝试。 同意并完成!感谢您在回复中付出的时间、精力和关心。它们在帮助加快理解 Matplotlib 的道路上非常有帮助。另外,感谢您介绍 Seaborn。

以上是关于Matplotlib:在两点之间绘制一条线......但以一种不寻常的方式的主要内容,如果未能解决你的问题,请参考以下文章

使用jQuery在谷歌地图上的两点之间画一条线?

Python matplotlib - 如何在x轴上绘制一条线?

如何使用 matplotlib 在 3 维空间中绘制一条线

如何用 matplotlib 画一条线?

如何使用matplotlib在两条独立的图线上的标记之间绘制一条新线?

需要在网页上的两点之间画一条线