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

How do you add dataclasses as valid index values to a plotly chart?

我正在尝试从 matplotlib pandas 绘图后端切换到 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')

不出所料,上面的returns:

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')

猴子补丁

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')