gpt4 book ai didi

matplotlib - 我可以使用 matplotlib.units 在图表上显示的单位之间切换吗?

转载 作者:行者123 更新时间:2023-12-04 08:35:15 26 4
gpt4 key购买 nike

我正在使用 matplotlib 在桌面应用程序中渲染图形,我对 matplotlib 对单位的支持有点困惑。我想让用户更改图表 x 轴上显示的单位:所有计算都将以纳米为单位进行,但图表可以以纳米或千兆赫为单位显示。 (请注意,这两个单位之间存在反向而非线性关系。)

有两种明显的方法可以做到这一点:“手动”或使用 matplotlib。在前一种情况下,matplotlib 对单位一无所知;当用户更改单位时,我只需重新计算所有数据点,更改轴的边界和标签,并告诉 matplotlib 重绘。但我希望 matplotlib 有内置功能来做同样的事情。

有一些light documentation about matplotlib.units ,但据我所知,这是用于绘制用户指定对象的数组,而不是浮点数组。我的数据实际上是一个浮点数组,由于每个图有数十万个数据点,我无法将每个值包装在一些自定义模型类中。 (甚至 this simple example 将每个数据点包装在模型类中,整个示例非常通用,我不知道如何根据需要对其进行调整。)无论如何,原始数据点始终具有相同的单位,因此这些值只需要转换为另一个单位。

如何告诉 matplotlib 我的单位,然后使用 axes.set_xunit或者他们之间有什么改变?

最佳答案

尝试使用函数而不是浮点数进行转换

下面的例子可以作为一个开始。千兆赫GHzper nanosecondnm^-1per nano meter , 所以这个例子会给出 nm^-1我猜。

我拿了 mpl 模型并做了三个改编:

支持可调用函数进行转换

def value( self, unit ):
if callable(unit): # To handle a callable function for conversion
return unit(self._val)
...

定义转换函数
one_by_x = lambda x: 1 / x if x != 0 else 0
....

交上来
ax.plot( x, y, 'o', xunits=one_by_x )
....
ax.set_title("xunits = 1/x")

您定义一些函数并使用适当的函数重新绘制。
或者 - 为复杂起见 - 甚至添加另一个参数并同时拥有:恒定比例因子加函数。

来自 http://matplotlib.org/examples/units/evans_test.html 的整个改编示例:
"""
A mockup "Foo" units class which supports
conversion and different tick formatting depending on the "unit".
Here the "unit" is just a scalar conversion factor, but this example shows mpl is
entirely agnostic to what kind of units client packages use
"""
from matplotlib.cbook import iterable
import matplotlib.units as units
import matplotlib.ticker as ticker
import matplotlib.pyplot as plt


class Foo:
def __init__( self, val, unit=1.0 ):
self.unit = unit
self._val = val * unit

def value( self, unit ):
if callable(unit):
return unit(self._val)
if unit is None: unit = self.unit
return self._val / unit

class FooConverter:

@staticmethod
def axisinfo(unit, axis):
'return the Foo AxisInfo'
if unit==1.0 or unit==2.0:
return units.AxisInfo(
majloc = ticker.IndexLocator( 8, 0 ),
majfmt = ticker.FormatStrFormatter("VAL: %s"),
label='foo',
)

else:
return None

@staticmethod
def convert(obj, unit, axis):
"""
convert obj using unit. If obj is a sequence, return the
converted sequence
"""
if units.ConversionInterface.is_numlike(obj):
return obj

if iterable(obj):
return [o.value(unit) for o in obj]
else:
return obj.value(unit)

@staticmethod
def default_units(x, axis):
'return the default unit for x or None'
if iterable(x):
for thisx in x:
return thisx.unit
else:
return x.unit

units.registry[Foo] = FooConverter()

# create some Foos
x = []
for val in range( 0, 50, 2 ):
x.append( Foo( val, 1.0 ) )

# and some arbitrary y data
y = [i for i in range( len(x) ) ]

one_by_x = lambda x: 1 / x if x != 0 else 0
# plot specifying units
fig = plt.figure()
fig.suptitle("Custom units")
fig.subplots_adjust(bottom=0.2)
ax = fig.add_subplot(1,2,2)
ax.plot( x, y, 'o', xunits=one_by_x )
for label in ax.get_xticklabels():
label.set_rotation(30)
label.set_ha('right')
ax.set_title("xunits = 1/x")


# plot without specifying units; will use the None branch for axisinfo
ax = fig.add_subplot(1,2,1)
ax.plot( x, y ) # uses default units
ax.set_title('default units')
for label in ax.get_xticklabels():
label.set_rotation(30)
label.set_ha('right')

plt.show()

关于matplotlib - 我可以使用 matplotlib.units 在图表上显示的单位之间切换吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21271195/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com