Skip to content

Commit 9721b1b

Browse files
added warning messages when OverflowError occurs.
1 parent 3e4fe6e commit 9721b1b

3 files changed

Lines changed: 65 additions & 10 deletions

File tree

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626
, 'scikit-learn'
2727
, 'numpy'
2828
, 'sparse_dot_topn_for_blocks>=0.3.1'
29-
, 'topn>=0.0.6'
29+
, 'topn>=0.0.7'
3030
]
3131
)

string_grouper/string_grouper.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import numpy as np
33
import re
44
import multiprocessing
5+
import warnings
56
from sklearn.feature_extraction.text import TfidfVectorizer
67
from scipy.sparse import vstack
78
from scipy.sparse.csr import csr_matrix
@@ -409,13 +410,19 @@ def divide_by(n, series):
409410
hblocks = []
410411
for right_block in block_ranges_right:
411412
right_matrix = self._get_right_tf_idf_matrix(right_block)
412-
413-
# Calculate the matches using the cosine similarity
414-
# Note: awesome_cossim_topn will sort each row only when
415-
# _max_n_matches < size of right_block or sort=True
416-
matches, block_true_max_n_matches = self._build_matches(
417-
left_matrix, right_matrix, nnz_rows, sort=(len(block_ranges_right) == 1)
418-
)
413+
try:
414+
# Calculate the matches using the cosine similarity
415+
# Note: awesome_cossim_topn will sort each row only when
416+
# _max_n_matches < size of right_block or sort=True
417+
matches, block_true_max_n_matches = self._build_matches(
418+
left_matrix, right_matrix, nnz_rows, sort=(len(block_ranges_right) == 1)
419+
)
420+
except OverflowError as oe:
421+
import sys
422+
raise (type(oe)(f"{str(oe)} Use the n_blocks parameter to split-up "
423+
f"the data into smaller chunks. The current values"
424+
f"(n_blocks = {n_blocks}) are too small.")
425+
.with_traceback(sys.exc_info()[2]))
419426
hblocks.append(matches)
420427
# end of inner loop
421428

@@ -478,6 +485,12 @@ def end(partition, left=True):
478485
left_matrix, right_matrix, nnz_rows[slice(*left_partition)],
479486
sort=sort)
480487
except OverflowError:
488+
warnings.warn("An OverflowError occurred but is being "
489+
"handled. The input data will be automatically "
490+
"split-up into smaller chunks which will then be "
491+
"processed one chunk at a time. To prevent "
492+
"OverflowError, use the n_blocks parameter to split-up "
493+
"the data manually into small enough chunks.")
481494
# Matrices too big! Try splitting:
482495
del left_matrix, right_matrix
483496

string_grouper/test/test_string_grouper.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def test_auto_blocking_single_DataFrame(self):
122122
# This function will force an OverflowError to occur when
123123
# the input Series have a combined length above a given number:
124124
# OverflowThreshold. This will in turn trigger automatic splitting
125-
# of the Series/matrices into smaller blocks
125+
# of the Series/matrices into smaller blocks when n_blocks = None
126126

127127
sort_cols = ['right_index', 'left_index']
128128

@@ -143,7 +143,7 @@ def fix_row_order(df):
143143
# Create a custom wrapper for this StringGrouper instance's
144144
# _build_matches() method which will later be used to
145145
# mock _build_matches().
146-
# Note that we have to define the mock function here because
146+
# Note that we have to define the wrapper here because
147147
# _build_matches() is a non-static function of StringGrouper
148148
# and needs access to the specific StringGrouper instance sg
149149
# created here.
@@ -240,6 +240,48 @@ def fix_row_order(df):
240240
match_strings(df1, n_blocks=(3, 2), min_similarity=0.1))
241241
pd.testing.assert_frame_equal(matches11, matches32)
242242

243+
# Create a custom wrapper for this StringGrouper instance's
244+
# _build_matches() method which will later be used to
245+
# mock _build_matches().
246+
# Note that we have to define the wrapper here because
247+
# _build_matches() is a non-static function of StringGrouper
248+
# and needs access to the specific StringGrouper instance sg
249+
# created here.
250+
sg = StringGrouper(df1, min_similarity=0.1)
251+
252+
def mock_build_matches(OverflowThreshold,
253+
real_build_matches=sg._build_matches):
254+
def wrapper(left_matrix,
255+
right_matrix,
256+
nnz_rows=None,
257+
sort=True):
258+
if (left_matrix.shape[0] + right_matrix.shape[0]) > \
259+
OverflowThreshold:
260+
raise OverflowError
261+
return real_build_matches(left_matrix, right_matrix, nnz_rows, sort)
262+
return wrapper
263+
264+
def test_overflow_error_with(OverflowThreshold, n_blocks):
265+
nonlocal sg
266+
sg._build_matches = Mock(side_effect=mock_build_matches(OverflowThreshold))
267+
sg.clear_data()
268+
max_left_block_size = (len(df1)//n_blocks[0]
269+
+ (1 if len(df1) % n_blocks[0] > 0 else 0))
270+
max_right_block_size = (len(df1)//n_blocks[1]
271+
+ (1 if len(df1) % n_blocks[1] > 0 else 0))
272+
if (max_left_block_size + max_right_block_size) > OverflowThreshold:
273+
with self.assertRaises(Exception):
274+
_ = sg.match_strings(df1, n_blocks=n_blocks)
275+
else:
276+
matches_manual = fix_row_order(sg.match_strings(df1, n_blocks=n_blocks))
277+
pd.testing.assert_frame_equal(matches11, matches_manual)
278+
279+
test_overflow_error_with(OverflowThreshold=100, n_blocks=(1, 1))
280+
test_overflow_error_with(OverflowThreshold=10, n_blocks=(1, 1))
281+
test_overflow_error_with(OverflowThreshold=10, n_blocks=(2, 1))
282+
test_overflow_error_with(OverflowThreshold=10, n_blocks=(1, 2))
283+
test_overflow_error_with(OverflowThreshold=10, n_blocks=(4, 4))
284+
243285
def test_n_blocks_both_DataFrames(self):
244286
"""tests whether manual blocking yields consistent results"""
245287
sort_cols = ['right_index', 'left_index']

0 commit comments

Comments
 (0)