この記事に書いた現象は、bokeh3.1では発生しません。
環境
- Python 3.10.2
- bokeh 3.0.3
- pandas 1.5.3
背景
string型の列を持つpandas.DataFrame
を使って、bokehでグラフを描画したいです。
sample.py
from bokeh.plotting import ColumnDataSource, figure, output_file, show
import pandas
output_file("toolbar.html")
data = dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
desc=["A", "b", "C", "d", "E"],
)
df = pandas.DataFrame(data)
# `desc`列のdtypeをobjectからstringに変換
df["desc"] = df["desc"].astype("string")
source = ColumnDataSource(data=df)
TOOLTIPS = [
("desc", "@desc"),
]
p = figure(tooltips=TOOLTIPS)
p.circle("x", "y", size=20, source=source)
show(p)
起きたこと
bokeh 3.0.3で以下のコードを実行すると、SerializationError
エラーが発生しました。
Traceback (most recent call last):
File "/home/vagrant/Documents/study/20230219/sample.py", line 24, in <module>
show(p)
...
File "/home/vagrant/Documents/study/20230219/.venv/lib/python3.10/site-packages/bokeh/core/serialization.py", line 461, in error
raise SerializationError(message)
bokeh.core.serialization.SerializationError: can't serialize <class 'pandas.core.arrays.string_.StringArray'>
ただし bokeh 2.4.3で実行するとエラーは発生せずに、グラフは期待通り描画されました。
原因
原因は分かりませんでした。
bokehのMigration Guidesによると、3.0.0からpanadsに依存するようになったようです。もしかしたら、これに関係しているのかもしれません。
Bokeh now requires pandas.
Githubにissueを作ったので、返信待ちです。
追記
PullRequestがマージされました。bokeh3.1で解決されました。
https://github.com/bokeh/bokeh/pull/12841
補足
pandas.NA
を含むDataFrameも描画できない
output_file("toolbar.html")
data = dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
desc=["A", "b", "C", "d", "E"],
)
df = pandas.DataFrame(data)
df["desc"][4] = pandas.NA
print(df["desc"])
# 0 A
# 1 b
# 2 C
# 3 d
# 4 <NA>
# Name: desc, dtype: object
source = ColumnDataSource(data=df)
TOOLTIPS = [
("desc", "@desc"),
]
p = figure(tooltips=TOOLTIPS)
p.circle("x", "y", size=20, source=source)
show(p)
desc
列のdtypeがobject
でもpandas.NA
を含むと、SerializationError
が発生します。
bokeh.core.serialization.SerializationError: can't serialize <class 'pandas._libs.missing.NAType'>
Int64
型の列を含むDataFrameも描画できない
output_file("sample.html")
x = pandas.Series([1, 2, 3, 4, 5], dtype="Int64")
y = pandas.Series([2, 5, 8, 2, 3], dtype="Int64")
df = pandas.DataFrame({"x": x, "y": y})
print(df)
# x y
# 0 1 2
# 1 2 5
# 2 3 8
# 3 4 2
# 4 5 3
source = ColumnDataSource(data=df)
p = figure()
p.circle("x", "y", size=20, source=source)
show(p)
SerializationError
が発生します。要はnullableなdtypeは、bokeh3.0では対応していません。
bokeh.core.serialization.SerializationError: can't serialize <class 'pandas.core.arrays.integer.IntegerArray'>