我正试图从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')