{"id":2844,"date":"2023-01-17T05:47:54","date_gmt":"2023-01-17T05:47:54","guid":{"rendered":"http:\/\/optimumsportsperformance.com\/blog\/?p=2844"},"modified":"2023-01-18T16:39:33","modified_gmt":"2023-01-18T16:39:33","slug":"catapult-gps-converting-the-practice-duration-string-to-minutes","status":"publish","type":"post","link":"https:\/\/optimumsportsperformance.com\/blog\/catapult-gps-converting-the-practice-duration-string-to-minutes\/","title":{"rendered":"Catapult GPS &#8211; Converting the practice duration string to minutes"},"content":{"rendered":"<p>One of the most frustrating things to deal with is date and time strings. Using <strong><span style=\"color: #0000ff;\"><a style=\"color: #0000ff;\" href=\"https:\/\/www.catapultsports.com\/\">Catapult GPS<\/a><\/span><\/strong>, a popular GPS provider for professional and collegiate sports teams, practice duration is reported in their export as a string, <em>hours : minutes : seconds.<\/em> Unfortunately, we can&#8217;t do much with this if we want to perform additional computations, for example calculate player load per minute, we need to convert this column into total minutes.<\/p>\n<p>I&#8217;ve had a few people in the sports performance field reach out and ask how to do this in R because they often get frustrated and just resort to changing the data in their CSV download prior to importing it into R, where they then do their plotting and visualizing. Today, I&#8217;ll walk through a few steps using the {<strong>lubridate<\/strong>} package and show you how you can handle this data cleaning all within you R environment.<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Load Packages &amp; Get Data<\/strong><\/span><\/p>\n<p>We start by loading {<strong>tidyverse<\/strong>} and {<strong>lubridate<\/strong>} and some fake Catpault data that I&#8217;ve created.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n### Packages ---------------------------------------\r\nlibrary(tidyverse)\r\nlibrary(lubridate)\r\n\r\n### Load Data -------------------------------------\r\ncatapult &lt;- read.csv(&quot;catapult_example.csv&quot;, header = TRUE) %&gt;%\r\njanitor::clean_names()\r\n\r\ncatapult\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.28.09-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-2845\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.28.09-PM.png\" alt=\"\" width=\"518\" height=\"260\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.28.09-PM.png 784w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.28.09-PM-300x151.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.28.09-PM-768x386.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.28.09-PM-624x314.png 624w\" sizes=\"auto, (max-width: 518px) 100vw, 518px\" \/><\/a><\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Adjusting time<\/strong><\/span><\/p>\n<p>We can see the duration string (hour : minute : second) indicating that the session was 97 minutes and 10 seconds long. Before handling the entire column of data, let&#8217;s just grab a single observation and work through the functions we need so that we know what is going on.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n### Adjust Time ------------------------------------\r\n# hms() function to split out duration to its component parts into a string\r\nsingle_time &lt;- catapult %&gt;% \r\n  slice(1) %&gt;% \r\n  pull(duration)\r\n\r\nsingle_time\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.30.48-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-2846\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.30.48-PM.png\" alt=\"\" width=\"178\" height=\"66\" \/><\/a><\/p>\n<p>The <strong>hms()<\/strong> function can be used to convert each of the time components into a named string.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\nsingle_time2 &lt;- hms(single_time)\r\nsingle_time2\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.33.21-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-2847\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.33.21-PM.png\" alt=\"\" width=\"223\" height=\"76\" \/><\/a>Once we have the individual components in a named string we can extract them out with the <strong>hour(), minute(), <\/strong>and <strong>second()<\/strong> functions and have each returned back as an integer.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\n# Select each component \r\nhour(single_time2)\r\nminute(single_time2)\r\nsecond(single_time2)\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.33.47-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-2848\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.33.47-PM.png\" alt=\"\" width=\"275\" height=\"166\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.33.47-PM.png 354w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.33.47-PM-300x181.png 300w\" sizes=\"auto, (max-width: 275px) 100vw, 275px\" \/><\/a><\/p>\n<p>Once in integer form, converting this data to a total minutes value we first multiplying hour by 60 and divide second by 60 and then sum those up with minutes.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\nhour(single_time2)*60 + minute(single_time2) + second(single_time2)\/60\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-2849\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM-1024x87.png\" alt=\"\" width=\"625\" height=\"53\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM-1024x87.png 1024w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM-300x26.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM-768x65.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM-624x53.png 624w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.36.24-PM.png 1082w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><br \/>\nThe finished product suggests the session was 97.2 minutes long.<\/p>\n<p><span style=\"text-decoration: underline;\"><strong>Applying the approach to all of our data<\/strong><\/span><\/p>\n<p>Now that we understand what is going on under the hood, we can apply this at scale, to our of our data.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\ncatapult &lt;- catapult %&gt;%\r\n  mutate(hour_min_sec = hms(duration),\r\n    pract_time = hour(hour_min_sec) * 60 + minute(hour_min_sec) + second(hour_min_sec) \/ 60)\r\n\r\ncatapult\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-2850\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM-1024x360.png\" alt=\"\" width=\"625\" height=\"220\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM-1024x360.png 1024w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM-300x105.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM-768x270.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM-624x219.png 624w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.38.26-PM.png 1196w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<p>After getting practice time into minutes we will adjust the date column from a character string to an actual date, using the <strong>as.Date()<\/strong> function.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\ncatapult$date &lt;- as.Date(catapult$date, &quot;%m\/%d\/%y&quot;)\r\ncatapult\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-2851\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM-1024x328.png\" alt=\"\" width=\"625\" height=\"200\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM-1024x328.png 1024w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM-300x96.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM-768x246.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM-624x200.png 624w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.39.13-PM.png 1194w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<p>To finish, we will do a bit of clean up and remove the duration and hour_min_sec columns, round the player_load and pract_time columns to one significant digit and create a player_load_per_min column.<\/p>\n<pre class=\"brush: r; title: ; notranslate\" title=\"\">\r\ncatapult %&gt;%\r\n  select(-duration, -hour_min_sec) %&gt;%\r\n  mutate(across(.cols = player_load:pract_time,\r\n                ~round(.x, 1)),\r\n         player_load_per_min = round(player_load \/ pract_time, 2))\r\n<\/pre>\n<p><a href=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-large wp-image-2852\" src=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM-1024x342.png\" alt=\"\" width=\"625\" height=\"209\" srcset=\"https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM-1024x342.png 1024w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM-300x100.png 300w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM-768x256.png 768w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM-624x208.png 624w, https:\/\/optimumsportsperformance.com\/blog\/wp-content\/uploads\/2023\/01\/Screen-Shot-2023-01-16-at-9.41.10-PM.png 1162w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<p>Now we have a cleaned data set that we can worth with!<\/p>\n<p>Access to the full code is available on my <strong><span style=\"color: #0000ff;\"><a style=\"color: #0000ff;\" href=\"https:\/\/github.com\/pw2\/R-Tips-Tricks\/tree\/master\/Catapult%20-%20Handling%20Time\">GITHUB page<\/a><\/span><\/strong>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the most frustrating things to deal with is date and time strings. Using Catapult GPS, a popular GPS provider for professional and collegiate sports teams, practice duration is reported in their export as a string, hours : minutes : seconds. Unfortunately, we can&#8217;t do much with this if we want to perform additional [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42,27],"tags":[],"class_list":["post-2844","post","type-post","status-publish","format-standard","hentry","category-sports-science","category-strength-and-conditioning"],"_links":{"self":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts\/2844","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/comments?post=2844"}],"version-history":[{"count":1,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts\/2844\/revisions"}],"predecessor-version":[{"id":2853,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/posts\/2844\/revisions\/2853"}],"wp:attachment":[{"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/media?parent=2844"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/categories?post=2844"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/optimumsportsperformance.com\/blog\/wp-json\/wp\/v2\/tags?post=2844"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}