python - Pyplot - 根据 y 轴值显示 x 轴标签

标签 python pandas matplotlib

我有 1 分 20 秒长、23.813 FPS 的视频记录。更准确地说,我有 1923 个帧,我在其中扫描了所需的特征。我通过神经网络检测到了一些特定行为,并使用所选指标计算了每个帧的值。

现在,我有 X-Y 值来绘制图表:

X: time (each step of size 0,041993869s)
Y: a value measured by neural network

在默认状态下,绘图如下所示:

default plot rendering

因此,我尝试限制垃圾箱的数量,因为我相信这些垃圾箱将分布在我的所有值中。但他们不是。如您所见,仅呈现前十五个 x 值:

pyplot.locator_params(axis='x', nbins=15)

但两者都不是理想的状态。所需的状态应该渲染此类 x-bins 的标签,其 y 值高于例如1.2。所以,它应该看起来像这样:

desired state

有可能达到这样的结果吗?

代码:

# draw plot
from pandas import read_csv
from matplotlib import pyplot

test_video_fps = 23.813

df = read_csv('/path/to/csv/file/file.csv', header=None)
df.columns = ['anomaly']

df['time'] = [round((i + 1) / test_video_fps, 2) for i in range(df.shape[0])]

axes = df.plot.bar(x='time', y='anomaly', rot='0')
# pyplot.locator_params(axis='x', nbins=15)
# axes.get_xaxis().set_visible(False)

fig = pyplot.gcf()
fig.set_size_inches(16, 10)
fig.savefig('/path/to/output/plot.png', dpi=100)

# pyplot.show()

示例:

带有原始数据子集的简单示例。

0.379799
0.383786
0.345488
0.433286
0.469474
0.431993
0.474253
0.418843
0.491070
0.447778
0.384890
0.410994
0.898229
1.872756
2.907009
3.691382
4.685749
4.599612
3.738768
8.043357
7.660785
2.311198
1.956096
2.877326
3.467511
3.896339
4.250552
6.485533
7.452986
7.103761
2.684189
2.516134
1.512196
1.435303
0.852047
0.842551
0.957888
0.983085
0.990608
1.046679
1.082040
1.119655
0.962391
1.263255
1.371034
1.652812
2.160451
2.646674
1.460051
1.163745
0.938030
0.862976
0.734119
0.567076
0.417270

期望的情节:

desired plot of the example

最佳答案

你的问题已经变成了一个由两部分组成的问题,但它很有趣,所以我会回答这两部分。

我将用 Matplotlib 面向对象的表示法用 numpy 数据而不是 pandas 来回答这个问题。这将使事情更容易解释,并且可以轻松推广到 pandas。

我假设您有以下两个数据数组:

dt = 0.041993869
x = np.arange(0.0, 15 * dt, dt)
y = np.array([1., 1.1, 1.3, 7.6, 2.4, 0.8, 0.7, 0.8, 1.0, 1.5, 10.0, 4.5, 3.2, 0.9, 0.7])

第 1 部分:确定需要放置标签的位置

可以屏蔽数据以获得峰值的位置:

mask = y > 1.2

通过计算差异可以轻松消除连续峰值。 bool 掩码的 diff 在掩码改变意义的位置将为 True。然后,您必须获取所有其他元素来获取它从 FalseTrue 的位置。以下代码将捕获以峰值开始或以峰值中间结束的所有极端情况:

d = np.flatnonzero(np.diff(mask))
if mask[d[0]]:  # First diff is end of peak: True to False
    d = np.concatenate(([0], d[1::2] + 1))
else:
    d = d[::2] + 1

d 现在是 xy 的数组索引,表示每个峰的第一个元素。您可以通过交换 if-else 语句中的索引 [1::2][::2] 来获取最后一个元素,并在这两种情况下删除 + 1

标签的位置现在只是x[d]

第 2 部分:定位标签并设置其格式

对于这一部分,您将需要通过您正在绘制的 Axes 对象访问 Matplotlib 的面向对象 API。您已经以 pandas 形式获得了该文件,从而使传输变得容易。这是原始 Matplotlib 中的示例:

fig, axes = plt.subplots()
axes.plot(x, y)

现在使用ticker API轻松设置位置和标签。实际上,您可以直接设置位置(而不是使用 Locator),因为您有一个非常固定的刻度列表:

axes.set_xticks(x[d])
axes.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:0.01g}s'))

对于此处显示的示例数据,您将得到

enter image description here

关于python - Pyplot - 根据 y 轴值显示 x 轴标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60047328/

相关文章:

python - python在重叠和旋转的瓷砖中分割图像

python - 跳过每组中的前 n 行

python - 通过 Pandas Series 中的多个实例计算第一个非零值和最后一个非零值之间的差异?

python - 有没有一种简单的方法来扩展/完成 pandas DataFrame 以包含多列缺失的观察结果?

python - Matplotlib:子图中的插图

python - "Reset original view"不显示全貌

python - pandas 散点图与一天中时间的关系?

python - 实时 subprocess.Popen 通过 stdout 和 PIPE

python - 用装饰器替换宏样式的类方法?

python - 在python中的不规则网格上集成二维数据