new demo mode & tenure
This commit is contained in:
parent
7656f24544
commit
4a0f00f2a4
64 changed files with 2875 additions and 338 deletions
|
|
@ -220,6 +220,77 @@ def test_fuzzy_join_matches_high_score_number_less_pair():
|
|||
assert result["right_address"].to_list() == ["THE OLD RECTORY"]
|
||||
|
||||
|
||||
def test_fuzzy_join_keep_unmatched_right_appends_epc_only_rows():
|
||||
# Models "price-paid LEFT JOIN epc" with keep_unmatched_right: matched pairs
|
||||
# keep both sides; an unmatched LEFT (sold-but-no-EPC) row keeps null right
|
||||
# columns; an unmatched RIGHT (EPC-only, never sold) row is appended with
|
||||
# null left columns so the dwelling still enters the property universe.
|
||||
left = pl.LazyFrame(
|
||||
{
|
||||
"left_id": ["sold_with_epc", "sold_no_epc"],
|
||||
"left_address": ["10 High Street", "12 High Street"],
|
||||
"left_postcode": ["AB1 2CD", "AB1 2CD"],
|
||||
}
|
||||
)
|
||||
right = pl.LazyFrame(
|
||||
{
|
||||
"right_id": ["epc_for_10", "epc_only"],
|
||||
"right_address": ["10 HIGH STREET", "14 High Street"],
|
||||
"right_postcode": ["AB1 2CD", "AB1 2CD"],
|
||||
}
|
||||
)
|
||||
|
||||
result = (
|
||||
fuzzy_join_on_postcode(
|
||||
left=left,
|
||||
right=right,
|
||||
left_address_col="left_address",
|
||||
right_address_col="right_address",
|
||||
left_postcode_col="left_postcode",
|
||||
right_postcode_col="right_postcode",
|
||||
keep_unmatched_right=True,
|
||||
)
|
||||
.sort("left_id", "right_id", nulls_last=True)
|
||||
.collect()
|
||||
)
|
||||
|
||||
assert result.select("left_id", "right_id").to_dicts() == [
|
||||
# Sold but no EPC: left present, right null (ordinary left-join row).
|
||||
{"left_id": "sold_no_epc", "right_id": None},
|
||||
# Matched pair: both sides present.
|
||||
{"left_id": "sold_with_epc", "right_id": "epc_for_10"},
|
||||
# EPC-only dwelling: appended with null left columns.
|
||||
{"left_id": None, "right_id": "epc_only"},
|
||||
]
|
||||
# The appended EPC-only row carries its own address/postcode and a null score.
|
||||
epc_only = result.filter(pl.col("right_id") == "epc_only")
|
||||
assert epc_only["right_address"].to_list() == ["14 High Street"]
|
||||
assert epc_only["left_address"].to_list() == [None]
|
||||
assert epc_only["_match_score"].to_list() == [None]
|
||||
|
||||
|
||||
def test_fuzzy_join_keep_unmatched_right_off_by_default():
|
||||
# Without the flag the join stays left-only: an EPC-only right row is dropped.
|
||||
left = pl.LazyFrame(
|
||||
{"left_address": ["10 High Street"], "left_postcode": ["AB1 2CD"]}
|
||||
)
|
||||
right = pl.LazyFrame(
|
||||
{"right_address": ["14 High Street"], "right_postcode": ["AB1 2CD"]}
|
||||
)
|
||||
|
||||
result = fuzzy_join_on_postcode(
|
||||
left=left,
|
||||
right=right,
|
||||
left_address_col="left_address",
|
||||
right_address_col="right_address",
|
||||
left_postcode_col="left_postcode",
|
||||
right_postcode_col="right_postcode",
|
||||
).collect()
|
||||
|
||||
assert result.height == 1
|
||||
assert result["right_address"].to_list() == [None]
|
||||
|
||||
|
||||
def test_numbers_compatible_treats_letter_suffix_as_part_of_the_number():
|
||||
# 8A, 8B and plain 8 are three different properties on the same street;
|
||||
# digit-only extraction collapsed all three to {8} and let them match.
|
||||
|
|
@ -252,9 +323,7 @@ def test_numbers_compatible_gates_single_letter_flats():
|
|||
assert not _numbers_compatible(
|
||||
"FLAT D 39 GERTRUDE STREET", "FLAT F 39 GERTRUDE STREET"
|
||||
)
|
||||
assert _numbers_compatible(
|
||||
"FLAT D 39 GERTRUDE STREET", "39 GERTRUDE STREET FLAT D"
|
||||
)
|
||||
assert _numbers_compatible("FLAT D 39 GERTRUDE STREET", "39 GERTRUDE STREET FLAT D")
|
||||
assert not _numbers_compatible("FLAT B ROSE COURT", "ROSE COURT")
|
||||
# A letter glued to a number ("A3") is a unit name, not a flat letter.
|
||||
assert _numbers_compatible("FLAT A3 CHESHAM HEIGHTS", "FLAT A3 CHESHAM HEIGHTS")
|
||||
|
|
@ -263,9 +332,9 @@ def test_numbers_compatible_gates_single_letter_flats():
|
|||
def test_admissible_variants_allows_locality_suffix_only():
|
||||
# Locality words may differ between a variant and its primary; digits and
|
||||
# flat designators may not (the gate ran on the primary only).
|
||||
assert _admissible_variants(
|
||||
"12 OAK ROAD", ["12 OAK ROAD HALE", "12 OAK ROAD"]
|
||||
) == ("12 OAK ROAD HALE",)
|
||||
assert _admissible_variants("12 OAK ROAD", ["12 OAK ROAD HALE", "12 OAK ROAD"]) == (
|
||||
"12 OAK ROAD HALE",
|
||||
)
|
||||
# Dropping "FLAT 1" (digit) or "FLAT B" (flat designator) is inadmissible:
|
||||
# the variant would score a single flat as the whole building.
|
||||
assert (
|
||||
|
|
@ -278,9 +347,7 @@ def test_admissible_variants_allows_locality_suffix_only():
|
|||
# disagrees with the combined address must not smuggle in a different
|
||||
# street for scoring.
|
||||
assert _admissible_variants("12 OAK ROAD", ["12 ELM ROAD"]) == ()
|
||||
assert (
|
||||
_admissible_variants("1 TOTALLY DIFFERENT ROAD", ["1 EXAMPLE STREET"]) == ()
|
||||
)
|
||||
assert _admissible_variants("1 TOTALLY DIFFERENT ROAD", ["1 EXAMPLE STREET"]) == ()
|
||||
|
||||
|
||||
def test_fuzzy_join_variant_recovers_locality_suffix_mismatch():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue