◇ OpenCyber Academy
Master's · Chapter 5 · English

Chapter 5 — Proposal and pilot

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 5 — Proposal and pilot

Lesson map

Lesson 05 published. Map, example, EX027.

flowchart TD
  N0["Learning outcomes"]
  N1["5.1 Pilot purpose"]
  N2["5.2 The duplicate lab"]
  N3["5.3 Correction times"]
  N4["5.4 Refining the proposal"]
  N5["Lab — Address duplicates before and after normalisat"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5
  N5 --> EX["Worked example"]
  EX --> Q["Exercise EX027"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["5.1 Pilot purpose"]
  N2["5.2 The duplicate lab"]
  N3["5.3 Correction times"]
  N4["5.4 Refining the proposal"]
  N5["Lab — Address duplicates before and after normalisat"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX027"]
[Learning outcomes]
    |
    v
[5.1 Pilot purpose]
    |
    v
[5.2 The duplicate lab]
    |
    v
[5.3 Correction times]
    |
    v
[5.4 Refining the proposal]
    |
    v
[Lab — Address duplicates before and after normalisat]
    |
    v
[Worked example] --> [Exercise EX027]

Learning outcomes

You will (1) pilot measurement of duplicates and correction times; (2) normalise address data; (3) refine the proposal from pilot lessons.

5.1 Pilot purpose

Before the main data collection, Tomás pilots his measurements on a synthetic replica of the address registers. He wants to know whether duplicates can be counted reliably, whether correction times can be extracted from ticket logs and how long each step takes. A pilot is not meant to answer the research question; it tests whether the methods work. Dr. Solberg reminds him that problems found in a pilot are cheap, while the same problems found during the main study can cost months.

5.2 The duplicate lab

The pilot lab builds 3,305 synthetic address records in which a second department sometimes keys the same address with abbreviations, extra spaces and different capitals. Exact matching finds no duplicates at all, because no two strings are identical. After normalisation, which lowercases text, expands abbreviations such as St and Rd and collapses spaces, 384 duplicates appear, 11.6% of records. The result shows that any duplicate measure depends heavily on the normalisation rules chosen, which are themselves a governance decision. The abbreviation rules decide what counts as the same address.

5.3 Correction times

Ticket logs record when an error was reported and when it was closed, but closure does not always mean the address changed in every system. In the replica, some tickets close when the reporting department fixes its own copy while other departments remain wrong. Tomás redefines the outcome as days until the corrected address appears in all five systems, which matches what residents experience. ISO 8000-1's emphasis on requirements helps him justify the change: the requirement is a correct address everywhere, not a closed ticket.

5.4 Refining the proposal

From the pilot, Tomás updates his proposal: duplicate counts will use documented normalisation rules agreed with the stewards, correction time will be measured to the last system updated, and data extraction will take two weeks rather than one. He records the changes and their reasons in his decision log before collecting real outcome data, so the changes cannot be accused of chasing results. Dr. Solberg approves, noting that the pilot has already produced a finding about how definitions shape measured quality.

Lab — Address duplicates before and after normalisation

"""Find duplicate address records before and after normalisation in a synthetic council register (stdlib only)."""
import random, re, collections
random.seed(12)
streets = ["High Street", "Mill Lane", "Church Road", "Station Road", "Park Avenue", "Kings Way"]
base = [(random.randint(1, 120), random.choice(streets), f"AR{random.randint(1,9)} {random.randint(1,9)}QX") for _ in range(3000)]
base = list(dict.fromkeys(base))
recs = []
for n, s, p in base:
    recs.append(f"{n} {s}, {p}")
    if random.random() < 0.12:   # a second department keys the same address differently
        v = s.replace("Street", "St").replace("Road", "Rd").replace("Avenue", "Ave")
        recs.append(f"{n}  {v.upper()},{p.lower()}")
def norm(a):
    a = a.lower().replace(",", " ")
    for k, v in {" st ": " street ", " rd ": " road ", " ave ": " avenue "}.items():
        a = (" " + a + " ").replace(k, v).strip()
    return re.sub(r"\s+", " ", a)
exact = len(recs) - len(set(recs))
normd = len(recs) - len({norm(r) for r in recs})
print(f"records {len(recs)}; exact duplicates {exact}; duplicates after normalisation {normd} ({100*normd/len(recs):.1f}%)")

Run with python3 lab_dupes.py. Verified output:

records 3305; exact duplicates 0; duplicates after normalisation 384 (11.6%)

Worked example

Tomás finds no exact duplicates but 384 (11.6%) after normalisation among 3,305 synthetic records, redefines correction time to the last system updated and logs proposal changes before main data collection.

Synthetic case. Records are synthetic; ISO 8000-1:2022 is real.

Errors and limits

Aggressive normalisation can merge different addresses; check a sample by hand.

Exercises

Continue studying — lesson 05 (chapter 05 of 08)

← Chapter 04 · Course chapter index · Chapter 06 →

Continue to the next authored lesson.