如何将数据类作为有效的索引值添加到绘图图中



我正试图从matplotlib熊猫绘图后端切换到plotly。然而,我被一个常见的错误所阻碍:

TypeError: Object of type Quarter is not JSON serializable

其中Quarter是我的代码库中的一个数据类。

对于一个最小的例子,请考虑:

@dataclass
class Foo:
val:int

df = pd.DataFrame({'x': [Foo(i) for i in range(10)], 'y':list(range(10))})
df.plot.scatter(x='x', y='y')

正如预期的那样,上述回报:

TypeError: Object of type Foo is not JSON serializable

现在,我不希望plotly是神奇的,但添加__float__神奇方法可以使Foo对象与matplotlib后端一起使用:

# This works
@dataclass
class Foo:
val:int

def __float__(self):
return float(self.val)

df = pd.DataFrame({'x': [Foo(i) for i in range(10)], 'y':list(range(10))})
df.plot.scatter(x='x', y='y')

如何更新我的dataclass以允许它与plotly后端一起使用?

在调用绘图后端之前,可以让pandas强制转换为float

from dataclasses import dataclass
import pandas as pd
@dataclass
class Foo:
val:int

def __float__(self):
return float(self.val)

df = pd.DataFrame({'x': [Foo(i) for i in range(10)], 'y':list(range(10))})
df["x"].astype(float)
pd.options.plotting.backend = "plotly"
df.assign(x=lambda d: d["x"].astype(float)).plot.scatter(x='x', y='y')

猴子补丁

  • 如果您不想更改代码,您可以对绘图实现熊猫绘图API进行monkey补丁
  • https://pandas.pydata.org/pandas-docs/stable/development/extending.html#plotting-后端
from dataclasses import dataclass
import pandas as pd
import wrapt, json
import plotly
@wrapt.patch_function_wrapper(plotly, 'plot')
def new_plot(wrapped, instance, args, kwargs):
try:
json.dumps(args[0][kwargs["x"]])
except TypeError:
args[0][kwargs["x"]] = args[0][kwargs["x"]].astype(float)
return wrapped(*args, **kwargs)


@dataclass
class Foo:
val:int

def __float__(self):
return float(self.val)

df = pd.DataFrame({'x': [Foo(i) for i in range(10)], 'y':list(range(10))})
df["x"].astype(float)
pd.options.plotting.backend = "plotly"
df.plot.scatter(x='x', y='y')

最新更新