如何将数据类作为有效索引值添加到绘图图表中?
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')
猴子补丁
- 如果您不想更改代码,您可以猴子修补 plotly 实现 pandas 绘图 API
- https://pandas.pydata.org/pandas-docs/stable/development/extending.html#plotting-backends
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')
我正在尝试从 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')
猴子补丁
- 如果您不想更改代码,您可以猴子修补 plotly 实现 pandas 绘图 API
- https://pandas.pydata.org/pandas-docs/stable/development/extending.html#plotting-backends
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')