Scoring
Functions for computing quality signals and comparing professors. All take list[Rating] as input (from get_all_ratings) and return typed dataclasses.
Weight presets
WEIGHT_PRESETS is a dict of named weight configurations for compute_score. Pass any entry directly to the weights parameter:
from rmp_api import WEIGHT_PRESETS, compute_score
score = compute_score(ratings, weights=WEIGHT_PRESETS["best_teacher"])
| Key | What it emphasizes |
|---|---|
"overall" |
Balanced default |
"best_teacher" |
Teaching quality; ignores difficulty |
"easiest" |
Easiness (low difficulty) |
"rigorous" |
Harder courses score higher (negative easiness weight) |
Custom weights
Supply any subset of these keys. Missing keys default to 0. Values should sum to approximately 1.0. The resulting composite_score is clamped to [0, 1].
score = compute_score(ratings, weights={
"recency_rating": 0.4,
"would_take_again": 0.3,
"easiness": 0.2,
"reliability": 0.1,
})
Custom weights only affect composite_score. All other signals (raw_avg_rating, reliability_score, etc.) are always computed regardless of weights.
Sorting and comparison
When using compare_professors, pass a SortBy enum value or its string equivalent to choose the ranking field. Higher values always rank first -- to rank by easiness, use SortBy.EASINESS_SCORE rather than SortBy.AVG_DIFFICULTY.
from rmp_api import SortBy, compare_professors
comparison = compare_professors(professors, sort_by=SortBy.WOULD_TAKE_AGAIN_PCT)
Reference
Scoring functions: compute quality signals and composite scores from rating lists.
compute_score(ratings, weights=None, half_life_days=365.0)
Compute all quality signals for a professor from their Rating list.
Aggregates raw stats, derives recency-weighted and reliability signals,
then combines them into a single composite_score in [0, 1].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
Output of :func: |
required |
weights
|
dict[str, float] | None
|
Score component weights. Use a :data: |
None
|
half_life_days
|
float
|
Recency decay half-life. At |
365.0
|
Returns:
| Type | Description |
|---|---|
ProfessorScore
|
class: |
ProfessorScore
|
zero-valued instance if |
compute_score_over_time(ratings, period=TimePeriod.YEAR, weights=None, half_life_days=365.0)
Bucket ratings by time period and compute a :class:ProfessorScore per bucket.
Useful for detecting whether a professor has improved or declined over time. Buckets with zero dated ratings are skipped. Buckets are returned oldest -> newest.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
Output of :func: |
required |
period
|
TimePeriod | str
|
Bucketing granularity. Use :class:
|
YEAR
|
weights
|
dict[str, float] | None
|
Passed through to each :func: |
None
|
half_life_days
|
float
|
Recency decay half-life passed to each :func: |
365.0
|
Returns:
| Type | Description |
|---|---|
ScoreTimeline
|
class: |
ScoreTimeline
|
a |
ScoreTimeline
|
Returns an empty timeline if no ratings have parseable dates. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
compute_split_score(ratings, weights=None, half_life_days=365.0)
Compute professor scores split by online vs. in-person delivery format.
Runs :func:compute_score three times — once per subset and once for all
ratings combined — so each :class:ProfessorScore reflects only the
ratings relevant to that format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
Output of :func: |
required |
weights
|
dict[str, float] | None
|
Passed through to each :func: |
None
|
half_life_days
|
float
|
Recency decay half-life passed to each
:func: |
365.0
|
Returns:
| Type | Description |
|---|---|
SplitScore
|
class: |
SplitScore
|
fields. Subsets with zero ratings return a zero-valued |
SplitScore
|
class: |
compare_professors(professors, sort_by=SortBy.COMPOSITE_SCORE, weights=None, half_life_days=365.0)
Compute and rank scores for multiple professors side-by-side.
Each professor's full :class:ProfessorScore is computed from their
ratings, then professors are ranked best -> worst on a chosen signal.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
professors
|
dict[str, list[Rating]] | list[tuple[str, list[Rating]]]
|
Professors to compare, supplied as either:
|
required |
sort_by
|
SortBy | str
|
:class: |
COMPOSITE_SCORE
|
weights
|
dict[str, float] | None
|
Weight dict passed to each :func: |
None
|
half_life_days
|
float
|
Recency decay half-life in days passed to each
:func: |
365.0
|
Returns:
| Type | Description |
|---|---|
ProfessorComparison
|
class: |
ProfessorComparison
|
|
ProfessorComparison
|
|
ProfessorComparison
|
|
ProfessorComparison
|
|
ProfessorComparison
|
|
ProfessorComparison
|
Returns a comparison with empty |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Individual signal computers. Each takes a list of Rating objects and returns a normalized metric.
compute_difficulty_histogram(ratings)
Count ratings in each integer difficulty bucket from 1 to 5.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
List of :class: |
required |
Returns:
| Type | Description |
|---|---|
dict[int, int]
|
Dict mapping each bucket |
compute_easiness_score(ratings)
Inverse of average difficulty, normalised to [0, 1].
difficulty = 1 (easiest) -> 1.0; difficulty = 5 -> 0.0.
Ratings with None difficulty are excluded from both sides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
List of :class: |
required |
Returns:
| Type | Description |
|---|---|
float
|
Easiness in |
compute_recency_weighted_rating(ratings, half_life_days=365.0)
Weighted mean of per-rating overall quality, decayed by age.
More recent ratings contribute more to the result. Output stays on the 1–5 scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
List of :class: |
required |
half_life_days
|
float
|
Exponential decay half-life in days. |
365.0
|
Returns:
| Type | Description |
|---|---|
float
|
Recency-weighted mean in |
compute_reliability_score(num_ratings, target=25)
Bayesian confidence score based on sample size.
Uses a logistic curve centred at target ratings:
~0.5 at target, approaches 1 asymptotically, never reaches 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_ratings
|
int
|
Total number of ratings for the professor. |
required |
target
|
int
|
Rating count at which confidence reaches ~0.5 (default |
25
|
Returns:
| Type | Description |
|---|---|
float
|
Confidence score in |
compute_review_velocity(ratings, window_years=2.0)
Average number of reviews posted per year within a rolling window.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
List of :class: |
required |
window_years
|
float
|
How many years back to look (default |
2.0
|
Returns:
| Type | Description |
|---|---|
float
|
Reviews per year as a float, or |
compute_tag_frequencies(ratings)
Aggregate and rank all rating tags across a professor's ratings.
Tags stored as "--"-delimited strings are split automatically;
list-typed tags are used directly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ratings
|
list[Rating]
|
List of :class: |
required |
Returns:
| Type | Description |
|---|---|
list[tuple[str, int]]
|
List of |