{"id":"data-processing-finding-modules","slug":"finding-modules","title":"Finding the right module","text":"Before you write a function, it's worth checking whether the standard library already has one. Its modules are listed by theme in Python's documentation, at [docs.python.org/3/library](https://docs.python.org/3/library/): text, numbers and mathematics, dates, files, data formats such as CSV and JSON, and much more. Beyond the standard library, thousands of modules written by other programmers are at the Python Package Index, [pypi.org](https://pypi.org), and on your own computer you install them with a tool called pip. This site runs only the standard library.\n\nHere are two finds that save real work.\n\n### statistics\n\nThe **`statistics`** module calculates averages and more. `mean` is the ordinary average, and `median` the middle value when the values are in order:\n\n```python\nimport statistics\n\nlap_times = [12.5, 11.8, 13.1, 12.0, 30.2]\nprint(statistics.mean(lap_times))\nprint(statistics.median(lap_times))\n```\n\n```output\n15.92\n12.5\n```\n\nOne lap went badly (30.2 seconds), and it pulls the mean up. The median stays a typical lap time, which is why the median is often the better summary of data with outliers. With an even number of values, the median is the mean of the two middle ones.\n\n### difflib\n\nThe **`difflib`** module compares texts. Its function `get_close_matches(word, possibilities)` returns the strings of the list that look most like the word, the most similar first, and an empty list when nothing is close. Python's own \"Did you mean\" messages work in a similar way:\n\n```python\nfrom difflib import get_close_matches\n\ncommands = [\"help\", \"start\", \"stop\", \"status\", \"quit\"]\nprint(get_close_matches(\"hlep\", commands))\nprint(get_close_matches(\"strat\", commands))\nprint(get_close_matches(\"xyz\", commands))\n```\n\n```output\n['help']\n['start', 'status']\n[]\n```\n\n### Reading a documentation entry\n\nThe documentation shows a function by its first line, followed by a description. The entry for this one starts with `difflib.get_close_matches(word, possibilities, n=3, cutoff=0.6)`. The parameters with `=` have a default value: you can leave them out, and then the function returns at most 3 matches (`n`) and only fairly close ones (`cutoff`). Most entries work like this, so knowing how to read one lets you use functions you have never seen before.\n","task":"Fill in the blank so the program prints the middle value of the ages (27), not their average.\n","kind":"fill","seed":"import statistics\n\nages = [23, 31, 27, 45, 19]\nprint(statistics.[[median]](ages))\n","solution":"import statistics\n\nages = [23, 31, 27, 45, 19]\nprint(statistics.median(ages))\n","hints":["The average of these ages is 29. The middle value, when they're in order, is what the task asks for.","The function for the middle value is `median`."],"tests":[{"name":"Output","stdin":"","expect":"27","hidden":false}],"require":[],"forbid":[],"more":[{"task":"Write a command prompt that helps with typos. It asks for commands until the command is `quit`, and then prints `Bye!`. A known command (one of the list `commands` in the starter code) is answered with `Running` and its name. An unknown one is answered with a suggestion from `get_close_matches`, its first match, or without one if there's no match. For example:\n\n```\nCommand: strat\nUnknown command strat. Did you mean start?\nCommand: start\nRunning start\nCommand: xyz\nUnknown command xyz.\nCommand: quit\nBye!\n```\n","kind":"code","seed":"from difflib import get_close_matches\n\ncommands = [\"help\", \"start\", \"stop\", \"status\", \"quit\"]\n","solution":"from difflib import get_close_matches\n\ncommands = [\"help\", \"start\", \"stop\", \"status\", \"quit\"]\n\nwhile True:\n    command = input(\"Command: \")\n    if command == \"quit\":\n        print(\"Bye!\")\n        break\n    if command in commands:\n        print(\"Running\", command)\n    else:\n        matches = get_close_matches(command, commands)\n        if len(matches) > 0:\n            print(f\"Unknown command {command}. Did you mean {matches[0]}?\")\n        else:\n            print(f\"Unknown command {command}.\")\n","hints":["Read commands in a `while True` loop, and leave it with `break` after printing `Bye!` for `quit`.","Check `command in commands` first. Only an unknown command needs `get_close_matches(command, commands)`.","The matches are a list, best first. If it isn't empty, suggest `matches[0]`."],"tests":[{"name":"Test 1","stdin":"strat\nstart\nxyz\nquit\n","expect":"Command: strat\nUnknown command strat. Did you mean start?\nCommand: start\nRunning start\nCommand: xyz\nUnknown command xyz.\nCommand: quit\nBye!","hidden":false},{"name":"Test 2","stdin":"hlep\nhelp\nstp\nstatsu\nstatus\nabc\nquit\n","expect":"Command: hlep\nUnknown command hlep. Did you mean help?\nCommand: help\nRunning help\nCommand: stp\nUnknown command stp. Did you mean stop?\nCommand: statsu\nUnknown command statsu. Did you mean status?\nCommand: status\nRunning status\nCommand: abc\nUnknown command abc.\nCommand: quit\nBye!","hidden":true},{"name":"Test 3","stdin":"quit\n","expect":"Command: quit\nBye!","hidden":true}],"require":[],"forbid":[]},{"task":"The file `temperatures.csv` has a date and a temperature (a float) on each line, separated by a comma. Write a program that reads it with the `csv` module and prints the mean and the median of the temperatures with one decimal, using the `statistics` module. For example, for this file:\n\n```text\n2026-03-01,4.5\n2026-03-02,6.0\n2026-03-03,5.5\n2026-03-04,12.0\n```\n\nthe program prints:\n\n```\nMean: 7.0\nMedian: 5.8\n```\n","kind":"code","seed":"import csv\nimport statistics\n","solution":"import csv\nimport statistics\n\ntemperatures = []\nwith open(\"temperatures.csv\") as file:\n    for row in csv.reader(file):\n        temperatures.append(float(row[1]))\n\nprint(f\"Mean: {statistics.mean(temperatures):.1f}\")\nprint(f\"Median: {statistics.median(temperatures):.1f}\")\n","hints":["Collect the temperatures into a list first, converting each one with `float(row[1])`.","Then give the whole list to `statistics.mean` and `statistics.median`, and print them with `:.1f` in an f-string."],"tests":[{"name":"Test 1","stdin":"","files":{"temperatures.csv":"2026-03-01,4.5\n2026-03-02,6.0\n2026-03-03,5.5\n2026-03-04,12.0\n"},"expect":"Mean: 7.0\nMedian: 5.8","hidden":false},{"name":"Test 2","stdin":"","files":{"temperatures.csv":"2026-01-10,-5.0\n2026-01-11,-2.5\n2026-01-12,1.0\n"},"expect":"Mean: -2.2\nMedian: -2.5","hidden":true},{"name":"Test 3","stdin":"","files":{"temperatures.csv":"2026-06-01,18.5\n2026-06-02,21.0\n2026-06-03,19.5\n2026-06-04,30.0\n2026-06-05,20.0\n"},"expect":"Mean: 21.8\nMedian: 20.0","hidden":true}],"require":[{"pattern":"csv\\.reader","message":"Read the file with `csv.reader`."},{"pattern":"statistics\\.median|\\bmedian\\s*\\(","raw":true,"message":"Calculate the median with the `statistics` module."}],"forbid":[]}]}