Skip to content

Commit 3c2d1bf

Browse files
maartenbreddelsanmyachev
authored andcommitted
support dataframe protocol (tested with Vaex)
This allows plotly express to take in any dataframe that supports the dataframe protocol, see: https://data-apis.org/blog/dataframe_protocol_rfc/ https://data-apis.org/dataframe-protocol/latest/index.html Test includes an example with vaex, which should work with vaexio/vaex#1509 (not yet released)
1 parent 216fca2 commit 3c2d1bf

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

Diff for: packages/python/plotly/plotly/express/_core.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,17 @@ def build_dataframe(args, constructor):
13071307
# Cast data_frame argument to DataFrame (it could be a numpy array, dict etc.)
13081308
df_provided = args["data_frame"] is not None
13091309
if df_provided and not isinstance(args["data_frame"], pd.DataFrame):
1310-
args["data_frame"] = pd.DataFrame(args["data_frame"])
1310+
if hasattr(args["data_frame"], "__dataframe__"):
1311+
# Pandas does not implement a `from_dataframe` yet
1312+
# $ wget https://raw.githubusercontent.com/data-apis/dataframe-api/main/protocol/pandas_implementation.py
1313+
# $ export PYTHONPATH=`pwd`
1314+
import pandas_implementation
1315+
1316+
args["data_frame"] = pandas_implementation.from_dataframe(
1317+
args["data_frame"]
1318+
)
1319+
else:
1320+
args["data_frame"] = pd.DataFrame(args["data_frame"])
13111321
df_input = args["data_frame"]
13121322

13131323
# now we handle special cases like wide-mode or x-xor-y specification

Diff for: packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py

+13
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,19 @@ def test_build_df_with_index():
233233
assert_frame_equal(tips.reset_index()[out["data_frame"].columns], out["data_frame"])
234234

235235

236+
def test_build_df_protocol():
237+
import vaex
238+
239+
# take out the 'species' columns since the vaex implementation does not cover strings yet
240+
iris_pandas = px.data.iris()[["petal_width", "sepal_length"]]
241+
iris_vaex = vaex.from_pandas(iris_pandas)
242+
args = dict(data_frame=iris_vaex, x="petal_width", y="sepal_length")
243+
out = build_dataframe(args, go.Scatter)
244+
assert_frame_equal(
245+
iris_pandas.reset_index()[out["data_frame"].columns], out["data_frame"]
246+
)
247+
248+
236249
def test_timezones():
237250
df = pd.DataFrame({"date": ["2015-04-04 19:31:30+1:00"], "value": [3]})
238251
df["date"] = pd.to_datetime(df["date"])

0 commit comments

Comments
 (0)