Skip to content

Commit c90df2d

Browse files
committed
BUG: Fix #57608: queries on categorical string columns in
HDFStore.select() return unexpected results. In function __init__() of class Selection (pandas/core/io/pytables.py), the method self.terms.evaluate() was not returning the correct value for the where condition. The issue stemmed from the function convert_value() of class BinOp (pandas/core/computation/pytables.py), where the function searchedsorted() did not return the correct index when matching the where condition in the metadata (categories table). Replacing searchsorted() with np.where() resolves this issue.
1 parent eca6bd3 commit c90df2d

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,7 @@ I/O
775775
- Bug in :meth:`DataFrame.to_stata` when writing more than 32,000 value labels. (:issue:`60107`)
776776
- Bug in :meth:`DataFrame.to_string` that raised ``StopIteration`` with nested DataFrames. (:issue:`16098`)
777777
- Bug in :meth:`HDFStore.get` was failing to save data of dtype datetime64[s] correctly (:issue:`59004`)
778+
- Bug in :meth:`HDFStore.select` causing queries on categorical string columns to return unexpected results (:issue:`57608`)
778779
- Bug in :meth:`read_csv` causing segmentation fault when ``encoding_errors`` is not a string. (:issue:`59059`)
779780
- Bug in :meth:`read_csv` raising ``TypeError`` when ``index_col`` is specified and ``na_values`` is a dict containing the key ``None``. (:issue:`57547`)
780781
- Bug in :meth:`read_csv` raising ``TypeError`` when ``nrows`` and ``iterator`` are specified without specifying a ``chunksize``. (:issue:`59079`)

pandas/core/computation/pytables.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ def stringify(value):
239239
if conv_val not in metadata:
240240
result = -1
241241
else:
242-
result = metadata.searchsorted(conv_val, side="left")
242+
# Find the index of the first match of conv_val in metadata
243+
result = np.where(metadata == conv_val)[0][0]
243244
return TermValue(result, result, "integer")
244245
elif kind == "integer":
245246
try:

pandas/tests/io/pytables/test_store.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
timedelta_range,
2424
)
2525
import pandas._testing as tm
26+
from pandas.api.types import (
27+
CategoricalDtype,
28+
)
29+
from pandas.conftest import has_pyarrow
2630
from pandas.tests.io.pytables.common import (
2731
_maybe_remove,
2832
ensure_clean_store,
@@ -1107,3 +1111,23 @@ def test_store_bool_index(tmp_path, setup_path):
11071111
df.to_hdf(path, key="a")
11081112
result = read_hdf(path, "a")
11091113
tm.assert_frame_equal(expected, result)
1114+
1115+
1116+
@pytest.mark.parametrize("model", ["name", "longname", "verylongname"])
1117+
def test_select_categorical_string_columns(tmp_path, model):
1118+
# Corresponding to BUG: 57608
1119+
1120+
path = tmp_path / "test.h5"
1121+
1122+
models = CategoricalDtype(categories=["name", "longname", "verylongname"])
1123+
df = DataFrame(
1124+
{"modelId": ["name", "longname", "longname"], "value": [1, 2, 3]}
1125+
).astype({"modelId": models, "value": int})
1126+
1127+
with HDFStore(path, "w") as store:
1128+
store.append("df", df, data_columns=["modelId"])
1129+
1130+
with HDFStore(path, "r") as store:
1131+
result = store.select("df", "modelId == model")
1132+
expected = df[df["modelId"] == model]
1133+
tm.assert_frame_equal(result, expected)

0 commit comments

Comments
 (0)