이것저것

Formula 1 2024년 영국 GP 타이어 성능 분석

sam_j_s 2024. 7. 15. 04:33
728x90
반응형

주제

2024년 영국 그랑프리는 영국인 드라이버들이 처음으로 프런트 그리드를 차지한 역사적인 경기였습니다. 또한, 루이스 해밀턴은 이 경기에서 자신의 199번째 포디움이자 104번째 우승을 달성했습니다.

 

이번 그랑프리에서는 경기 전에 비가 오다 그치기도 했고, 경기 중에도 비가 내렸다가 그치는 등 날씨가 변덕스러웠습니다. 이러한 날씨 조건 때문에 언제 인터미디어 타이어로 바꾸고 언제 다시 슬릭 타이어로 교체할지에 대한 변수가 많았습니다.

To Box, or not to Box?

 

따라서 이번 영국 그랑프리에서는 각 랩의 어느 부분에서 어떤 타이어가 더 나은 성능을 발휘했는지 살펴보겠습니다.

 

시각화

필요한 패키지 임포트

import fastf1 as ff1
from fastf1 import plotting
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
from matplotlib import cm
import numpy as np
import pandas as pd
import os

 

영국 그랑프리 데이터 가져오기

# Plotting 설정
plotting.setup_mpl()

# 캐시 활성화
ff1.Cache.enable_cache('cache')  # 'cache' 폴더에 데이터 저장

# Pandas 경고 비활성화
pd.options.mode.chained_assignment = None

# 2024 영국 그랑프리 데이터 로드
race = ff1.get_session(2024, 'British', 'R')

# 세션 데이터 로드
race.load()

 

플로팅 기능을 활성화하고, 캐시를 활성화하며, 몇 가지 작은 설정을 변경합니다.

 

그다음, 2024년 영국 그랑프리 레이스 세션 데이터를 불러와서 'cache' 폴더에 저장합니다.

랩 데이터 처리

# 랩 데이터 로드
laps = race.laps

# RaceLapNumber 계산
laps['RaceLapNumber'] = laps['LapNumber'] - 1

# 모든 드라이버 리스트
drivers = pd.unique(laps['Driver'])

telemetry = pd.DataFrame()

 

로드된 데이터 세션에서 랩 데이터를 가져와줍니다.'race.laps'는 레이스 중 각 드라이버의 랩 정보를 포함한 데이터프레임을 반환합니다.

'LapNumber'에는 워밍업 랩이 포함되어 있으므로 1랩을 지워주겠습니다.

 

원격 측정 데이터 수집

이제 드라이버별로 원격 측정 데이터를 수집합니다.

for driver in drivers:
    driver_laps = laps.pick_driver(driver)
    
    for _, lap in driver_laps.iterrows():
        telemetry_data = race.laps.pick_driver(driver).pick_lap(lap['LapNumber']).get_telemetry().copy()
        telemetry_data = telemetry_data.add_distance()
        
        # 데이터 타입 일관성 유지
        telemetry_data = telemetry_data.astype({
            'X': float,
            'Y': float,
            'Z': float,
            'Speed': float,
            'Distance': float
        })
        
        telemetry_data['Driver'] = driver
        telemetry_data['Lap'] = lap['RaceLapNumber']
        telemetry_data['Compound'] = lap['Compound']
        
        # telemetry와 telemetry_data의 데이터 타입 일치시키기
        telemetry_data = telemetry_data.astype({
            'Lap': int,
            'Distance': float,
            'Speed': float,
            'X': float,
            'Y': float,
            'Compound': str,
            'Driver': str
        })
        
        telemetry = pd.concat([telemetry, telemetry_data], ignore_index=True)

# 필요한 열만 선택
telemetry = telemetry[['Lap', 'Distance', 'Compound', 'Speed', 'X', 'Y']]
telemetry = telemetry.astype({
    'Lap': int,
    'Distance': float,
    'Speed': float,
    'X': float,
    'Y': float,
    'Compound': str
})

# "INTERMEDIATE"가 아닌 모든 타이어를 "SLICK"으로 변환
telemetry.loc[telemetry['Compound'] != 'INTERMEDIATE', 'Compound'] = 'SLICK'

 

Fastf1 패키지는 드라이버별로 원격 측정 데이터를 제공하므로, 모든 드라이버에 대해 데이터를 수집해야 합니다.

먼저 모든 드라이버를 반복합니다. 그런 다음 해당 드라이버에 속하는 랩을 선택합니다. 원격 측정 데이터를 랩별로 비교할 수 있도록 Fastf1의 내장 함수인 'iterlaps'를 사용하여 그 드라이버의 모든 랩을 반복합니다.

이제 단일 드라이버의 단일 랩이 변수 lap에 저장되므로, 원격 측정 데이터와 랩 거리를 로드할 수 있습니다. 마지막으로 원격 측정 데이터에 자동으로 포함되지 않는 몇 가지 정보(driver, RaceLapNumber, Compound)를 추가합니다.

이제 모든 원격 측정 데이터를 수집했으므로, 두 가지 작은 수정이 남았습니다. 필요한 열만 선택하고, 모든 Hard, Medium, Soft 타이어를 SLICK으로 변환하면 됩니다.

미니 섹터 생성 및 가장 빠른 컴파운드 계산

# 미니 섹터 수 설정
num_minisectors = 25

# 한 랩의 총 거리 계산
total_distance = max(telemetry['Distance'])

# 미니 섹터 길이 계산
minisector_length = total_distance / num_minisectors

# 미니 섹터 경계 설정
minisectors = [0]
for i in range(0, (num_minisectors - 1)):
    minisectors.append(minisector_length * (i + 1))

# 각 원격 측정 데이터 포인트에 미니 섹터 할당
telemetry['Minisector'] = telemetry['Distance'].apply(
    lambda x: np.digitize(x, minisectors)
)

# 각 미니 섹터에서 평균 속도 계산
average_speed = telemetry.groupby(['Lap', 'Minisector', 'Compound'])['Speed'].mean().reset_index()

 

이제 데이터를 올바른 형식으로 준비했으므로, 각 랩의 어느 지점에서 어떤 타이어가 가장 빠른지 살펴볼 수 있습니다. 이를 위한 방법론은 다음과 같습니다.

 

첫째, 랩을 25개의 동일한 크기의 미니 섹터로 나눕니다. 이를 위해 먼저 num_minisectors 변수를 25로 설정하고, 랩의 총거리를 계산한 후, 이를 미니 섹터의 개수로 나누어 각 미니 섹터의 길이를 구합니다. 그런 다음, 각 미니 섹터의 경계를 설정합니다.

 

둘째,  원격 측정 데이터의 각 행에 미니 섹터를 할당하는 것입니다. 원격 측정 데이터프레임에 Minisector라는 열을 생성하고, Distance 열에 저장된 값을 기반으로 해당 데이터 포인트가 어느 미니 섹터에 속하는지 할당합니다. np.digitize 함수를 사용하여 거리를 기준으로 해당 값이 미니 섹터 목록의 어느 인덱스에 속하는지 계산하여 인덱스 번호를 반환합니다.

 

이제 각 미니 섹터에서 평균 속도를 계산할 수 있습니다. telemetry 데이터프레임을 랩, 미니 섹터, 컴파운드별로 그룹화하고, 각 그룹의 평균 속도를 계산합니다. reset_index()를 사용하여 결과를 데이터프레임 형식으로 반환합니다.

# 가장 빠른 타이어 컴파운드 선택
fastest_compounds = average_speed.loc[average_speed.groupby(['Lap', 'Minisector'])['Speed'].idxmax()]
fastest_compounds = fastest_compounds[['Lap', 'Minisector', 'Compound']].rename(columns={'Compound': 'Fastest_compound'})

# 가장 빠른 타이어 컴파운드와 원격 측정 데이터 병합
telemetry = telemetry.merge(fastest_compounds, on=['Lap', 'Minisector'])

# 거리별로 데이터 정렬
telemetry = telemetry.sort_values(by=['Distance'])

# 타이어 컴파운드에 정수 값 할당
telemetry.loc[telemetry['Fastest_compound'] == "INTERMEDIATE", 'Fastest_compound_int'] = 1
telemetry.loc[telemetry['Fastest_compound'] == "SLICK", 'Fastest_compound_int'] = 2

 

이제 각 미니 섹터에서 가장 빠른 타이어 컴파운드를 선택해 주겠습니다. 'average_speed'에서 각 랩의 미니 섹터별로 가장 높은 평균 속도를 기록한 타이어 컴파운드를 선택합니다. 이를 통해 'fastest_compounds'를 생성합니다.

 

다음으로, 'fastest_compounds'에 원래의 'telemetry'데이터와 병합하여 각 원격 측정 데이터 포인트에 대해 해당 미니 섹터에서 가장 빠른 타이어 컴파운드 정보를 추가합니다. 병합 후에는 데이터를 'Distance'열을 기준으로 정렬하여 각 랩의 거리 순서대로 데이터를 배열합니다.

 

마지막으로, 'telemetry'데이터프레임에 있는 'fastest_compound'열에 정수 값을 할당합니다. 인터미디어 타이어는 1, 슬릭 타이어는 2로 변환합니다. 

데이터 시각화

def generate_minisector_plot(lap, save=False, details=True):
    single_lap = telemetry.loc[telemetry['Lap'] == lap]

    x = np.array(single_lap['X'].values)
    y = np.array(single_lap['Y'].values)

    points = np.array([x, y]).T.reshape(-1, 1, 2)
    segments = np.concatenate([points[:-1], points[1:]], axis=1)
    compound = single_lap['Fastest_compound_int'].to_numpy().astype(float)

    cmap = plt.get_cmap('ocean', 2)
    lc_comp = LineCollection(segments, norm=plt.Normalize(1, cmap.N + 1), cmap=cmap)
    lc_comp.set_array(compound)
    lc_comp.set_linewidth(2)

    plt.rcParams['figure.figsize'] = [12, 5]

    if details:
        title = plt.suptitle(
            f"2024 British GP \n Lap {lap} - Slicks vs. Inters"
        )

    plt.gca().add_collection(lc_comp)
    plt.axis('equal')
    plt.tick_params(labelleft=False, left=False, labelbottom=False, bottom=False)

    if details:
        cbar = plt.colorbar(mappable=lc_comp, boundaries=np.arange(1, 4))
        cbar.set_ticks([1.5, 2.5])
        cbar.set_ticklabels(['Inters', 'Slicks'])

    if save:
        # 저장할 디렉토리가 존재하지 않으면 생성
        os.makedirs('img', exist_ok=True)
        plt.savefig(f"img/bri/minisectors_lap_{lap}.png", dpi=300)

    plt.show()

 

이 함수는 특정 랩의 원격 측정 데이터를 기반으로 트랙의 각 미니 섹터에서 사용된 타이어 컴파운드를 색상으로 구분하여 시각화를 해줍니다. 함수는 다음과 같은 단계로 구성됩니다.

 

먼저, telemetry 데이터프레임에서 특정 랩의 데이터를 선택합니다. 선택된 데이터에서 X와 Y 좌표를 추출하여 점을 생성하고, 이를 연결하여 세그먼트를 형성합니다. 그런 다음, 각 세그먼트에 해당하는 타이어 컴파운드를 색상으로 지정합니다.

 

시각화는 Matplotlib의 LineCollection을 사용하여 트랙의 모양을 형성하고, 각 미니 섹터의 색상을 지정합니다. 이를 통해 각 미니 섹터에서 어떤 타이어가 사용되었는지 시각적으로 구분할 수 있습니다.

 

마지막으로, 시각화를 저장하고 화면에 표시합니다. 저장할 디렉토리가 존재하지 않으면 생성합니다.

# 15랩부터 52랩까지 플롯 생성
for lap in range(15, 53):
    generate_minisector_plot(lap, save=True, details=True)

이렇게 2024년 영국 그랑프리 데이터를 분석해 보았습니다. 각 랩에서 어떤 타이어가 어느 구간에서 더 빨랐는지 시각적으로 확인할 수 있었습니다.

반응형

'이것저것' 카테고리의 다른 글

르끌레르의 모나코 그링프리 간단한 시각화  (0) 2024.07.13

'이것저것'의 다른글

  • 현재글 Formula 1 2024년 영국 GP 타이어 성능 분석

관련글