Skip to content

Commit 6c65381

Browse files
Fix on situations where postcode column exists in data but is not used
1 parent 6f2191c commit 6c65381

1 file changed

Lines changed: 56 additions & 9 deletions

File tree

fuzzy_address_matcher/preparation.py

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -224,16 +224,34 @@ def _add_postcode_column(df: PandasDataFrame, postcodes: str):
224224
if isinstance(postcodes, list):
225225
postcodes = postcodes[0]
226226

227-
if postcodes != "full_address_postcode":
228-
df = df.rename(columns={postcodes: "postcode"})
227+
# Helper: normalise a postcode-like series to strings with blanks for missing
228+
def _norm_pc(s: pd.Series) -> pd.Series:
229+
return s.fillna("").astype(str).str.strip()
230+
231+
if postcodes == "full_address_postcode":
232+
# Extract postcode from full address text into the same column name, then treat
233+
# it as the candidate postcode series.
234+
df["full_address_postcode"] = extract_postcode(df, "full_address_postcode")[0]
235+
candidate = _norm_pc(df["full_address_postcode"])
236+
source_col = "full_address_postcode"
229237
else:
230-
# print(df["full_address_postcode"])
231-
# print(extract_postcode(df,"full_address_postcode"))
232-
df["full_address_postcode"] = extract_postcode(df, "full_address_postcode")[
233-
0
234-
] #
235-
df = df.rename(columns={postcodes: "postcode"})
236-
# print(df)
238+
if postcodes not in df.columns:
239+
return df
240+
candidate = _norm_pc(df[postcodes])
241+
source_col = postcodes
242+
243+
# Avoid creating duplicate column names ("postcode" already exists in some inputs).
244+
if "postcode" in df.columns:
245+
existing = _norm_pc(df["postcode"])
246+
use_existing = existing.ne("")
247+
df["postcode"] = existing.where(use_existing, candidate)
248+
# Drop the source column if it's not the canonical postcode column.
249+
if source_col != "postcode" and source_col in df.columns:
250+
df = df.drop(columns=[source_col])
251+
else:
252+
df["postcode"] = candidate
253+
if source_col != "postcode" and source_col in df.columns:
254+
df = df.drop(columns=[source_col])
237255

238256
return df
239257

@@ -342,6 +360,35 @@ def prepare_ref_address(
342360

343361
ref_df_cleaned["ref_index"] = ref_df_cleaned.index
344362

363+
# --- Postcode column normalisation ---
364+
# Prevent duplicate postcode column names from propagating downstream (which can
365+
# make df["Postcode"] return a DataFrame and break `.str` operations).
366+
#
367+
# Canonical reference postcode column name in this codebase is "Postcode".
368+
if (
369+
"Postcode" not in ref_df_cleaned.columns
370+
and "postcode" in ref_df_cleaned.columns
371+
):
372+
ref_df_cleaned = ref_df_cleaned.rename(columns={"postcode": "Postcode"})
373+
374+
# If both exist, prefer non-blank values in "Postcode" and fill from "postcode".
375+
if "Postcode" in ref_df_cleaned.columns and "postcode" in ref_df_cleaned.columns:
376+
_pc_main = ref_df_cleaned["Postcode"].fillna("").astype(str).str.strip()
377+
_pc_alt = ref_df_cleaned["postcode"].fillna("").astype(str).str.strip()
378+
ref_df_cleaned["Postcode"] = _pc_main.where(_pc_main.ne(""), _pc_alt)
379+
ref_df_cleaned = ref_df_cleaned.drop(columns=["postcode"])
380+
381+
# If there are duplicated "Postcode" columns (possible after merges), keep the first.
382+
if (
383+
hasattr(ref_df_cleaned.columns, "duplicated")
384+
and ref_df_cleaned.columns.duplicated().any()
385+
):
386+
dup_names = ref_df_cleaned.columns[ref_df_cleaned.columns.duplicated()].tolist()
387+
if "Postcode" in dup_names:
388+
ref_df_cleaned = ref_df_cleaned.loc[
389+
:, ~ref_df_cleaned.columns.duplicated()
390+
].copy()
391+
345392
# In on-prem LPI db street has been excluded, so put this back in
346393
if ("Street" not in ref_df_cleaned.columns) & (
347394
"Address_LPI" in ref_df_cleaned.columns

0 commit comments

Comments
 (0)