While most users interact with laps through the high-level
Session and Driver APIs, understanding these operations enables advanced analysis workflows, custom filtering logic, performance-optimized data processing, and the ability to build sophisticated F1 data applications. This guide covers both the public API methods and internal utilities that power tif1’s lap data processing.Overview
Lap operations in tif1 encompass several categories of functionality, each designed to address specific aspects of lap data processing and analysis:Core Utilities (Low-Level Operations)
These foundational functions provide the building blocks for all lap data operations:- Type Coercion: Robust conversion of lap numbers and lap times from various input formats (strings, floats, integers) to standardized types with comprehensive error handling
- Data Extraction: Fast extraction of lap numbers from DataFrames using optimized algorithms for membership checks and validation
- Column Resolution: Intelligent column name resolution with fallback logic to handle different data source formats and naming conventions
- DataFrame Validation: Empty-check utilities and data quality validation to ensure reliable data processing
- Performance Optimization: Zero-copy operations and vectorized processing for maximum throughput
High-Level Filtering Methods (Laps Class API)
TheLaps class provides a rich set of filtering methods that enable intuitive, chainable queries:
- Driver and Team Selection: Flexible identifier matching supporting driver codes, racing numbers, team names, and driver objects
- Lap Number Filtering: Single lap, range selection, slice notation, and list-based filtering
- Lap Time Filtering: Fastest lap identification, quicklaps (within percentage threshold), personal bests, and time-based queries
- Tire Strategy Filtering: Compound selection (soft/medium/hard/intermediate/wet), fresh tire filtering, and tire life-based queries
- Track Status Filtering: Green flag laps, yellow flag exclusion, safety car periods, VSC periods, and red flag sessions
- Pit Stop Filtering: In-laps, out-laps, clean laps (no pit activity), and pit window analysis
- Data Quality Filtering: Deleted lap exclusion, accuracy flag filtering, and synthetic lap identification
- Stint Analysis: Stint-based filtering, tire life within stint, and multi-stint comparisons
Data Transformation Operations
Transform lap data for analysis, visualization, and reporting:- Time Format Conversions: Convert between seconds (float), timedelta objects, and human-readable formatted strings (MM:SS.mmm)
- Delta Calculations: Compute deltas to fastest lap, previous lap, session leader, or custom reference points
- Cumulative Metrics: Calculate cumulative time, distance, and other aggregated values across laps
- Aggregation Operations: Group by stint, driver, compound, track status, or custom groupings with statistical summaries
- Qualifying Session Splitting: Automatically separate Q1, Q2, and Q3 sessions for qualifying analysis
- Telemetry Integration: Seamless retrieval and merging of telemetry data with lap timing information
Advanced Analysis Capabilities
Build sophisticated analysis workflows:- Tire Degradation Analysis: Calculate degradation rates, identify cliff points, and compare compound performance
- Driver Comparison: Head-to-head lap time comparisons, consistency analysis, and performance profiling
- Optimal Lap Identification: Find the fastest lap under ideal conditions (green flag, fresh tires, no traffic)
- Race Pace Analysis: Analyze race pace by stint, fuel load, and track conditions
- Stint Strategy Evaluation: Compare stint lengths, compound choices, and pit stop timing
- Statistical Analysis: Calculate percentiles, standard deviations, and other statistical measures
- Time Series Analysis: Analyze lap time evolution, identify trends, and detect anomalies
Understanding Lap Data Structure
Before diving into operations, it’s essential to understand the comprehensive structure of lap data in tif1. Each lap is represented as a row in a DataFrame, with columns organized into logical categories. The availability of specific columns depends on the session type (Practice, Qualifying, Race), the year of the data, and the data source.Core Timing Columns
These columns form the foundation of lap timing data and are present in virtually all sessions:-
LapNumber (
int): Integer lap number, 1-indexed. This is the primary identifier for laps within a session. In qualifying sessions, lap numbers continue incrementing across Q1, Q2, and Q3. -
LapTime (
float): Lap time in seconds with millisecond precision (e.g.,83.456represents 1:23.456). This is the primary timing metric used for all comparisons and analysis. NaN values indicate incomplete or invalidated laps. -
LapTimeSeconds (
float): Alternative representation of lap time in seconds. In most cases, this is identical toLapTime. Some data sources use this column name instead ofLapTime. -
Time (
timedeltaorfloat): Session time when the lap was completed, measured from the start of the session. This can be either a pandas Timedelta object or a float representing seconds. Used for temporal analysis and synchronization with other session data. -
LapStartTime (
timedeltaorfloat): Session time when the lap started. Calculated asTime - LapTime. Essential for analyzing lap-by-lap progression and identifying when specific laps occurred during the session. -
LapStartDate (
datetime): Absolute date and time when the lap started, in the session’s local timezone. Useful for correlating lap data with external events, weather changes, or broadcast footage.
Sector and Speed Columns
Sector times and speed trap measurements provide detailed performance insights:-
Sector1Time (
float): Time in seconds to complete sector 1. Sector 1 typically covers the start/finish straight and the first sequence of corners. -
Sector2Time (
float): Time in seconds to complete sector 2. Sector 2 usually includes the middle portion of the circuit. -
Sector3Time (
float): Time in seconds to complete sector 3. Sector 3 covers the final section leading back to the start/finish line. -
Sector1SessionTime (
timedeltaorfloat): Session time when sector 1 was completed. Used for synchronizing sector performance with session events. -
Sector2SessionTime (
timedeltaorfloat): Session time when sector 2 was completed. -
Sector3SessionTime (
timedeltaorfloat): Session time when sector 3 was completed.
-
SpeedI1 (
float): Speed trap measurement at intermediate point 1, in km/h. Location varies by circuit but typically measures speed at a key straight or corner exit. -
SpeedI2 (
float): Speed trap measurement at intermediate point 2, in km/h. Provides additional speed data for performance analysis. -
SpeedFL (
float): Speed at the finish line, in km/h. Measured as the car crosses the timing line to complete the lap. -
SpeedST (
float): Speed at the designated speed trap location, in km/h. This is typically the fastest point on the circuit, usually on the main straight.
Sector times should sum to approximately the lap time, but small discrepancies (typically < 0.1s) can occur due to timing system precision and rounding. Speed trap data may be missing for some laps, especially during yellow flag periods or pit stops.
Driver and Team Columns
Identification columns for drivers and teams:-
Driver (
str): Three-letter driver code following FIA conventions (e.g., “VER” for Max Verstappen, “HAM” for Lewis Hamilton, “LEC” for Charles Leclerc). This is the primary identifier for driver-based filtering and analysis. -
DriverNumber (
int): Racing number assigned to the driver (e.g., 1, 44, 16). Racing numbers are permanent and follow drivers across teams. Useful for identifying drivers across different seasons. -
Team (
str): Full team name as registered with the FIA (e.g., “Red Bull Racing”, “Mercedes”, “Ferrari”). Team names may change between seasons due to rebranding or ownership changes.
Tire Strategy Columns
Comprehensive tire and strategy information:-
Compound (
str): Tire compound used for the lap. Values include:"SOFT": Soft compound (red sidewall) - fastest but degrades quickly"MEDIUM": Medium compound (yellow sidewall) - balanced performance and durability"HARD": Hard compound (white sidewall) - most durable but slowest"INTERMEDIATE": Intermediate wet weather tire (green sidewall)"WET": Full wet weather tire (blue sidewall)"UNKNOWN": Compound information not available
-
TyreLife (
int): Number of laps completed on the current tire set, including the current lap. Starts at 1 for the first lap on a new set. Essential for tire degradation analysis. -
FreshTyre (
bool): Boolean flag indicating whether the tires were fresh (unused) at the start of this lap.Truefor the first lap on a new set,Falsefor subsequent laps. Used to identify qualifying runs and optimal performance laps. -
Stint (
int): Stint number, 1-indexed. Increments each time the driver makes a pit stop for new tires. Stint 1 is the opening stint from the race start or session beginning.
Tire compound data is most reliable in race sessions. In practice and qualifying, compound information may be incomplete or missing, especially in older seasons. The
FreshTyre flag is particularly useful for identifying qualifying push laps.Track and Session Columns
Track conditions and session context:-
TrackStatus (
str): Track status code indicating racing conditions. This is a string representation of numeric codes:"1": Green flag - normal racing conditions, all clear"2": Yellow flag - caution, incident on track, no overtaking"4": Safety car deployed - all cars must slow down and bunch up"5": Red flag - session stopped, cars must return to pits"6": Virtual safety car (VSC) - electronic speed limiting, no physical safety car"7": VSC ending - transition period as track returns to green flag
"2"and"4"together). Always check for the presence of specific codes rather than exact equality. -
Position (
int): Driver’s position at the completion of this lap. In qualifying, this represents the current standing based on best lap times. In races, this is the running order position. -
QualifyingSession (
str): Qualifying session identifier, present only in qualifying sessions:"Q1": First qualifying session (all 20 drivers)"Q2": Second qualifying session (top 15 drivers)"Q3": Third qualifying session (top 10 drivers)
Noneor missing for practice and race sessions.
Pit Stop Columns
Pit stop timing and activity:-
PitOutTime (
timedeltaorfloat): Session time when the driver exited the pit lane after a pit stop.NaNorNoneif the lap did not include a pit exit. Used to identify out-laps and calculate pit stop duration. -
PitInTime (
timedeltaorfloat): Session time when the driver entered the pit lane for a pit stop.NaNorNoneif the lap did not include a pit entry. Used to identify in-laps and analyze pit stop timing.
- In-lap: A lap where
PitInTimeis not NaN - the driver entered the pits during this lap - Out-lap: A lap where
PitOutTimeis not NaN - the driver exited the pits during this lap - Clean lap: A lap where both
PitInTimeandPitOutTimeare NaN - no pit activity - Pit stop duration: Can be calculated by comparing
PitOutTimewith thePitInTimeof the previous lap
In-laps and out-laps typically have significantly slower lap times due to pit lane speed limits (usually 60-80 km/h depending on the circuit). Always exclude these laps when analyzing representative race pace.
Data Quality Columns
Flags indicating data quality and validity:-
Deleted (
bool): Boolean flag indicating whether the lap was deleted or invalidated by race control.Truemeans the lap time does not count (e.g., due to track limits violation, red flag, or other infringement).FalseorNonemeans the lap is valid. -
DeletedReason (
str): Human-readable reason for lap deletion, if available. Common reasons include:- Track limits violation (exceeding track boundaries)
- Red flag (session stopped)
- Pit lane infringement
- Impeding another driver
- Missing transponder data
-
IsPersonalBest (
bool): Boolean flag indicating whether this lap is the driver’s personal best (fastest lap) in the session. Only one lap per driver should have this flag set toTrue. -
IsAccurate (
bool): Boolean flag indicating data accuracy and reliability.Truemeans the lap data is complete and accurate.Falsemay indicate missing sector times, interpolated data, or other quality issues. -
FastF1Generated (
bool): Boolean flag indicating whether the lap was synthetically generated to fill gaps in the data.Truemeans the lap is not from actual timing data but was created for continuity. AlwaysFalsein tif1 data sources.
Weather Columns (Per-Lap)
Weather conditions at the time of each lap:-
WeatherTime (
datetime): Timestamp of the weather measurement, typically synchronized with lap completion time. -
AirTemp (
float): Air temperature in degrees Celsius (°C). Affects engine performance and tire behavior. -
TrackTemp (
float): Track surface temperature in degrees Celsius (°C). Critical for tire performance and degradation rates. Track temperature can vary significantly from air temperature, especially in sunny conditions. -
Humidity (
float): Relative humidity as a percentage (0-100%). Affects air density and engine performance. -
Pressure (
float): Atmospheric pressure in millibars (mbar). Standard atmospheric pressure is approximately 1013 mbar. Lower pressure at high-altitude circuits affects engine performance. -
Rainfall (
bool): Boolean flag indicating whether rain was detected.Truemeans rain is falling,Falsemeans dry conditions. -
WindSpeed (
float): Wind speed in kilometers per hour (km/h). Affects car balance and straight-line speed. -
WindDirection (
int): Wind direction in degrees (0-360), where 0° is north, 90° is east, 180° is south, and 270° is west. Combined with circuit layout, this determines headwind/tailwind effects.
Column Availability Matrix
Not all columns are present in all sessions. Here’s a general guide:
✅ = Typically available | ⚠️ = Partially available | ❌ = Not available
Low-Level Utility Functions
These internal functions provide the foundation for lap data operations throughout the tif1 library. While primarily used internally, they’re exposed in the public API for advanced use cases requiring custom data processing pipelines, integration with external systems, or performance-critical applications. Understanding these utilities is valuable for:- Building custom data validation pipelines
- Integrating tif1 with other data analysis frameworks
- Debugging data quality issues
- Optimizing performance-critical code paths
- Extending tif1 with custom functionality
_coerce_lap_number
Converts various lap number representations to a standardized integer format with comprehensive error handling and validation.
lap_value(Any): Lap number in various formats:- Integer: Direct passthrough with no conversion (e.g.,
19→19) - Float: Converted to integer via truncation (e.g.,
19.0→19,19.7→19) - String: Parsed to integer, whitespace is automatically stripped (e.g.,
"19"→19," 19 "→19) - NumPy integers: Converted from numpy.int32, numpy.int64, etc. to Python int
- Other numeric types: Coerced via
int()constructor (e.g., Decimal, Fraction)
- Integer: Direct passthrough with no conversion (e.g.,
int: Standardized integer lap number, guaranteed to be a Pythoninttype
ValueError: Raised in the following cases:- Input is
None(message:"No lap number found in row")- This typically indicates missing data in the source
- Common when processing incomplete lap records
- Input cannot be converted to integer (message:
"Invalid lap number: {value}")- Raised for non-numeric strings like
"invalid","N/A","" - Raised for complex numbers, objects without numeric conversion
- Raised for non-numeric strings like
- Input is a non-numeric string (message:
"Invalid lap number: {value}")- Includes strings with letters, special characters, or mixed content
- Input is
int() constructor for conversion, which handles most numeric types automatically through the __int__() protocol. The error messages are designed to be informative for debugging data quality issues, including the problematic value in the error message.
Type Conversion Behavior:
- Truncation, not rounding: Float values are truncated, not rounded (e.g.,
19.9→19, not20) - Whitespace handling: Leading and trailing whitespace in strings is automatically stripped
- Scientific notation: Strings in scientific notation are supported (e.g.,
"1.9e1"→19) - Negative numbers: Negative lap numbers are technically allowed but will cause issues in most tif1 operations
-
Validating user input for lap number queries:
-
Normalizing lap numbers from mixed-type data sources:
-
Ensuring type safety in lap filtering operations:
-
Data quality checks in ETL pipelines:
- Direct type checking: Uses
int()constructor directly rather than complex validation logic - No unnecessary copies: Returns the input directly if it’s already an integer
- Fast-path for common types: Integer and float inputs are handled with minimal overhead
- Efficient error handling: Exceptions are only raised for truly invalid inputs
- Integer input: ~50 nanoseconds
- Float input: ~100 nanoseconds
- String input: ~200 nanoseconds
- Invalid input (exception): ~5 microseconds
_extract_lap_numbers
Extract all unique lap numbers from a DataFrame with optimized performance for fast membership checks and validation operations.
-
laps(DataFrame): DataFrame with lap data containing eitherLapNumberorlapcolumn- Can be a pandas DataFrame or polars DataFrame/LazyFrame
- Must contain at least one lap number column
- Can contain invalid or missing lap numbers (they will be skipped)
-
lib(str): Backend library identifier"pandas": Use pandas-optimized extraction"polars": Use polars-optimized extraction- Must match the actual DataFrame type
set[int]: Set of unique lap numbers found in the DataFrame- Empty set if DataFrame is empty or contains no valid lap numbers
- Set provides O(1) membership testing:
if 19 in lap_numbers: - Unordered collection (use
sorted()if order matters)
- Uses
to_numpy(copy=False)for zero-copy array extraction - Iterates through numpy array for maximum speed
- Skips invalid values without raising exceptions
- Uses
get_column().to_list()for efficient column extraction - Leverages polars’ optimized column access
- Handles LazyFrame evaluation automatically
- First tries
LapNumber(standard tif1 column name) - Falls back to
lap(alternative column name for compatibility) - Returns empty set if neither column exists
- Invalid lap numbers (non-numeric, None, NaN) are silently skipped
- Empty DataFrames return empty set
- Missing columns return empty set
- No exceptions raised for data quality issues
-
Fast membership testing:
-
Data completeness validation:
-
Lap range validation:
-
Batch lap existence checks:
- Extraction: O(n) where n is the number of rows
- Set construction: O(n) average case
- Membership testing: O(1) after extraction
- O(k) where k is the number of unique lap numbers
- Typically k << n (e.g., 60 unique laps vs 1200 total lap records)
- 1,000 rows: ~0.5 milliseconds
- 10,000 rows: ~3 milliseconds
- 100,000 rows: ~25 milliseconds
- Pandas: Zero-copy array extraction (no data duplication)
- Polars: Efficient column access with minimal overhead
- Set storage: ~28 bytes per unique lap number (Python 3.10+)
Lap Time Operations
_coerce_lap_time
Convert lap time values to standardized float seconds with strict validation and NaN rejection.
_coerce_lap_number, this function explicitly rejects NaN values because a lap without a valid time is meaningless for analysis.
The function is designed to fail-fast on invalid data, helping identify data quality issues early in the processing pipeline. This is particularly important for lap time analysis where invalid times can significantly skew statistical calculations.
Parameters:
lap_time_value(Any): Lap time in various formats:- Float: Direct passthrough if valid (e.g.,
83.456) - Integer: Converted to float (e.g.,
83→83.0) - String: Parsed to float (e.g.,
"83.456"→83.456) - Timedelta: Converted to total seconds (if applicable)
- Other numeric types: Coerced via
float()constructor
- Float: Direct passthrough if valid (e.g.,
float: Lap time in seconds with millisecond precision- Guaranteed to be a valid, non-NaN float
- Typically in range 60.0-120.0 seconds for F1 circuits
- Values outside normal range are allowed but may indicate data issues
ValueError: Raised in the following cases:- Input is
None(message:"No lap time found in row") - Input cannot be converted to float (message:
"Invalid lap time: {value}") - Input is NaN after conversion (message:
"Invalid lap time: {value}") - Input is a non-numeric string (message:
"Invalid lap time: {value}")
- Input is
float() constructor for conversion, followed by an explicit math.isnan() check to reject NaN values. This two-step validation ensures that only valid, usable lap times pass through.
Type Conversion Behavior:
- Precision preservation: Float values maintain full precision
- Integer conversion: Integers are converted to float (e.g.,
83→83.0) - String parsing: Supports decimal notation and scientific notation
- NaN rejection: Explicitly rejects
float('nan'),np.nan, and similar values - Infinity handling:
float('inf')andfloat('-inf')are technically allowed but will cause issues
-
Validating lap time data:
-
Filtering valid lap times:
-
Data quality validation:
- Direct conversion: Uses
float()constructor with minimal overhead - Single NaN check: Only one
math.isnan()call per invocation - No unnecessary copies: Returns the converted value directly
- Fast exception path: Exceptions are only raised for truly invalid inputs
- Valid float input: ~80 nanoseconds
- Integer input: ~120 nanoseconds
- String input: ~250 nanoseconds
- Invalid input (exception): ~5 microseconds
Column Operations
_get_lap_column
Get the lap number column name with intelligent fallback logic for cross-compatibility with different data sources and naming conventions.
LapNumber), then falls back to alternative names (lap) used by other libraries or data sources.
Parameters:
-
df(DataFrame): DataFrame with lap data- Can be pandas DataFrame or polars DataFrame/LazyFrame
- Must contain at least one lap number column
- Column names are case-sensitive
-
lib(str): Backend library identifier"pandas": Pandas DataFrame"polars": Polars DataFrame/LazyFrame- Used for backend-specific column access optimizations
str: Column name string to use for lap number access"LapNumber": Standard tif1 column name (preferred)"lap": Alternative column name (fallback for compatibility)- Guaranteed to exist in the DataFrame
KeyError: Implicitly raised if neither column exists when the returned name is used- This is intentional - the function returns a name, validation happens at use time
- Allows for lazy evaluation and deferred error handling
- Check if
"LapNumber"exists in DataFrame columns - If yes, return
"LapNumber" - If no, return
"lap"(assumed to exist)
-
LapNumber: Standard tif1 column name- Used in all tif1-generated DataFrames
- PascalCase following tif1 naming conventions
- Preferred for new code and data sources
-
lap: Alternative column name- Used by some legacy data sources
- Lowercase following different naming conventions
- Supported for backward compatibility
-
Backend-agnostic lap filtering:
-
Dynamic column access:
-
Cross-source data processing:
-
Validation and debugging:
- Time complexity: O(1) - simple column existence check
- Space complexity: O(1) - returns a string reference
- Overhead: < 100 nanoseconds per call
Filtering Laps
By Lap Number
By Lap Time
By Compound
By Track Status
By Stint
Transforming Lap Data
Convert Lap Times
Calculate Deltas
Aggregate by Stint
Analyze Tire Degradation
Compare Lap Times
Best Practices
- Filter before operations: Reduce data size for faster processing.
- Use vectorized operations: Avoid loops when possible.
- Check for empty results: Always validate filtered data.
- Use appropriate data types: Convert lap times to timedelta for time operations.
- Handle missing data: Check for NaN values.
-
Use vectorized operations: Avoid loops when possible, leverage pandas/polars vectorization
-
Check for empty results: Always validate filtered data before processing
-
Cache expensive operations: Store results of expensive computations for reuse
-
Use appropriate data types: Convert to timedelta for time operations, keep as float for calculations
-
Handle missing data: Check for NaN values and missing columns
-
Chain filtering methods: Use method chaining for readable, efficient filtering
Common Patterns
Finding the Optimal Lap:Integration with Other Modules
The lap operations module integrates seamlessly with other tif1 components: Session API:Error Handling
The lap operations module uses a consistent error handling strategy: ValueError: Raised for invalid data (non-numeric lap numbers, NaN lap times)Thread Safety
All utility functions are thread-safe for read-only operations:_coerce_lap_number: Thread-safe, no shared state_coerce_lap_time: Thread-safe, no shared state_extract_lap_numbers: Thread-safe for read-only DataFrames_get_lap_column: Thread-safe, read-only operation
Backend Compatibility
The lap operations module supports both pandas and polars backends: Pandas:Future Enhancements
Potential future additions to the lap operations module:- Advanced statistical analysis (confidence intervals, hypothesis testing)
- Machine learning integration (lap time prediction, anomaly detection)
- Real-time streaming data support
- GPU-accelerated operations for large datasets
- Additional filtering methods based on user feedback
Additional Resources
- API Reference: Complete API documentation for all methods
- Examples: Comprehensive examples in the
examples/directory - Tutorials: Step-by-step tutorials for common use cases
- Performance Guide: Optimization tips and benchmarking results
- Migration Guide: Upgrading from FastF1 or other libraries
Getting Help
If you encounter issues or have questions:- Check the documentation for examples and best practices
- Review the error messages for specific guidance
- Consult the FAQ for common issues
- Open an issue on GitHub for bugs or feature requests
- Join the community Discord for real-time help
Conclusion
The lap operations module provides everything you need for professional-grade Formula 1 lap data analysis. Whether you’re building a simple lap time comparison tool or a sophisticated race strategy analyzer, these utilities offer the performance, reliability, and flexibility required for production applications. By understanding and leveraging these operations, you can:- Process lap data efficiently with minimal overhead
- Build robust analysis pipelines with proper error handling
- Create reusable components for common analysis tasks
- Optimize performance for large datasets
- Integrate seamlessly with the broader tif1 ecosystem