{"id":46639,"date":"2021-04-02T00:00:00","date_gmt":"2021-04-02T07:00:00","guid":{"rendered":"https:\/\/griddb-linux-hte8hndjf8cka8ht.westus-01.azurewebsites.net\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/"},"modified":"2025-11-13T12:55:17","modified_gmt":"2025-11-13T20:55:17","slug":"creating-a-performance-tracker-for-car-races-collecting-race-data-part-2","status":"publish","type":"post","link":"https:\/\/www.griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/","title":{"rendered":"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2)"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of information. In this article, we will learn how to transform structured data into meaningful data using data visualization methods.<\/p>\n<p>In the <a href=\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data\/\">previous article<\/a>, we learned how to store data inside a database in a structured manner and also how to retrieve data from the database. This article will focus on what we can achieve through data visualization and how to obtain data from the database to match our analytics needs.<\/p>\n<h2>Prerequisites<\/h2>\n<p>We will use Python as the programming language and utilize pandas, matplotlib, and folium libraries for data analysis and visualization for the purpose of this tutorial. The GridDB Python connector will be used to interact with the database.<\/p>\n<p>Additionally, we need to have a GridDB instance configured, and all the required collections created from the <a href=\"https:\/\/www.kaggle.com\/rohanrao\/formula-1-world-championship-1950-2020?select=lap_times.csv\">Formula 1 World Championship (1950 &#8211; 2020)<\/a> data set obtained from <a href=\"https:\/\/www.kaggle.com\/\">Kaggle<\/a>.<\/p>\n<h2>Data Structure<\/h2>\n<p>Following are the collections within the GridDB instance, which we will be using for data visualization.<\/p>\n<p><style type=\"text\/css\">\n  .tg  {border-collapse:collapse;border-spacing:0;}\n.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;\n  overflow:hidden;padding:10px 5px;word-break:normal;}\n.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;\n  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}\n.tg .tg-0lax{text-align:left;vertical-align:top}\n<\/style>\n<\/p>\n<table class=\"tg\">\n<thead>\n<tr>\n<th class=\"tg-0pky\">\n        Field Name\n      <\/th>\n<th class=\"tg-0pky\">\n        Data Type (GridDB)\n      <\/th>\n<th class=\"tg-0pky\">\n        Notes\n      <\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td class=\"tg-0pky\">\n        CircuitID\n      <\/td>\n<td class=\"tg-0pky\">\n        INTEGER\n      <\/td>\n<td class=\"tg-0pky\">\n        Curcuit Identifier\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        CircuitRef\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        name\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        location\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n        City where the circuit is located\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        country\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        lat\n      <\/td>\n<td class=\"tg-0pky\">\n        FLOAT\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        lng\n      <\/td>\n<td class=\"tg-0pky\">\n        FLOAT\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0lax\">\n        url\n      <\/td>\n<td class=\"tg-0lax\">\n        String\n      <\/td>\n<td class=\"tg-0lax\">\n        URL for Wiki Article\n      <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Races collection<\/p>\n<p><style type=\"text\/css\">\n  .tg  {border-collapse:collapse;border-spacing:0;}\n.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;\n  overflow:hidden;padding:10px 5px;word-break:normal;}\n.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;\n  font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;}\n.tg .tg-0pky{border-color:inherit;text-align:left;vertical-align:top}\n<\/style>\n<\/p>\n<table class=\"tg\">\n<thead>\n<tr>\n<th class=\"tg-0pky\">\n        Field Name\n      <\/th>\n<th class=\"tg-0pky\">\n        Data Type (GridDB)\n      <\/th>\n<th class=\"tg-0pky\">\n        Notes\n      <\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td class=\"tg-0pky\">\n        raceid\n      <\/td>\n<td class=\"tg-0pky\">\n        INTEGER\n      <\/td>\n<td class=\"tg-0pky\">\n        Race Identifier\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        year\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        round\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        circuitid\n      <\/td>\n<td class=\"tg-0pky\">\n        INTEGER\n      <\/td>\n<td class=\"tg-0pky\">\n        City where the circuit is located\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        name\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        raceTime\n      <\/td>\n<td class=\"tg-0pky\">\n        TIMESTAMP\n      <\/td>\n<td class=\"tg-0pky\">\n      <\/td>\n<\/tr>\n<tr>\n<td class=\"tg-0pky\">\n        url\n      <\/td>\n<td class=\"tg-0pky\">\n        STRING\n      <\/td>\n<td class=\"tg-0pky\">\n        URL for Wiki Article\n      <\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Basic Data Presentation<\/h2>\n<p>Before trying to analyze or visualize data, first, we need to retrieve them from the database. So let&#8217;s have a small refresher on how to retrieve data. GridDB provides the TQL query language to perform database queries.<\/p>\n<p>For data retrieval, we need to create the connection, get the collection, and perform the queries on the collection objects. The following code block demonstrates how to obtain the containers within the database.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">$ sudo yum -y install griddb_nosql griddb-c-client<\/code><\/pre>\n<\/div>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">factory = griddb.StoreFactory.get_instance()\n\ntry:\n    # Create gridstore object\n    gridstore = factory.get_store(\n        host='239.0.0.1', \n        port=31999, \n        cluster_name='defaultCluster', \n        username='admin', \n        password='admin'\n    )\n\n    # Define the container names\n    circuits_container = \"circuits\"\n    races_container = \"races\"\n\n    # Get the containers\n    circuits_data = gridstore.get_container(circuits_container)\n    races_data = gridstore.get_container(races_container)\n\nexcept griddb.GSException as e:\n    for i in range(e.get_error_stack_size()):\n        print(\"[\", i, \"]\")\n        print(e.get_error_code(i))\n        print(e.get_location(i))\n        print(e.get_message(i))<\/code><\/pre>\n<\/div>\n<p>Now we have data in two different objects. We need to convert these data into a proper format so that they can be easily analyzed. This is where the &#8220;Pandas&#8221; library comes in, and we will convert the data into Pandas DataFrames.<\/p>\n<p>For that, we need to write a query to select all the data within the two containers, create a list from those data and then convert that list into a DataFrame. Following is a simple TQL query to achieve that.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># Select all rows from circuits_container\n    query = circuits_data.query(\"select *\")\n    rs = query.fetch(False)\n    \n    # Create a list\n    retrieved_data= []\n    while rs.has_next():\n        data = rs.next()\n        retrieved_data.append(data)\n\n    # Convert the list to a pandas data frame\n    circuits_dataframe = pd.DataFrame(retrieved_data, columns=['circuitId', 'circuitRef', 'name', 'location', 'country', 'lat', 'lng', 'url'])\n\n    # Select all rows from races_container\n    query = races_data.query(\"select *\")\n    rs = query.fetch()\n\n    # Create a list\n    retrieved_data= []\n    while rs.has_next():\n        data = rs.next()\n        retrieved_data.append(data)\n\n    # Convert the list to a pandas data frame\n    races_dataframe = pd.DataFrame(retrieved_data, columns=['raceID', 'year', 'round', 'circuitId', 'name', 'url', 'raceTime'])\n<\/code><\/pre>\n<\/div>\n<h2>Creating an HTML Table<\/h2>\n<p>One of the simplest ways to represent data is through a table. The panda\u00e2\u20ac\u2122s library provides the \u00e2\u20ac\u0153to_html\u00e2\u20ac\u009d function to convert a data frame into an HTML table.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">races_dataframe.to_html('races_data.html')<\/code><\/pre>\n<\/div>\n<p>The above function will create a simple HTML table. However, we need to present the data inside the table in a pleasing manner. To accomplish this, let\u00e2\u20ac\u2122s add some formatting to the data frame and embed the created HTML table within a proper HTML page with an attached style sheet.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># Create the HTML Page Structure\n# Include the Style Sheet\nhtml_string = '''\n&lt;html>\n    \n    &lt;link rel=\"stylesheet\" type=\"text\/css\" href=\"style.css\"\/>\n    &lt;body>\n    &lt;h1>Races Collection&lt;\/h1>\n    {table}\n    &lt;\/body>\n&lt;\/html>\n'''\n\n# Rename the Columns Headers\nraces_dataframe.rename(columns={'raceId': 'Race ID', 'circuitId': 'Circuit ID', 'raceTime': 'Race Time'}, inplace=True)\n\n# Convert the Headers to Uppercase\nraces_dataframe.rename(str.upper, axis='columns', inplace=True)\n\n# Write to HTML File\nwith open('races_table.html', 'w') as f:\n    # Pass the DataFrame to the HTML String\n    f.write(html_string.format(table=races_dataframe.to_html(index=False, render_links=True, escape=False, justify='left', classes='htmlfilestyle')))<\/code><\/pre>\n<\/div>\n<p>CSS File:<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">.htmlfilestyle {\n    font-size: 11pt;\n    font-family: Arial;\n    border-collapse: collapse;\n    border: 1px solid silver;\n}\n\n.htmlfilestyle td, th {\n    padding: 5px;\n    font-size: 12pt;\n}\n\n.htmlfilestyle tr:nth-child(even) {\n    background: #E0E0E0;\n}\n\n.htmlfilestyle tr:hover {\n    background: silver;\n    cursor: pointer;\n}<\/code><\/pre>\n<\/div>\n<p>This will provide us with a formatted HTML table that offers a better representation of data using the given data frame.<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture0.png\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture0.png\" alt=\"\" width=\"602\" height=\"125\" class=\"aligncenter size-full wp-image-27391\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture0.png 602w, \/wp-content\/uploads\/2021\/03\/Picture0-300x62.png 300w, \/wp-content\/uploads\/2021\/03\/Picture0-600x125.png 600w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/p>\n<h2>Using TQL<\/h2>\n<p>We can further refine the data set retrieved from the database by utilizing the TQL query language offered by GridDB. What we can analyze or visualize depends on the structure and the values of the data set. The logical, comparison, string, numerical, array, spatial, and time operators in GridDB allow us to query the database effectively to obtain the required data. Let&#8217;s take a look at a couple of TQL statements that can be used to filter the data set.<\/p>\n<h3>races collection<\/h3>\n<p>Get only the races in Monaco Grand Prix<\/p>\n<p><code>races_data.query(\"select * where name = 'Monaco Grand Prix'\")<\/code><\/p>\n<p>Get the races between the years 2010 and 2015<\/p>\n<p><code># Using year field<\/code> <code>query = races_data.query(\"select * where year &gt;= 2009 AND year &lt;= 2015 ORDER BY raceTime DESC\")<\/code><\/p>\n<p><code># Using raceTime field<\/code> <code>races_data.query(\"select * where raceTime &gt;= TIMESTAMP('2010-01-01T00:00:00.000Z') AND year &lt;= TIMESTAMP('2015-12-31T23:59:59.000Z')\")<\/code><\/p>\n<p>Get the races excluding the past 5 years.<\/p>\n<p><code># TIMESTAPADD function is used to exclude 5 years from the current time<\/code> <code>races_data.query(\"select * where raceTime &lt; TIMESTAMPADD(YEAR, NOW(), -5)\")<\/code><\/p>\n<p>Count the number of races that happened during 1990<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">query = races_data.query(\"select COUNT(*) where year = 2009\")\n#query = circuits_data.query(\"select COUNT(*)\")\nrs = query.fetch(False)\n\n# Obtain the calculated value\nwhile rs.has_next():\n    data = rs.next()\n    count = data.get(griddb.Type.LONG)\n    print(count)<\/code><\/pre>\n<\/div>\n<p>Limit the number of records to 100 <code>races_data.query(\"select * LIMIT 100\")<\/code><\/p>\n<h3>circuits collection<\/h3>\n<p>Get the race circuits located in Germany <code>circuits_data.query(\"select * where country = 'Germany'\")<\/code><\/p>\n<p>Calculate the total number of circuits<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\">circuits_data.query(\"select COUNT(*)\")\nrs = query.fetch(False)\n\n# Obtain the calculated value\nwhile rs.has_next():\n    data = rs.next()\n    count = data.get(griddb.Type.LONG)\n    print(count)\n<\/code><\/pre>\n<\/div>\n<p>Get the race circuits located in UK, France, and Spain <code>circuits_data.query(\"select * where country = 'UK' OR country = 'France' OR country = 'Spain' ORDER BY name DESC\")<\/code><\/p>\n<p>Get circuits that have \u00e2\u20ac\u0153Park\u00e2\u20ac\u009d or \u00e2\u20ac\u0153Speedway\u00e2\u20ac\u009d in their names <code>circuits_data.query(\"select * where name LIKE '%Park%' OR name LIKE '%Speedway%' ORDER BY name DESC\")<\/code><\/p>\n<p>When it comes to extracting data via TQL, there are two limitations. One is the inability to select specific columns like in SQL, except for aggregation operations. The other is TQL lacking support for statements like GROUP BY, HAVING, DISTINCT, and JOIN.<\/p>\n<p>However, GridDB supports all the above statements through their SQL interface, overcoming the limitations imposed by TQL. Another method that can be used is utilizing Pandas DataFrames. Pandas offers the functionality to select specific columns, join data frames, and group columns, essentially eliminating the drawbacks mentioned above. Combining GridDB with Pandas library vastly expands what we can achieve through the data, leading to greater analytics capabilities. For more information about TQL, please refer to its <a href=\"https:\/\/griddb.org\/docs-en\/manuals\/GridDB_TQL_Reference.html\">official documentation<\/a>.<\/p>\n<h2>Creating Charts using Pandas<\/h2>\n<p>Pandas offers inbuilt functionality to make plots using Data Frames. Let&#8217;s look at how to create a bar chart to show the number of races held in each venue.<\/p>\n<p>The value_counts function enables us to count the unique values of a particular column, which is the &#8220;name&#8221; column of the dataset in this instance. Then, we can create a separate variable to store the counted data, and using that, we can plot a bar chart with the figsize, title, and x,y labels options. The kind parameter is used to select the chart type. The charts will be generated using matplotlib library as the default backend.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># Print the count\nprint(races_dataframe['name'].value_counts())\n\n# Obtain the count of each venue\nplotdata = races_dataframe['name'].value_counts()\n\n# Plot the data as a bar chart\nplotdata.plot(kind=\"bar\", figsize=(20,10), title=\"Race Locations\", xlabel=\"Races\", ylabel=\"No of Races\")<\/code><\/pre>\n<\/div>\n<p>Output &#8211; Print Statement<\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture1.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture1.png\" alt=\"\" width=\"358\" height=\"327\" class=\"aligncenter size-full wp-image-27392\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture1.png 358w, \/wp-content\/uploads\/2021\/03\/Picture1-300x274.png 300w\" sizes=\"(max-width: 358px) 100vw, 358px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture2.png\"><img decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture2.png\" alt=\"\" width=\"602\" height=\"383\" class=\"aligncenter size-full wp-image-27398\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture2.png 602w, \/wp-content\/uploads\/2021\/03\/Picture2-300x191.png 300w, \/wp-content\/uploads\/2021\/03\/Picture2-600x382.png 600w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/p>\n<p>Next, we will create a pie chart using the circuit data set. Using the country column, we can analyze the number of race circuits distributed across each participating country. To create a pie chart, we have to configure the chart kind as \u00e2\u20ac\u0153pie.\u00e2\u20ac\u009d<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># Print the count\nprint(circuits_dataframe['country'].value_counts())\n\n# Obtain the count of each venue\nplotdata = circuits_dataframe['country'].value_counts()\n\n# Plot the data as a pie chart\n# Disable the legend and ylabel\nplotdata.plot(kind=\"pie\", figsize=(30,15), title=\"Circuit Locations\", legend=False, ylabel=\"\")<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture3-REAL.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture3-REAL.png\" alt=\"\" width=\"289\" height=\"255\" class=\"aligncenter size-full wp-image-27401\" \/><\/a><\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture3.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture3.png\" alt=\"\" width=\"602\" height=\"581\" class=\"aligncenter size-full wp-image-27400\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture3.png 602w, \/wp-content\/uploads\/2021\/03\/Picture3-300x290.png 300w, \/wp-content\/uploads\/2021\/03\/Picture3-600x579.png 600w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/p>\n<p>As you can see from the above examples, the data can be visualized by plotting the data frame. This is only a subset of what we can achieve through plotting, and there&#8217;s the ability to refine this further using additional filters and formatting. Have a look at the <a href=\"https:\/\/pandas.pydata.org\/pandas-docs\/stable\/reference\/api\/pandas.DataFrame.plot.html#pandas.DataFrame.plot\">official documentation<\/a> for more information about the plotting function.<\/p>\n<h2>Create a Table using Matplotlib<\/h2>\n<p>In the previous example, we learned how to create an HTML table using pandas data frames. However, if you need more granular control over the table, it&#8217;s better to generate the table via the matplotlib library.<\/p>\n<p>For this example, we will query 10 records from the GridDB database in the \u00e2\u20ac\u0153circuits\u00e2\u20ac\u009d collection and create a data frame using those data.<\/p>\n<p><code>circuits_data.query(\"select * LIMIT 10\")<\/code><\/p>\n<p>Using the data frame as the base data set, we can create the table as shown in the following code block. There, we create a plot object with subplots, assign the data frame values to the required columns (cellText and colLabels) and formatting. Then add the title, footer, and finally save the table as a png image file.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># Create the plot object\nfig, ax =plt.subplots(\n    figsize=(20, 6),\n    linewidth=2,\n    tight_layout={'pad':1})\n\n# Turn off the axis\nax.axis('off')\n# Set background color\nax.set_facecolor(\"#ffffff\")\n\ntable = ax.table(\n    # Define cell values\n    cellText=circuits_dataframe.values,\n    # Define column headings\n    colLabels=circuits_dataframe.columns,\n    # Column Options - color and width\n    colColours=['skyblue']*8,\n    colWidths=[0.03,0.06,0.1,0.05,0.04,0.06,0.06,0.135],\n    loc=\"center\")\n\n# Set the font size\ntable.auto_set_font_size(False)\ntable.set_fontsize(10)\n\n# Scale the table\ntable.scale(1.8, 1.8)\n\n# Add title\nplt.suptitle(\"Circuits Collection\", size=25, weight='light')\n\n# Add footer\nplt.figtext(0.95, 0.05, \"GridDB Data Collection\", horizontalalignment='right', size=6, weight='light')\n\n# Draw and save the table as a png\nplt.draw()\nplt.savefig('table.png',dpi=150)<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture4.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture4.png\" alt=\"\" width=\"602\" height=\"199\" class=\"aligncenter size-full wp-image-27402\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture4.png 602w, \/wp-content\/uploads\/2021\/03\/Picture4-300x99.png 300w, \/wp-content\/uploads\/2021\/03\/Picture4-600x198.png 600w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/p>\n<p>Matplotlib is the most widely used Python library for data visualization. It can be used to create simple tables and charts to complex 3D graphs while providing complete control over each aspect of the visualization. You can refer to more information about Matplotlib from the <a href=\"https:\/\/matplotlib.org\/stable\/index.html\">matplotlib documentation<\/a>.<\/p>\n<h2>Creating Map using Folium Library<\/h2>\n<p>Folium is a Python visualization library that can be used to create maps. It combines Python with leaflet.js to create maps. This combination enables users to bind data that has been transformed via Python to an interactive leaflet map. In this section, let&#8217;s map the locations of the race circuits in a world map using latitude and longitude data obtained from the &#8220;circuits&#8221; collection in GridDB.<\/p>\n<p>In the following code block, we have created a world map object and a cluster to include all the circuit locations using the MakeCluster function. Then we iterate the data frame and extract the latitude(lat) and longitude(lng) to create individual markers for each location and add them to the cluster. Additionally, we extract the name and country data in each iteration to include in a clickable popup.<\/p>\n<div class=\"clipboard\">\n<pre><code class=\"language-py\"># Create map object\nworld_map= folium.Map()\n\n# Create marker cluster\nmarker_cluster = MarkerCluster().add_to(world_map)\n\n# Create marker for each coordinates\nfor i in range(len(circuits_dataframe)):\n        # Get latitude and longitude from data frame\n        latitude = circuits_dataframe.iloc[i]['lat']\n        longitude = circuits_dataframe.iloc[i]['lng']\n\n        # Set circle radius\n        radius=5\n\n        # Create the popup\n        popup_text = \"\"\"Country : {}&lt;br \/> Circuit Name : {}&lt;br \/>\"\"\"\n        popup_text = popup_text.format(\n                                        circuits_dataframe.iloc[i]['country'],\n                                        circuits_dataframe.iloc[i]['name'])\n        test = folium.Html(popup_text, script=True)\n        popup = folium.Popup(test, max_width=250,min_width=250)\n\n        # Add marker to marker_cluster\n        folium.CircleMarker(location=[latitude, longitude], radius=radius, popup=popup, fill =True).add_to(marker_cluster)\n\n# View the Map\nworld_map<\/code><\/pre>\n<\/div>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture5.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture5.png\" alt=\"\" width=\"602\" height=\"361\" class=\"aligncenter size-full wp-image-27403\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture5.png 602w, \/wp-content\/uploads\/2021\/03\/Picture5-300x180.png 300w, \/wp-content\/uploads\/2021\/03\/Picture5-600x360.png 600w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/p>\n<p><a href=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture6.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/griddb.net\/wp-content\/uploads\/2021\/03\/Picture6.png\" alt=\"\" width=\"602\" height=\"361\" class=\"aligncenter size-full wp-image-27396\" srcset=\"\/wp-content\/uploads\/2021\/03\/Picture6.png 602w, \/wp-content\/uploads\/2021\/03\/Picture6-300x180.png 300w, \/wp-content\/uploads\/2021\/03\/Picture6-600x360.png 600w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><\/p>\n<p>Folium is a powerful yet simple library that can be easily adapted to visualize data on a map. For more information, check out the <a href=\"https:\/\/python-visualization.github.io\/folium\/\">folium documentation<\/a> to begin your journey of data visualization through maps.<\/p>\n<h2>Conclusion<\/h2>\n<p>In this article, we have covered the basics of data visualization. By combining the data retrieved from GridDB collections, we analyzed the data and then created tables, charts, and maps to visualize them to understand those data better. Pandas, matplotlib, and folium are only a few of the powerful libraries available in Python to analyze and visualize data. Data analytics is a fascinating subject where one could spend his whole life learning it. I hope that this article tempted you to dive deep into the world of data analytics and data visualization.<\/p>\n<h2>Source Code<\/h2>\n<p>Here is the source code <a href=\"https:\/\/github.com\/griddbnet\/Blogs\/tree\/main\/Creating%20a%20Performance%20Tracker%20for%20Car%20Races%20%E2%80%93%20Collecting%20Race%20Data%20(Part%202)\">SOURCE CODE<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of information. In this article, we will learn how to transform structured data into meaningful data using data visualization methods. In the previous article, we learned how to store data inside [&hellip;]<\/p>\n","protected":false},"author":41,"featured_media":27400,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[121],"tags":[],"class_list":["post-46639","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2) | GridDB: Open Source Time Series Database for IoT<\/title>\n<meta name=\"description\" content=\"Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2) | GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"og:description\" content=\"Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of\" \/>\n<meta property=\"og:url\" content=\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"GridDB: Open Source Time Series Database for IoT\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/griddbcommunity\/\" \/>\n<meta property=\"article:published_time\" content=\"2021-04-02T07:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-13T20:55:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.griddb.net\/wp-content\/uploads\/2021\/03\/Picture3.png\" \/>\n\t<meta property=\"og:image:width\" content=\"602\" \/>\n\t<meta property=\"og:image:height\" content=\"581\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"griddb-admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:site\" content=\"@GridDBCommunity\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"griddb-admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\"},\"author\":{\"name\":\"griddb-admin\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\"},\"headline\":\"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2)\",\"datePublished\":\"2021-04-02T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:55:17+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\"},\"wordCount\":1462,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2021\/03\/Picture3.png\",\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\",\"url\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\",\"name\":\"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2) | GridDB: Open Source Time Series Database for IoT\",\"isPartOf\":{\"@id\":\"https:\/\/griddb.net\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage\"},\"thumbnailUrl\":\"\/wp-content\/uploads\/2021\/03\/Picture3.png\",\"datePublished\":\"2021-04-02T07:00:00+00:00\",\"dateModified\":\"2025-11-13T20:55:17+00:00\",\"description\":\"Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage\",\"url\":\"\/wp-content\/uploads\/2021\/03\/Picture3.png\",\"contentUrl\":\"\/wp-content\/uploads\/2021\/03\/Picture3.png\",\"width\":602,\"height\":581},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/griddb.net\/en\/#website\",\"url\":\"https:\/\/griddb.net\/en\/\",\"name\":\"GridDB: Open Source Time Series Database for IoT\",\"description\":\"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL\",\"publisher\":{\"@id\":\"https:\/\/griddb.net\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/griddb.net\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/griddb.net\/en\/#organization\",\"name\":\"Fixstars\",\"url\":\"https:\/\/griddb.net\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"contentUrl\":\"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png\",\"width\":200,\"height\":83,\"caption\":\"Fixstars\"},\"image\":{\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/griddbcommunity\/\",\"https:\/\/x.com\/GridDBCommunity\",\"https:\/\/www.linkedin.com\/company\/griddb-by-toshiba\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233\",\"name\":\"griddb-admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g\",\"caption\":\"griddb-admin\"},\"url\":\"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2) | GridDB: Open Source Time Series Database for IoT","description":"Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/","og_locale":"en_US","og_type":"article","og_title":"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2) | GridDB: Open Source Time Series Database for IoT","og_description":"Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of","og_url":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/","og_site_name":"GridDB: Open Source Time Series Database for IoT","article_publisher":"https:\/\/www.facebook.com\/griddbcommunity\/","article_published_time":"2021-04-02T07:00:00+00:00","article_modified_time":"2025-11-13T20:55:17+00:00","og_image":[{"width":602,"height":581,"url":"https:\/\/www.griddb.net\/wp-content\/uploads\/2021\/03\/Picture3.png","type":"image\/png"}],"author":"griddb-admin","twitter_card":"summary_large_image","twitter_creator":"@GridDBCommunity","twitter_site":"@GridDBCommunity","twitter_misc":{"Written by":"griddb-admin","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#article","isPartOf":{"@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/"},"author":{"name":"griddb-admin","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233"},"headline":"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2)","datePublished":"2021-04-02T07:00:00+00:00","dateModified":"2025-11-13T20:55:17+00:00","mainEntityOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/"},"wordCount":1462,"commentCount":0,"publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2021\/03\/Picture3.png","articleSection":["Blog"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/","url":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/","name":"Creating a Performance Tracker for Car Races \u00e2\u20ac\u201c Collecting Race Data (Part 2) | GridDB: Open Source Time Series Database for IoT","isPartOf":{"@id":"https:\/\/griddb.net\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage"},"image":{"@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage"},"thumbnailUrl":"\/wp-content\/uploads\/2021\/03\/Picture3.png","datePublished":"2021-04-02T07:00:00+00:00","dateModified":"2025-11-13T20:55:17+00:00","description":"Introduction Data Analysis is the process of gaining meaningful data from raw data. Without proper analytics, any data set will be simply a bunch of","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/blog\/creating-a-performance-tracker-for-car-races-collecting-race-data-part-2\/#primaryimage","url":"\/wp-content\/uploads\/2021\/03\/Picture3.png","contentUrl":"\/wp-content\/uploads\/2021\/03\/Picture3.png","width":602,"height":581},{"@type":"WebSite","@id":"https:\/\/griddb.net\/en\/#website","url":"https:\/\/griddb.net\/en\/","name":"GridDB: Open Source Time Series Database for IoT","description":"GridDB is an open source time-series database with the performance of NoSQL and convenience of SQL","publisher":{"@id":"https:\/\/griddb.net\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/griddb.net\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/griddb.net\/en\/#organization","name":"Fixstars","url":"https:\/\/griddb.net\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/","url":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","contentUrl":"https:\/\/griddb.net\/wp-content\/uploads\/2019\/04\/fixstars_logo_web_tagline.png","width":200,"height":83,"caption":"Fixstars"},"image":{"@id":"https:\/\/griddb.net\/en\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/griddbcommunity\/","https:\/\/x.com\/GridDBCommunity","https:\/\/www.linkedin.com\/company\/griddb-by-toshiba"]},{"@type":"Person","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/4fe914ca9576878e82f5e8dd3ba52233","name":"griddb-admin","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/griddb.net\/en\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5bceca1cafc06886a7ba873e2f0a28011a1176c4dea59709f735b63ae30d0342?s=96&d=mm&r=g","caption":"griddb-admin"},"url":"https:\/\/www.griddb.net\/en\/author\/griddb-admin\/"}]}},"_links":{"self":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46639","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/comments?post=46639"}],"version-history":[{"count":1,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46639\/revisions"}],"predecessor-version":[{"id":51314,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/posts\/46639\/revisions\/51314"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media\/27400"}],"wp:attachment":[{"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/media?parent=46639"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/categories?post=46639"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.griddb.net\/en\/wp-json\/wp\/v2\/tags?post=46639"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}