简体   繁体   English

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

[英]Pyplot - show x-axis labels according to y-axis value

I have 1min 20s long video record of 23.813 FPS.我有 23.813 FPS 的 1 分钟 20 秒长视频记录。 More precisely, I have 1923 frames in which I've been scanning desired features.更准确地说,我有 1923 帧,其中我一直在扫描所需的特征。 I've detected some specific behavior via neural network and using chosen metric I calculated a value for each frame.我通过神经网络检测到了一些特定的行为,并使用选定的指标为每一帧计算了一个值。

So, now, I have XY values to plot a graph:所以,现在,我有 XY 值来绘制图形:

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

In the default state, the plot looks like this:在默认状态下,绘图如下所示:

默认绘图渲染

So, I've tried to limit the number of bins in the faith that the bins will be spread over all my values.所以,我试图限制垃圾箱的数量,相信垃圾箱将分布在我的所有价值观上。 But they are not.但他们不是。 As you can see, only first fifteen x-values are rendered:如您所见,仅呈现前十五个 x 值:

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

But neither one is desired state.但两者都不是理想状态。 The desired state should render the labels of such x-bins with y-value higher than eg 1.2 .所需的状态应该呈现这样的 x-bins 的标签,其 y 值高于例如1.2 So, it should look like this:所以,它应该是这样的:

理想状态

Is possible to achieve such result?有可能达到这样的结果吗?

Code:代码:

# 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()

Example:例子:

Simple example with a subset of original data.带有原始数据子集的简单示例。

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:想要的剧情:

所需的示例图

Your question has become a two-part problem, but it is interesting enough that I will answer both.你的问题已经变成了一个由两部分组成的问题,但很有趣,我会同时回答这两部分。

I will answer this in Matplotlib object oriented notation with numpy data rather than pandas.我将在 Matplotlib 面向对象的符号中使用 numpy 数据而不是 Pandas 来回答这个问题。 This will make things easier to explain, and can be easily generalized to pandas.这将使事情更容易解释,并且可以很容易地推广到熊猫。

I will assume that you have the following two data arrays:我假设您有以下两个数据数组:

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])

Part 1: Identifying the locations where you want labels第 1 部分:确定要放置标签的位置

The data can be masked to get the locations of the peaks:可以屏蔽数据以获得峰值的位置:

mask = y > 1.2

Consecutive peaks can be easily eliminated by computing the diff.通过计算差异可以轻松消除连续的峰值。 A diff of a boolean mask will be True at the locations where the mask changes sense.在掩码改变意义的位置,布尔掩码的差异将为True You will then have to take every other element to get the locations where it goes from False to True .然后,您将不得不采用其他所有元素来获取它从FalseTrue The following code will capture all the corner cases where you start with a peak or end in the middle of a peak:以下代码将捕获从峰值开始或在峰值中间结束的所有极端情况:

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 is now an array indices into x and y that represent the first element of each run of peaks. d现在是xy的数组索引,表示每次峰值运行的第一个元素。 You can get the last element by swapping the indices [1::2] and [::2] in the if-else statement, and removing the + 1 in both cases.您可以通过交换if-else语句中的索引[1::2][::2]来获取最后一个元素,并在两种情况下都删除+ 1

The locations of the labels are now simply x[d] .标签的位置现在只是x[d]

Part 2: Locating and formatting the labels第 2 部分:定位和格式化标签

For this part, you will need to access Matplotlib's object oriented API via the Axes object you are plotting on.对于这部分,您需要通过您正在绘图的Axes对象访问 Matplotlib 的面向对象的 API。 You already have this in the pandas form, making the transfer easy.您已经在 Pandas 形式中拥有了它,从而使传输变得容易。 Here is a sample in raw Matplotlib:这是原始 Matplotlib 中的示例:

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

Now use the ticker API to easily set the locations and labels.现在使用股票代码 API轻松设置位置和标签。 You actually set the locations directly (not with a Locator ) since you have a very fixed list of ticks:您实际上直接设置了位置(而不是使用Locator ),因为您有一个非常固定的刻度列表:

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

For the sample data show here, you get对于此处显示的示例数据,您将获得

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 3D图形显示错误的轴标签(X轴具有Y轴名称,Y轴具有X轴名称) - 3D Plot show wrong axis labels (X-axis has Y-axis name and Y-axis has X-axis name) 如何更改 plotly 中的 x 轴和 y 轴标签? - How to change the x-axis and y-axis labels in plotly? 使用正确的标签将值从 x 轴切换到 y 轴(Python Matplotlib.pyplot 或 Seaborn) - Switch the values from x-axis to y-axis while using the correct labels(Python Matplotlib.pyplot OR Seaborn) x轴和y轴的设置值 - Setting value for x-axis and y-axis 如何用pyplot在相同的x轴(日期时间)但不同的y轴上绘制线形图和条形图? - How to plot line and bar-chart on the same x-axis (datetime) but different y-axis with pyplot? 删除pyplot中重叠的x轴标签 - Removing overlapping x-axis labels in pyplot 在pyplot中更改x轴标签的增量 - Altering increment for x-axis labels in pyplot 根据不同子图的y轴更新matplotlib子图的x轴 - Update the x-axis of a matplotlib subplot according to the y-axis of a different subplot 如何使用python在x轴或y轴标签之间添加更多刻度? - How can I add more ticks between x-axis or y-axis labels using python? 在 matplotlib 中使用两个 y 轴格式化 x 轴标签(条形图和折线图) - formatting x-axis labels with two y-axis in matplotlib (bar and line plot)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM