Matplotlib:具有大误差条的循环角度图
Matplotlib: Cyclic angle plot with large error bars
这是我的问题:
_我有一些物理数据代表 -90 到 90 度之间的角度。此数据存在一个已知错误。我正在 python3 使用 numpy 和 matplotlib。
_我想为每个测量绘制数据及其误差线。角度范围从 -90 度到 90 度,误差不应超出这些范围。例如,对于 85+/-10 度的角度,我希望上方的误差线循环回到 -85 而不是回到 95。
_可能吗?如何?我正在尝试使用 $plt.fill_between()$ 或 $plt.errorbar()$,但它不起作用。在上面的示例中,即使我尝试将错误栏强制设置为 -85,错误也不会循环到 90...
这里有一些例子:
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(10) #time
a = np.linspace(50, 89, 10) #fake angle value
e = np.array([10]*10) #error value
a_up = a + e #Upper error bars
a_low = a - e #Lower error bars
f, ax = plt.subplots(nrows=2, ncols=2)
###Simple error graph, I don't want it because error bars outside of [-90, 90]
ax[0, 0].errorbar(t, a, yerr = e) #Plot the errors as error bars
### Same but with shaded area
ax[0, 1].fill_between(t, a_low, a_up) #Plot the errors as filled region
ax[0, 1].plot(t, a, "*r")
###My best option right now, put an upper limit everywhere
for i, u in enumerate(a_up):
if u > 90:
a_up[i] = 90
ax[1, 0].fill_between(t, a_low, a_up) #Plot the errors
ax[1, 0].plot(t, a, "*r")
###Finally, force all errorbars in [-90, 90] (Just for this exemple, it's generalized in my code)
for i, u in enumerate(a_up):
if u >= 90:
a_up[i] -= 90
ax[1, 1].fill_between(t, a_low, a_up) #Plot the errors
ax[1, 1].plot(t, a, "*r")
plt.show()
我希望我够清楚,我在网上找不到解决方案......也许我不知道如何制定它。
在此先感谢您的帮助,在使用您的答案 10 年后,我终于有机会提问了! :)
里奥
没有简单的方法可以做到这一点:
import matplotlib.pyplot as plt
angles = [30, 40, 50, -60, 10, 85, -85, 72, 2, 35]
errors = [2, 10, 10, 20, 4, 30, 30, 10, 12, 4]
x = [i for i, j in enumerate(angles)]
ls = dict()
for i, error, angle in zip(x, errors, angles):
if angle > 0 and abs(angle) + error > 90:
temp = angle + error - 90
ls.update({i:temp})
if angle < 0 and abs(angle) + error > 90:
temp = abs(angle) + error - 90
ls.update({i:temp})
plt.figure()
plt.ylim(-90, 90)
plt.errorbar(x, angles, yerr=errors, fmt='C0 ', marker='o')
# plt.errorbar(list(ls.keys()), [-90, 90], yerr=list(ls.values()), fmt='C0 ')
plt.vlines(list(ls.keys())[0], list(ls.values())[0] - 90, -90, colors='C0')
plt.vlines(list(ls.keys())[1], 90 - list(ls.values())[1], 90, colors='C0')
plt.ylabel('Angle')
plt.xlabel('Time (s)')
plt.show()
循环就是找出那些误差超过90度限制的角度。这样,您有两个选择:
# plt.errorbar(list(ls.keys()), [-90, 90], yerr=list(ls.values()), fmt='C0 ')
或
plt.vlines(list(ls.keys())[0], list(ls.values())[0] - 90, -90, colors='C0')
plt.vlines(list(ls.keys())[1], 90 - list(ls.values())[1], 90, colors='C0')
这意味着你必须手动添加垂直线,你可以写一个函数来做到这一点,但这是第一次尝试。顺便说一句,正如你所见,可视化效果不佳。
根据 David 的回答,我更改了一些内容,使其更通用:
import matplotlib.pyplot as plt
angles = [30, 40, 50, -60, 10, 85, -85, 72, 2, 35]
errors = [2, 10, 10, 40, 4, 30, 30, 10, 12, 4]
x = [i for i, j in enumerate(angles)]
ls = dict()
for i, error, angle in zip(x, errors, angles):
if angle > 0 and angle + error > 90:
temp = angle + error - 180
ls.update({i:[-90, temp]})
if angle < 0 and angle - error < -90:
temp = angle - error + 180
ls.update({i:[90, temp]})
plt.figure()
plt.ylim(-90, 90)
plt.errorbar(x, angles, yerr=errors, fmt='C0 ', marker='o')
# plt.errorbar(list(ls.keys()), [-90, 90], yerr=list(ls.values()), fmt='C0 ')
for i, a in ls.items():
plt.vlines(i, a[0], a[1], colors='C0')
plt.ylabel('Angle')
plt.xlabel('Time (s)')
plt.show()
它可能没有优化,但对我来说效果很好:)
再次坦克!
这是我的问题:
_我有一些物理数据代表 -90 到 90 度之间的角度。此数据存在一个已知错误。我正在 python3 使用 numpy 和 matplotlib。
_我想为每个测量绘制数据及其误差线。角度范围从 -90 度到 90 度,误差不应超出这些范围。例如,对于 85+/-10 度的角度,我希望上方的误差线循环回到 -85 而不是回到 95。
_可能吗?如何?我正在尝试使用 $plt.fill_between()$ 或 $plt.errorbar()$,但它不起作用。在上面的示例中,即使我尝试将错误栏强制设置为 -85,错误也不会循环到 90...
这里有一些例子:
import matplotlib.pyplot as plt
import numpy as np
t = np.arange(10) #time
a = np.linspace(50, 89, 10) #fake angle value
e = np.array([10]*10) #error value
a_up = a + e #Upper error bars
a_low = a - e #Lower error bars
f, ax = plt.subplots(nrows=2, ncols=2)
###Simple error graph, I don't want it because error bars outside of [-90, 90]
ax[0, 0].errorbar(t, a, yerr = e) #Plot the errors as error bars
### Same but with shaded area
ax[0, 1].fill_between(t, a_low, a_up) #Plot the errors as filled region
ax[0, 1].plot(t, a, "*r")
###My best option right now, put an upper limit everywhere
for i, u in enumerate(a_up):
if u > 90:
a_up[i] = 90
ax[1, 0].fill_between(t, a_low, a_up) #Plot the errors
ax[1, 0].plot(t, a, "*r")
###Finally, force all errorbars in [-90, 90] (Just for this exemple, it's generalized in my code)
for i, u in enumerate(a_up):
if u >= 90:
a_up[i] -= 90
ax[1, 1].fill_between(t, a_low, a_up) #Plot the errors
ax[1, 1].plot(t, a, "*r")
plt.show()
我希望我够清楚,我在网上找不到解决方案......也许我不知道如何制定它。
在此先感谢您的帮助,在使用您的答案 10 年后,我终于有机会提问了! :)
里奥
没有简单的方法可以做到这一点:
import matplotlib.pyplot as plt
angles = [30, 40, 50, -60, 10, 85, -85, 72, 2, 35]
errors = [2, 10, 10, 20, 4, 30, 30, 10, 12, 4]
x = [i for i, j in enumerate(angles)]
ls = dict()
for i, error, angle in zip(x, errors, angles):
if angle > 0 and abs(angle) + error > 90:
temp = angle + error - 90
ls.update({i:temp})
if angle < 0 and abs(angle) + error > 90:
temp = abs(angle) + error - 90
ls.update({i:temp})
plt.figure()
plt.ylim(-90, 90)
plt.errorbar(x, angles, yerr=errors, fmt='C0 ', marker='o')
# plt.errorbar(list(ls.keys()), [-90, 90], yerr=list(ls.values()), fmt='C0 ')
plt.vlines(list(ls.keys())[0], list(ls.values())[0] - 90, -90, colors='C0')
plt.vlines(list(ls.keys())[1], 90 - list(ls.values())[1], 90, colors='C0')
plt.ylabel('Angle')
plt.xlabel('Time (s)')
plt.show()
循环就是找出那些误差超过90度限制的角度。这样,您有两个选择:
# plt.errorbar(list(ls.keys()), [-90, 90], yerr=list(ls.values()), fmt='C0 ')
或
plt.vlines(list(ls.keys())[0], list(ls.values())[0] - 90, -90, colors='C0')
plt.vlines(list(ls.keys())[1], 90 - list(ls.values())[1], 90, colors='C0')
这意味着你必须手动添加垂直线,你可以写一个函数来做到这一点,但这是第一次尝试。顺便说一句,正如你所见,可视化效果不佳。
根据 David 的回答,我更改了一些内容,使其更通用:
import matplotlib.pyplot as plt
angles = [30, 40, 50, -60, 10, 85, -85, 72, 2, 35]
errors = [2, 10, 10, 40, 4, 30, 30, 10, 12, 4]
x = [i for i, j in enumerate(angles)]
ls = dict()
for i, error, angle in zip(x, errors, angles):
if angle > 0 and angle + error > 90:
temp = angle + error - 180
ls.update({i:[-90, temp]})
if angle < 0 and angle - error < -90:
temp = angle - error + 180
ls.update({i:[90, temp]})
plt.figure()
plt.ylim(-90, 90)
plt.errorbar(x, angles, yerr=errors, fmt='C0 ', marker='o')
# plt.errorbar(list(ls.keys()), [-90, 90], yerr=list(ls.values()), fmt='C0 ')
for i, a in ls.items():
plt.vlines(i, a[0], a[1], colors='C0')
plt.ylabel('Angle')
plt.xlabel('Time (s)')
plt.show()
它可能没有优化,但对我来说效果很好:) 再次坦克!