Contents
Deep Breakdown
What it tells me (Situation Awareness): A closed interval represents all real numbers from to , with both endpoints included. The square brackets are the signal: they visually "close" or "lock" the boundaries in. In DA/DS you use this for date range filtering ("give me all records from Jan 1 to Dec 31, inclusive"), defining clipping bounds in feature engineering, specifying acceptable ranges for a metric, and in statistical confidence intervals where the boundary values are valid members.
Flowchart
Real-world use
Where it is used
Date range filtering in SQL and pandas, defining the valid range for a numerical feature, clipping outliers to , specifying confidence interval bounds, and defining acceptable input ranges for a model.
Problem it solves
When filtering data, you need to specify precisely whether boundary values count. A sales report for "2023" should include January 1 and December 31. A half-open interval would miss the last day. The closed interval notation removes ambiguity about boundary inclusion.
How it solves the problem
is the mathematical statement: "include , include , and include everything in between." SQL's BETWEEN a AND b is a closed interval. Pandas' .loc[a:b] for DatetimeIndex is also inclusive on both ends.
Example in a business
Clipping a feature (e.g., "session duration in seconds") to a valid range to remove impossible values. Any value is set to , any value is set to , and any value in is left unchanged. This is directly expressed as: keep if .
The formula, piece by piece
Breaking the notation:
- (open square bracket on left): "closed at the lower bound" — include .
- : the lower bound (minimum value in the interval).
- : the upper bound (maximum value in the interval).
- (close square bracket on right): "closed at the upper bound" — include .
- (vertical bar): "such that."
- : the set of all real numbers.
Full set-builder definition:
Read: "The closed interval from to is the set of all real numbers such that is greater than or equal to AND less than or equal to ." Interval family (memorize the bracket/parenthesis convention):
| Notation | Name | Includes ? | Includes ? |
|---|---|---|---|
| Closed | Yes | Yes | |
| Open | No | No | |
| Half-open (left) | Yes | No | |
| Half-open (right) | No | Yes |
The formula in words
" means: is at least (can equal ) AND at most (can equal ). The two conditions must both be true simultaneously." Think of it like a physical door frame: the brackets are the door frame itself. The door includes the frame. Open intervals exclude the frame.
Critical Concepts
- Square bracket = include: and always mean the endpoint is part of the set. Parenthesis means the endpoint is excluded.
- SQL BETWEEN is closed:
WHERE date BETWEEN '2023-01-01' AND '2023-12-31'is equivalent to . - Python range() is NOT closed:
range(a, b)excludes . This is a half-open interval . A common bug source. - Numpy/pandas clipping:
np.clip(x, a, b)maps any to and any to . Values already in are unchanged. This is a closed interval enforcement. - Real vs. integer distinction: over contains infinitely many values (all reals from 2 to 5).
Over (integers), it contains , exactly 4 values.
Step-by-step calculation (tiny example)
Input: interval . Determine which of the following values are in it: .
Step 1: Write the membership condition requires . Both conditions must hold.
Step 2: Test each value
- : ? No. Not in the interval.
- : ? Yes. In the interval (boundary included).
- : ? Yes. In the interval.
- : ? Yes. In the interval (boundary included).
- : ? No. Not in the interval.
Step 3: Summarize Members of : . Non-members: .
Code examples
Beginner example (Python)
# Check membership in a closed interval [a, b]
a = 2
b = 5
test_values = [1, 2, 3.7, 5, 5.1]
for x in test_values:
in_interval = a <= x <= b # Python's chained comparison: clean and readable print(f"x = {x}: in [{a}, {b}] ? {in_interval}") # x = 1: in [2, 5] ? False
# x = 2: in [2, 5] ? True (boundary included)
# x = 3.7: in [2, 5] ? True
# x = 5: in [2, 5] ? True (boundary included)
# x = 5.1: in [2, 5] ? FalseBeginner example (R)
a <- 2
b <- 5
test_values <- c(1, 2, 3.7, 5, 5.1)
in_interval <- test_values >= a & test_values <= b # vectorized, both conditions
print(in_interval) # FALSE TRUE TRUE TRUE FALSE # Named output for clarity
names(in_interval) <- test_values
print(in_interval)Professional example (Python)
import numpy as np
import pandas as pd # Scenario: feature engineering - clip session_duration_seconds to valid range [0, 3600]
np.random.seed(42)
raw_durations = np.random.normal(loc=300, scale=400, size=1000) # many negatives and extremes
DURATION_MIN = 0
DURATION_MAX = 3600 # Clip to closed interval [0, 3600]
clipped_durations = np.clip(raw_durations, DURATION_MIN, DURATION_MAX)
df = pd.DataFrame({ "raw_duration": raw_durations, "clipped_duration": clipped_durations,
})
out_of_range = ((df["raw_duration"] < DURATION_MIN) | (df["raw_duration"] > DURATION_MAX)).sum()
print(f"Values outside [{DURATION_MIN}, {DURATION_MAX}]: {out_of_range}")
print(f"After clipping, min: {clipped_durations.min():.2f}, max: {clipped_durations.max():.2f}")
print(f"All values in [{DURATION_MIN}, {DURATION_MAX}]: {((clipped_durations >= DURATION_MIN) & (clipped_durations <= DURATION_MAX)).all()}")Professional example (R)
# Scenario: feature engineering - clip session_duration_seconds to valid range [0, 3600]
set.seed(42)
raw_durations <- rnorm(1000, mean = 300, sd = 400)
DURATION_MIN <- 0
DURATION_MAX <- 3600 # Clip to closed interval [0, 3600]
clipped_durations <- pmin(pmax(raw_durations, DURATION_MIN), DURATION_MAX)
df <- data.frame( raw_duration = raw_durations, clipped_duration = clipped_durations
) out_of_range <- sum(df$raw_duration < DURATION_MIN | df$raw_duration > DURATION_MAX)
cat("Values outside [", DURATION_MIN, ", ", DURATION_MAX, "]: ", out_of_range, "\n", sep = "")
cat(sprintf("After clipping, min: %.2f, max: %.2f\n", min(clipped_durations), max(clipped_durations)))
cat("All values in [0, 3600]:", all(clipped_durations >= DURATION_MIN & clipped_durations <= DURATION_MAX), "\n")Source: 1300 p. 13