Python Matplotlib 从以 mW 为单位的数据创建箱线图,以 dBm 为单位绘制
Python Matplotlib create boxplot from data in mW, plot in dBm
我有一组数据,其中包含以 mW 为单位的 RSSI 值和设备标签。请参阅下面的示例数据。
我的目标是创建一个按设备标签分组的平均 RSSI 箱线图,但我希望它以对数 dBm 刻度而不是线性 mW 刻度打印。
我有一个转换函数:
def toDeciBellMilliWatt(RSSI):
"""Returns RSSI value in dBm, assuming input is mW"""
return 10*math.log10(RSSI)
并且此调用可以创建 boxplots(请注意,我关注这些是因为方框和胡须显示分位数,我不关注绘图)我需要:
data.boxplot(column='RSSI', by='label')
但我希望 y 轴以 dBm 为单位。在对箱线图的调用计算完所有分位数后,有没有办法直接实现这一点?不知道从哪里开始
示例数据:
data = pd.DataFrame(columns=['label', 'RSSI'],
data=[['A', 1.99e-7],
['B', 1.25e-9],
['A', 1.99e-5],
['A', 3.16e-7],
['B', 3.16e-5],
['A', 1.99e-7],
['B', 3.91e-9],
['A', 1.99e-5],
['A', 3.14e-7],
['B', 3.16e-5]])
编辑 以避免混淆:转换为 dBm 的 mW 值的平均值不等于 dBm 值的平均值。这在纸上很容易证明,这是因为 dBm 是对数刻度,而 mW 不是。
当使用以 mW 为单位的箱线图计算统计值时,我们得到信号的 "correct" 功率平均值。现在,我缺少以 dBm 显示它的部分,以便技术人员能够理解它。
我可以自己计算所有值,然后根据我的计算组装箱线图。我所追求的是将Matplotlib创建的整个箱线图的y轴的度量单位转换为对数刻度的解决方案。
一种方法是先通过 pandas 绘制箱线图,然后将 y 轴设置为对数并更改刻度的格式。您可以删除小刻度线,因为它们会与新的刻度线标签混淆。
import math
import pandas as pd
from matplotlib import pyplot as plt
def toDeciBellMilliWatt(RSSI):
"""Returns RSSI value in dBm, assuming input is mW"""
return 10 * math.log10(RSSI)
def format_dBm(value, tick_number):
return '–' + str(round(-toDeciBellMilliWatt(value)))
data = pd.DataFrame(columns=['label', 'RSSI'],
data=[['A', 1.99e-7],
['B', 1.25e-9],
['A', 1.99e-5],
['A', 3.16e-7],
['B', 3.16e-5],
['A', 1.99e-7],
['B', 3.91e-9],
['A', 1.99e-5],
['A', 3.14e-7],
['B', 3.16e-5]])
fig, axes = plt.subplots(ncols=2, figsize=(10, 4))
for ax in axes:
data.boxplot(column='RSSI', by='label', ax=ax)
plt.subplots_adjust(wspace=0.25)
plt.yscale('log')
plt.minorticks_off()
axes[1].yaxis.set_major_formatter(plt.FuncFormatter(format_dBm))
plt.ylabel('RSSI (in dBm)')
plt.show()
左边是原始箱线图,中间是 dBm 的 y 刻度标签,右边是对数刻度的版本。由于该对数刻度,箱线图改变了其视觉方面。
我有一组数据,其中包含以 mW 为单位的 RSSI 值和设备标签。请参阅下面的示例数据。
我的目标是创建一个按设备标签分组的平均 RSSI 箱线图,但我希望它以对数 dBm 刻度而不是线性 mW 刻度打印。
我有一个转换函数:
def toDeciBellMilliWatt(RSSI):
"""Returns RSSI value in dBm, assuming input is mW"""
return 10*math.log10(RSSI)
并且此调用可以创建 boxplots(请注意,我关注这些是因为方框和胡须显示分位数,我不关注绘图)我需要:
data.boxplot(column='RSSI', by='label')
但我希望 y 轴以 dBm 为单位。在对箱线图的调用计算完所有分位数后,有没有办法直接实现这一点?不知道从哪里开始
示例数据:
data = pd.DataFrame(columns=['label', 'RSSI'],
data=[['A', 1.99e-7],
['B', 1.25e-9],
['A', 1.99e-5],
['A', 3.16e-7],
['B', 3.16e-5],
['A', 1.99e-7],
['B', 3.91e-9],
['A', 1.99e-5],
['A', 3.14e-7],
['B', 3.16e-5]])
编辑 以避免混淆:转换为 dBm 的 mW 值的平均值不等于 dBm 值的平均值。这在纸上很容易证明,这是因为 dBm 是对数刻度,而 mW 不是。
当使用以 mW 为单位的箱线图计算统计值时,我们得到信号的 "correct" 功率平均值。现在,我缺少以 dBm 显示它的部分,以便技术人员能够理解它。
我可以自己计算所有值,然后根据我的计算组装箱线图。我所追求的是将Matplotlib创建的整个箱线图的y轴的度量单位转换为对数刻度的解决方案。
一种方法是先通过 pandas 绘制箱线图,然后将 y 轴设置为对数并更改刻度的格式。您可以删除小刻度线,因为它们会与新的刻度线标签混淆。
import math
import pandas as pd
from matplotlib import pyplot as plt
def toDeciBellMilliWatt(RSSI):
"""Returns RSSI value in dBm, assuming input is mW"""
return 10 * math.log10(RSSI)
def format_dBm(value, tick_number):
return '–' + str(round(-toDeciBellMilliWatt(value)))
data = pd.DataFrame(columns=['label', 'RSSI'],
data=[['A', 1.99e-7],
['B', 1.25e-9],
['A', 1.99e-5],
['A', 3.16e-7],
['B', 3.16e-5],
['A', 1.99e-7],
['B', 3.91e-9],
['A', 1.99e-5],
['A', 3.14e-7],
['B', 3.16e-5]])
fig, axes = plt.subplots(ncols=2, figsize=(10, 4))
for ax in axes:
data.boxplot(column='RSSI', by='label', ax=ax)
plt.subplots_adjust(wspace=0.25)
plt.yscale('log')
plt.minorticks_off()
axes[1].yaxis.set_major_formatter(plt.FuncFormatter(format_dBm))
plt.ylabel('RSSI (in dBm)')
plt.show()
左边是原始箱线图,中间是 dBm 的 y 刻度标签,右边是对数刻度的版本。由于该对数刻度,箱线图改变了其视觉方面。