diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c842a380..8e9df6bc6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## UNRELEASED +### Fixed + - Fixed regression introduced in version 5.0.0 where pandas/numpy arrays with `dtype` of Object were being converted to `list` values when added to a Figure ([#3292](https://github.com/plotly/plotly.py/issues/3292), [#3293](https://github.com/plotly/plotly.py/pull/3293)) ## [5.1.0] - 2021-06-28 diff --git a/packages/python/plotly/_plotly_utils/basevalidators.py b/packages/python/plotly/_plotly_utils/basevalidators.py index da0d21db7c..66e7b15dc8 100644 --- a/packages/python/plotly/_plotly_utils/basevalidators.py +++ b/packages/python/plotly/_plotly_utils/basevalidators.py @@ -53,7 +53,7 @@ def to_scalar_or_list(v): return v -def copy_to_readonly_numpy_array_or_list(v, kind=None, force_numeric=False): +def copy_to_readonly_numpy_array(v, kind=None, force_numeric=False): """ Convert an array-like value into a read-only numpy array @@ -94,7 +94,6 @@ def copy_to_readonly_numpy_array_or_list(v, kind=None, force_numeric=False): "i": "int32", "f": "float64", "O": "object", - "U": "U", } # Handle pandas Series and Index objects @@ -119,12 +118,18 @@ def copy_to_readonly_numpy_array_or_list(v, kind=None, force_numeric=False): if not isinstance(v, np.ndarray): # v has its own logic on how to convert itself into a numpy array if is_numpy_convertable(v): - return copy_to_readonly_numpy_array_or_list( + return copy_to_readonly_numpy_array( np.array(v), kind=kind, force_numeric=force_numeric ) else: # v is not homogenous array - return [to_scalar_or_list(e) for e in v] + v_list = [to_scalar_or_list(e) for e in v] + + # Lookup dtype for requested kind, if any + dtype = kind_default_dtypes.get(first_kind, None) + + # construct new array from list + new_v = np.array(v_list, order="C", dtype=dtype) elif v.dtype.kind in numeric_kinds: # v is a homogenous numeric array if kind and v.dtype.kind not in kind: @@ -135,12 +140,6 @@ def copy_to_readonly_numpy_array_or_list(v, kind=None, force_numeric=False): else: # Either no kind was requested or requested kind is satisfied new_v = np.ascontiguousarray(v.copy()) - elif v.dtype.kind == "O": - if kind: - dtype = kind_default_dtypes.get(first_kind, None) - return np.array(v, dtype=dtype) - else: - return v.tolist() else: # v is a non-numeric homogenous array new_v = v.copy() @@ -155,12 +154,12 @@ def copy_to_readonly_numpy_array_or_list(v, kind=None, force_numeric=False): if "U" not in kind: # Force non-numeric arrays to have object type # -------------------------------------------- - # Here we make sure that non-numeric arrays become lists - # This works around cases like np.array([1, 2, '3']) where + # Here we make sure that non-numeric arrays have the object + # datatype. This works around cases like np.array([1, 2, '3']) where # numpy converts the integers to strings and returns array of dtype # 'sepal_length=%{y}
petal_length=%{customdata[2]}
petal_width=%{customdata[3]}
species_id=%{customdata[0]}" diff --git a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_functions.py b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_functions.py index fad79b5ded..a75a45f43d 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_functions.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_functions.py @@ -229,9 +229,9 @@ def test_sunburst_treemap_with_path_color(): df["hover"] = [el.lower() for el in vendors] fig = px.sunburst(df, path=path, color="calls", hover_data=["hover"]) custom = fig.data[0].customdata - assert [el[0] for el in custom[:8]] == df["hover"].tolist() - assert [el[0] for el in custom[8:]] == ["(?)"] * 7 - assert [el[1] for el in custom[:8]] == df["calls"].tolist() + assert np.all(custom[:8, 0] == df["hover"]) + assert np.all(custom[8:, 0] == "(?)") + assert np.all(custom[:8, 1] == df["calls"]) # Discrete color fig = px.sunburst(df, path=path, color="vendors") diff --git a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py index 0dce0ae663..477e7dbcb0 100644 --- a/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py +++ b/packages/python/plotly/plotly/tests/test_optional/test_px/test_px_input.py @@ -126,7 +126,7 @@ def test_repeated_name(): hover_data=["petal_length", "petal_width", "species_id"], custom_data=["species_id", "species"], ) - assert len(fig.data[0].customdata[0]) == 4 + assert fig.data[0].customdata.shape[1] == 4 def test_arrayattrable_numpy():