Visualization of F1 driver standings​
​By Kotaro Okazaki
The 2021 FIA Formula One World Championship was contested over twenty - two Grands Prix and held around the world. After a fierce battle for championship between Max Verstappen and Lewis Hamilton, Verstappen won his first World Championship. Hamilton, the defending champion, finished runner-up.
I implemented the visualization of the battle with the BarChartRace which has been often seen on SNS and other media these days.
Out[]=

Base URLs

In[]:=
baseURL="https://www.formula1.com/en/results.html/";​​driversURL[year_]:=URL[baseURL<>StringTemplate["``/drivers.html"][year]];

Final result

Show the final result in 2021 as follows.
In[]:=
year=2021;​​Grid[​​Join[{{"rank","driver","country","team","point"}},​​Import[driversURL[year],"Data"][[3,2]][[2]]],Background{None,{LightGray}},Alignment{{Right,Left,Center,Left,"."}}]
Out[]=
rank
driver
country
team
point
1
Max Verstappen VER
NED
Red Bull Racing Honda
395.5
2
Lewis Hamilton HAM
GBR
Mercedes
387.5
3
Valtteri Bottas BOT
FIN
Mercedes
226
4
Sergio Perez PER
MEX
Red Bull Racing Honda
190
5
Carlos Sainz SAI
ESP
Ferrari
164.5
6
Lando Norris NOR
GBR
McLaren Mercedes
160
7
Charles Leclerc LEC
MON
Ferrari
159
8
Daniel Ricciardo RIC
AUS
McLaren Mercedes
115
9
Pierre Gasly GAS
FRA
AlphaTauri Honda
110
10
Fernando Alonso ALO
ESP
Alpine Renault
81
11
Esteban Ocon OCO
FRA
Alpine Renault
74
12
Sebastian Vettel VET
GER
Aston Martin Mercedes
43
13
Lance Stroll STR
CAN
Aston Martin Mercedes
34
14
Yuki Tsunoda TSU
JPN
AlphaTauri Honda
32
15
George Russell RUS
GBR
Williams Mercedes
16
16
Kimi Räikkönen RAI
FIN
Alfa Romeo Racing Ferrari
10
17
Nicholas Latifi LAT
CAN
Williams Mercedes
7
18
Antonio Giovinazzi GIO
ITA
Alfa Romeo Racing Ferrari
3
19
Mick Schumacher MSC
GER
Haas Ferrari
0
20
Robert Kubica KUB
POL
Alfa Romeo Racing Ferrari
0
21
Nikita Mazepin MAZ
RAF
Haas Ferrari
0

Table of accumulated drivers’ points

Create a table of accumulated points for each driver in twenty-two Grands Prix, which will be used as input for BarChartRace.
First, get URLs with detailed information of all drivers in a specified year.
In[]:=
getdriverURL[year_]:=Module[{resp,xml,pos},​​resp=URLRead[driversURL@year];​​xml=resp["Body"]//ImportString[#,"XMLObject"]&;​​pos=Position[xml,XMLElement["tbody",___]][[1]];​​Cases[Extract[xml,pos],XMLElement["a",{"shape""rect","class""dark bold ArchiveLink","href"x_,___},___]URL["https://www.formula1.com"<>x],∞]​​];​​driverURLs=getdriverURL[year];​​driverURLs[[1]]
Out[]=
URL
https://www.formula1.com/en/results.html/2021/drivers/MAXVER01/max-verstappen.html

Get a driver name from the URL obtained above.
In[]:=
getdrivername[driverurl_URL]:=Module[{resp,xml},​​resp=URLRead[driverurl];​​xml=resp["Body"]//ImportString[#,"XMLObject"]&;​​Cases[xml[[2]],XMLElement["title",{},{x_}]StringSplit@x,∞][[1,-2;;]]​​];​​getdrivername[driverURLs[[1]]]
Out[]=
{Max,Verstappen}
The information in driverURLs is a list of points for the Grands Prix in which the driver participated. In other words, there is no points for the Grands Prix in which the driver did not participate. Taking this into account, create a table of accumulated points in all Grands Prix during the year.
In[]:=
getlocationandpoint[xml_]:={​​(*location*)Cases[xml,XMLElement["a",{"shape""rect","class""dark ArchiveLink",___},{x_}]x,∞][[1]],​​(*point*)​​Cases[xml,XMLElement["td",{"colspan""1","rowspan""1","class""dark bold"},{x_}]ToExpression@x,∞][[-1]]​​};​​​​getresult[driverurl_URL]:=Module[{resp,xml,p,list},​​resp=URLRead[driverurl];​​xml=resp["Body"]//ImportString[#,"XMLObject"]&;​​p=Position[xml,XMLElement["tr",{},___]];​​list=getlocationandpoint[Extract[xml,#]]&/@p[[2;;]];​​(*locationandpointfortheGrandsPrixinwhichthedriverparticipated*)​​Association@Thread[list[[All,1]]->list[[All,2]]]​​];​​​​getresult2[driverurl_URL,locations_List]:=Module[{as,v,list},​​as=getresult@driverurl;​​v=Lookup[as,#,0]&/@locations;​​(*driver,locationandpointforallGrandsPrix*)​​list=Association@Join[{"name"->(getdrivername@driverurl)[[2]]},Thread[locations->v]]​​];​​​​getaccumulate[year_]:=Module[{driverURLs,drivernames,result,result2,maxpos,locations,accumulate},​​(*dirversURL*)​​driverURLs=getdriverURL[year];​​(*driversname*)​​drivernames=getdrivername/@driverURLs;​​(*locationandpointfortheGrandsPrixinwhichthedriverparticipated*)​​result=getresult/@driverURLs;​​maxpos=Position[Length/@result,Max[Length/@result]][[1,1]];​​(*allGrandsPrix*)​​locations=Keys[result[[maxpos]]];​​(*pointsforallGrandsPrix*)​​result2=getresult2[#,locations]&/@driverURLs;​​(*joinallGrandsPrix*)​​result2=Join[{Join[{"driver"},locations]},Values@result2];​​(*accumulatepoints*)​​accumulate=Join[{result2[[1]]},Join[{#[[1]]},Accumulate[#[[2;;]]]]&/@result2[[2;;]]];​​accumulate​​];
In[]:=
accumulate=getaccumulate[year];
Show the table of accumulated drivers' points.
In[]:=
Grid[​​accumulate,​​Background{None,{LightGray}},Alignment{Join[{Left},Table[".",(Dimensions@accumulate)[[2]]-1]]},ItemSizeFull]
Out[]=
driver
Bahrain
Emilia Romagna
Portugal
Spain
Monaco
Azerbaijan
France
Styria
Austria
Great Britain
Hungary
Belgium
Netherlands
Italy
Russia
Turkey
United States
Mexico
Brazil
Qatar
Saudi Arabia
Abu Dhabi
Verstappen
18
43
61
80
105
105
131
156
182
185
187
199.5
224.5
226.5
244.5
262.5
287.5
312.5
332.5
351.5
369.5
395.5
Hamilton
25
44
69
94
101
101
119
138
150
177
195
202.5
221.5
221.5
246.5
256.5
275.5
293.5
318.5
343.5
369.5
387.5
Bottas
16
16
32
47
47
47
59
74
92
108
108
108
123
141
151
177
185
185
203
203
218
226
Perez
10
10
22
32
44
69
84
96
104
104
104
104
108
118
120
135
150
165
178
190
190
190
Sainz
4
14
14
20
38
42
42
50
60
68
83
83.5
89.5
97.5
112.5
116.5
122.5
130.5
139.5
145.5
149.5
164.5
Norris
12
27
37
41
56
66
76
86
101
113
113
113
114
132
139
145
149
150
151
153
154
160
Leclerc
8
20
28
40
40
52
52
58
62
80
80
82
92
104
104
116
128
138
148
152
158
159
Ricciardo
6
14
16
24
24
26
34
34
40
50
50
56
56
83
95
95
105
105
105
105
115
115
Gasly
0
6
7
8
16
31
37
37
39
39
50
54
66
66
66
74
74
86
92
92
100
110
Alonso
0
1
5
5
5
13
17
19
20
26
38
38
46
50
58
58
58
60
62
77
77
81
Ocon
0
2
8
10
12
12
12
12
12
14
39
42
44
45
45
46
46
46
50
60
72
74
Vettel
0
0
0
0
10
28
30
30
30
30
30
35
35
35
35
35
36
42
42
43
43
43
Stroll
1
5
5
5
9
9
10
14
14
18
18
18
18
24
24
26
26
26
26
34
34
34
Tsunoda
2
2
2
2
2
8
8
9
9
10
18
18
18
18
18
18
20
20
20
20
20
32
Russell
0
0
0
0
0
0
0
0
0
0
4
13
13
15
16
16
16
16
16
16
16
16
Räikkönen
0
0
0
0
0
1
1
1
1
1
2
2
2
2
6
6
6
10
10
10
10
10
Latifi
0
0
0
0
0
0
0
0
0
0
6
7
7
7
7
7
7
7
7
7
7
7
Giovinazzi
0
0
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
3
3
Schumacher
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Kubica
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
Mazepin
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

BarChartRace

I have published a Wolfram Language version of BarChartRace, which you may have seen on social networking sites, to the WOLFRAM FUNCTION REPOSITORY.
Prepare the required arguments for BarChartRace.
Generate a list of the top 10 BarChart with 22 frames between the two consecutive Grand Prix.
Overlay the location of the Grand Prix in the lower right corner of each BarChart.
Animate a bar chart race with ListAnimate. The output is showed at the top of this post.