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

时间:2020-02-03 21:20:56

标签: python pandas matplotlib

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

所以,现在,我有X-Y值来绘制图形:

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

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

default plot rendering

因此,我试图限制垃圾箱的数量,因为我相信垃圾箱会散布在我所有的值上。但事实并非如此。如您所见,仅呈现前15个x值:

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

但没有人处于理想状态。期望状态应使此类x-bin的标签的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

1 个答案:

答案 0 :(得分:2)

您的问题已经分为两部分,但是我将回答这两个问题很有趣。

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

我将假定您具有以下两个数据数组:

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

通过计算差异可以轻松消除连续峰。布尔蒙版的差异将在蒙版更改感官的位置为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的数组索引,它们表示每个峰的第一个元素。通过交换[1::2]语句中的索引[::2]if-else,然后在两种情况下都删除+ 1,可以获取最后一个元素。

标签的位置现在仅为x[d]

第2部分:查找和设置标签格式

对于这一部分,您将需要通过正在绘制的Axes对象访问Matplotlib的面向对象的API。您已经以熊猫的形式拥有此商品,从而使转移变得容易。这是原始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