Read and analyse the weather data with pandas
Task: MIL-003#1 Task: MIL-003#2 Task: MIL-003#3 Task: MIL-003#4
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
## @file analysis.py
|
||||
# @brief Reads and analyses the weather data file with `pandas`.
|
||||
#
|
||||
# This is the second half of the lectures: the file is read in one line into a
|
||||
# `DataFrame`, converted to a dictionary and a list, and the average and
|
||||
# maximum temperature and the row selections are computed. This is the only
|
||||
# module of the package that imports `pandas`, which is an optional extra.
|
||||
|
||||
"""Reads and analyses the weather data file with pandas."""
|
||||
|
||||
from collections.abc import Hashable
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import pandas
|
||||
|
||||
from weather.constants import (
|
||||
COLUMN_DAY,
|
||||
COLUMN_TEMP,
|
||||
DATA_FILE,
|
||||
FAHRENHEIT_DENOMINATOR,
|
||||
FAHRENHEIT_NUMERATOR,
|
||||
FAHRENHEIT_OFFSET,
|
||||
)
|
||||
|
||||
|
||||
def read_data(path: Path | str = DATA_FILE) -> pandas.DataFrame:
|
||||
"""! @brief Read a weather CSV file into a `DataFrame`.
|
||||
|
||||
@param path Path of the CSV file; the weather data file by default.
|
||||
@return The table, one row per day, with the columns of the file.
|
||||
"""
|
||||
return pandas.read_csv(path)
|
||||
|
||||
|
||||
def to_data_dict(data: pandas.DataFrame) -> dict[Hashable, Any]: # Any: cell values
|
||||
"""! @brief Convert the table to a dictionary of columns.
|
||||
|
||||
@param data The weather table.
|
||||
@return A dictionary that maps each column name to its values by row index.
|
||||
"""
|
||||
return data.to_dict()
|
||||
|
||||
|
||||
def to_temp_list(data: pandas.DataFrame) -> list[int]:
|
||||
"""! @brief Convert the temperature column to a list.
|
||||
|
||||
@param data The weather table.
|
||||
@return The temperatures in row order.
|
||||
"""
|
||||
return data[COLUMN_TEMP].to_list()
|
||||
|
||||
|
||||
def average_temp(data: pandas.DataFrame) -> float:
|
||||
"""! @brief Compute the average temperature from the sum and the length.
|
||||
|
||||
@param data The weather table.
|
||||
@return The average temperature.
|
||||
"""
|
||||
temp_list = to_temp_list(data)
|
||||
return sum(temp_list) / len(temp_list)
|
||||
|
||||
|
||||
def average_temp_mean(data: pandas.DataFrame) -> float:
|
||||
"""! @brief Compute the average temperature with `Series.mean()`.
|
||||
|
||||
@param data The weather table.
|
||||
@return The average temperature.
|
||||
"""
|
||||
return float(data[COLUMN_TEMP].mean())
|
||||
|
||||
|
||||
def max_temp(data: pandas.DataFrame) -> int:
|
||||
"""! @brief Find the highest temperature.
|
||||
|
||||
@param data The weather table.
|
||||
@return The maximum of the temperature column.
|
||||
"""
|
||||
return int(data[COLUMN_TEMP].max())
|
||||
|
||||
|
||||
def row_for_day(data: pandas.DataFrame, day: str) -> pandas.DataFrame:
|
||||
"""! @brief Select the rows of one day.
|
||||
|
||||
@param data The weather table.
|
||||
@param day Name of the day, such as `Monday`.
|
||||
@return The matching rows; empty when the day is not in the table.
|
||||
"""
|
||||
return data.loc[data[COLUMN_DAY] == day]
|
||||
|
||||
|
||||
def hottest_row(data: pandas.DataFrame) -> pandas.DataFrame:
|
||||
"""! @brief Select the row or rows with the highest temperature.
|
||||
|
||||
@param data The weather table.
|
||||
@return The rows whose temperature equals the maximum.
|
||||
"""
|
||||
return data.loc[data[COLUMN_TEMP] == max_temp(data)]
|
||||
|
||||
|
||||
def day_in_fahrenheit(data: pandas.DataFrame, day: str) -> float:
|
||||
"""! @brief Convert the temperature of one day from Celsius to Fahrenheit.
|
||||
|
||||
@param data The weather table.
|
||||
@param day Name of the day, such as `Monday`.
|
||||
@return The temperature in degrees Fahrenheit.
|
||||
@throws ValueError When the day is not in the table exactly once.
|
||||
"""
|
||||
rows = row_for_day(data, day)
|
||||
if len(rows) != 1:
|
||||
raise ValueError(f"Expected exactly one row for day {day!r}, got {len(rows)}")
|
||||
celsius = int(rows[COLUMN_TEMP].iloc[0])
|
||||
return celsius * FAHRENHEIT_NUMERATOR / FAHRENHEIT_DENOMINATOR + FAHRENHEIT_OFFSET
|
||||
Reference in New Issue
Block a user