Skip to content

Commit 756660a

Browse files
authored
Optimize copy_to_readonly_numpy_array for numeric pandas series/index objects (#1149)
* Removed redundant test * Performance optimization for numeric coercion of pandas series/index * Preserve integer type in homogenous array (don't case to double)
1 parent 96ade26 commit 756660a

File tree

4 files changed

+21
-13
lines changed

4 files changed

+21
-13
lines changed

_plotly_utils/basevalidators.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,20 @@ def copy_to_readonly_numpy_array(v, dtype=None, force_numeric=False):
8383
# u: unsigned int, i: signed int, f: float
8484
numeric_kinds = ['u', 'i', 'f']
8585

86+
# Unwrap data types that have a `values` property that might be a numpy
87+
# array. If this values property is a numeric numpy array then we
88+
# can take the fast path below
89+
if pd and isinstance(v, (pd.Series, pd.Index)):
90+
v = v.values
91+
8692
if not isinstance(v, np.ndarray):
8793
v_list = [to_scalar_or_list(e) for e in v]
8894
new_v = np.array(v_list, order='C', dtype=dtype)
8995
elif v.dtype.kind in numeric_kinds:
90-
new_v = np.ascontiguousarray(v.astype(dtype))
96+
if dtype:
97+
new_v = np.ascontiguousarray(v.astype(dtype))
98+
else:
99+
new_v = np.ascontiguousarray(v)
91100
else:
92101
new_v = v.copy()
93102

_plotly_utils/tests/validators/test_color_validator.py

-6
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,6 @@ def test_description_aok(validator_aok):
192192
assert 'A list or array of any of the above' in desc
193193

194194

195-
def test_description_aok(validator_colorscale):
196-
desc = validator_colorscale.description()
197-
assert 'A number that will be interpreted as a color' in desc
198-
assert 'A list or array of any of the above' not in desc
199-
200-
201195
def test_description_aok_colorscale(validator_aok_colorscale):
202196
desc = validator_aok_colorscale.description()
203197
assert 'A number that will be interpreted as a color' in desc

_plotly_utils/tests/validators/test_integer_validator.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from pytest import approx
55
from _plotly_utils.basevalidators import IntegerValidator
66
import numpy as np
7+
import pandas as pd
78

89

910
# ### Fixtures ###
@@ -121,17 +122,20 @@ def test_acceptance_aok_list(val, validator_aok):
121122
[([1, 0], (1, 0)),
122123
((1, -1), (1, -1)),
123124
(np.array([-1, 0, 5.0], dtype='int16'), [-1, 0, 5]),
124-
(np.array([1, 0], dtype=np.int64), [1, 0])])
125+
(np.array([1, 0], dtype=np.int64), [1, 0]),
126+
(pd.Series([1, 0], dtype=np.int64), [1, 0]),
127+
(pd.Index([1, 0], dtype=np.int64), [1, 0])])
125128
def test_coercion_aok_list(val, expected, validator_aok):
126129
v = validator_aok.validate_coerce(val)
127-
if isinstance(val, np.ndarray):
130+
if isinstance(val, (np.ndarray, pd.Series, pd.Index)):
128131
assert v.dtype == np.int32
129132
assert np.array_equal(validator_aok.present(v),
130133
np.array(expected, dtype=np.int32))
131134
else:
132135
assert isinstance(v, list)
133136
assert validator_aok.present(v) == expected
134137

138+
135139
# ### Rejection ###
136140
#
137141
@pytest.mark.parametrize('val',

_plotly_utils/tests/validators/test_number_validator.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from _plotly_utils.basevalidators import NumberValidator
55
import numpy as np
6-
6+
import pandas as pd
77

88
# Fixtures
99
# --------
@@ -118,12 +118,13 @@ def test_acceptance_aok_list(val, validator_aok):
118118
# Coerced to general consistent numeric type
119119
@pytest.mark.parametrize('val,expected',
120120
[([1.0, 0], (1.0, 0)),
121-
(np.array([1, -1]), np.array([1.0, -1.0])),
121+
(np.array([1, -1]), np.array([1, -1])),
122+
(pd.Series([1, -1]), np.array([1, -1])),
123+
(pd.Index([1, -1]), np.array([1, -1])),
122124
((-0.1234, 0, -1), (-0.1234, 0.0, -1.0))])
123125
def test_coercion_aok_list(val, expected, validator_aok):
124126
v = validator_aok.validate_coerce(val)
125-
if isinstance(val, np.ndarray):
126-
assert v.dtype == 'float'
127+
if isinstance(val, (np.ndarray, pd.Series, pd.Index)):
127128
assert np.array_equal(v, expected)
128129
else:
129130
assert isinstance(v, list)

0 commit comments

Comments
 (0)