{"id":1549,"date":"2013-05-19T15:32:13","date_gmt":"2013-05-19T19:32:13","guid":{"rendered":"http:\/\/lukemiller.org\/?p=1549"},"modified":"2016-09-06T17:31:45","modified_gmt":"2016-09-07T00:31:45","slug":"more-tide-prediction-with-r","status":"publish","type":"post","link":"https:\/\/lukemiller.org\/index.php\/2013\/05\/more-tide-prediction-with-r\/","title":{"rendered":"More tide prediction with R"},"content":{"rendered":"<p><strong>Edit: <\/strong>There is now a full-fledged R package, <a href=\"https:\/\/CRAN.R-project.org\/package=rtide\" target=\"_blank\">rtide<\/a>, to accomplish the same basic task of generating time series of tide predictions that is outlined here. See this <a href=\"https:\/\/lukemiller.org\/?p=2300\">more recent post<\/a> for information.<\/p>\n<p>In the <a href=\"https:\/\/lukemiller.org\/index.php\/2013\/05\/interfacing-xtide-and-r\/\">previous post<\/a> I outlined how to query the <a href=\"http:\/\/www.flaterco.com\/xtide\/\" target=\"_blank\">XTide<\/a> software with R and parse the results into a handy-dandy data frame. The biggest hurdle with that method is getting XTide up and running on your computer. The code outlined here works entirely within R, so you don&#8217;t need XTide installed on your computer. The trade-off is that it provides substantially less information. This script only produces tide height predictions at a user-specified interval (1 to 60 minutes), and doesn&#8217;t pick out high tide, low tide, sunrise, sunset, or any of the other fun stuff that XTide can produce. Additionally, this version only works for a subset of 637 of the NOAA tide stations rather than the 1000s of stations that XTide can output. The available stations are found <a href=\"http:\/\/www.flaterco.com\/xtide\/locations.html\" target=\"_blank\">on this page<\/a> listed with the type &#8216;Ref&#8217;, rather than the ones labeled &#8216;Sub&#8217;. If all you want is a series of continuous tide height predictions for a NOAA reference tide station, this script and the associated Rdata file will do it for you. Fair warning: the actual prediction routine is not vectorized, so if you ask for many weeks of high-frequency data, the script will take a few minutes to run.<\/p>\n<p>&nbsp;<\/p>\n<figure id=\"attachment_1551\" aria-describedby=\"caption-attachment-1551\" style=\"width: 480px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/lukemiller.org\/wp-content\/uploads\/2013\/05\/Output_tides.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-1551\" src=\"https:\/\/lukemiller.org\/wp-content\/uploads\/2013\/05\/Output_tides.png\" alt=\"An illustration of tide height predictions from the script. \" width=\"480\" height=\"300\" srcset=\"https:\/\/lukemiller.org\/wp-content\/uploads\/2013\/05\/Output_tides.png 480w, https:\/\/lukemiller.org\/wp-content\/uploads\/2013\/05\/Output_tides-300x187.png 300w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/a><figcaption id=\"caption-attachment-1551\" class=\"wp-caption-text\">An illustration of tide height predictions from the script.<\/figcaption><\/figure>\n<p>The script <code><a href=\"https:\/\/github.com\/millerlp\/Misc_R_scripts\/blob\/master\/tide_prediction.R\" target=\"_blank\">tide_prediction.R<\/a><\/code> and the harmonics file <code><a href=\"https:\/\/github.com\/millerlp\/Misc_R_scripts\/blob\/master\/Harmonics_20120302.Rdata\" target=\"_blank\">Harmonics-20120302.Rdata<\/a><\/code> can be found in my <a href=\"https:\/\/github.com\/millerlp\/Misc_R_scripts\" target=\"_blank\">GitHub repository<\/a>. The tide_prediction.R script is shown below.<\/p>\n<div style=\"overflow: auto;\">\n<div class=\"geshifilter\">\n<pre class=\"r geshifilter-R\" style=\"font-family: monospace;\"><span style=\"color: #666666; font-style: italic;\"># Filename: tide_prediction.R<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># NOT FOR NAVIGATIONAL USE. DON'T WRECK YOUR BOAT BASED ON MY BAD CODING.<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Generate tide height predictions for US NOAA *reference* tide stations<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># entirely within R.<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># This requires a previously-produced file of harmonics for the sites, stored as<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># a Rdata file. The current file is Harmonics-20120302.Rdata. The harmonics file<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># was originally derived from XTide, found at http:\/\/www.flaterco.com\/xtide\/<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># The available reference tide stations are listed here:<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># http:\/\/www.flaterco.com\/xtide\/locations.html<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Note that only stations listed as type 'Ref' on that page can be used<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># with this script.<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># The script assumes that all input times (and corresponding tide<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># time outputs) are in UTC\/GMT time zone, not your local time zone. Check the<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># output against NOAA's tide predictions at<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># http:\/\/tidesandcurrents.noaa.gov\/tide_predictions.shtml<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># This can produce predictions for years between 1700 and 2100, but with<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># decreasing accuracy as you move further from 2012 (say beyond 1990 or 2030)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># since the harmonics file is derived from the current tidal epoch, and things<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># like sea level have a tendency to change over time.<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># This script may take a few minutes to run if you ask for weeks of<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># high-frequency tide predictions.<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># The output is stored in a data frame called 'results'.<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Author: Luke Miller May 19, 2013<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">###############################################################################<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Sys.setenv(TZ='UTC') # Change R session time zone to UTC (optional)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># User-friendly version for loading harmonics Rdata file:<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Please load the harmonics Rdata file.<span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/load\"><span style=\"color: #003399; font-weight: bold;\">load<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/file.choose\"><span style=\"color: #003399; font-weight: bold;\">file.choose<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Hard-coded version, if your harmonics file is always in the same place:<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#load('D:\/R\/Weather_data\/Harmonics_20120302.Rdata')<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Specify tide station, Site names: http:\/\/www.flaterco.com\/xtide\/locations.html<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Only the stations labeled 'Ref' will work with this script.<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Please enter the station name: <span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\nstationID = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/scan\"><span style=\"color: #003399; font-weight: bold;\">scan<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/file\"><span style=\"color: #003399; font-weight: bold;\">file<\/span><\/a> = <span style=\"color: #0000ff;\">''<\/span><span style=\"color: #339933;\">,<\/span> <a href=\"http:\/\/inside-r.org\/r-doc\/base\/character\"><span style=\"color: #003399; font-weight: bold;\">character<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">,<\/span> quiet = <span style=\"color: #000000; font-weight: bold;\">TRUE<\/span><span style=\"color: #339933;\">,<\/span> n = <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #339933;\">,<\/span> sep = <span style=\"color: #0000ff;\">'#'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Hard-coded version:<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#stationID = 'Monterey Harbor'<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#stationID = 'Boston, Boston Harbor'<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#stationID = 'San Diego, San Diego Bay'<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#stationID = 'Boston'<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Find row index of the desired station in the harms list that was loaded from<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># the harmonics Rdata file.<\/span>\r\nstInd = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/grep\"><span style=\"color: #003399; font-weight: bold;\">grep<\/span><\/a><span style=\"color: #009900;\">(<\/span>stationID<span style=\"color: #339933;\">,<\/span> harms$station<span style=\"color: #009900;\">)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># If no stations are found, or multiple possible stations are found, notify the<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># user.<\/span>\r\n<span style=\"color: #000000; font-weight: bold;\">if<\/span> <span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/length\"><span style=\"color: #003399; font-weight: bold;\">length<\/span><\/a><span style=\"color: #009900;\">(<\/span>stInd<span style=\"color: #009900;\">)<\/span> == <span style=\"color: #cc66cc;\">0<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">{<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'No station found.<span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #009900;\">}<\/span> <span style=\"color: #000000; font-weight: bold;\">else<\/span> <span style=\"color: #000000; font-weight: bold;\">if<\/span> <span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/length\"><span style=\"color: #003399; font-weight: bold;\">length<\/span><\/a><span style=\"color: #009900;\">(<\/span>stInd<span style=\"color: #009900;\">)<\/span> &gt; <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Multiple stations found, please choose one (enter number): <span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #000000; font-weight: bold;\">for<\/span> <span style=\"color: #009900;\">(<\/span>i <span style=\"color: #000000; font-weight: bold;\">in<\/span> <span style=\"color: #cc66cc;\">1<\/span>:<a href=\"http:\/\/inside-r.org\/r-doc\/base\/length\"><span style=\"color: #003399; font-weight: bold;\">length<\/span><\/a><span style=\"color: #009900;\">(<\/span>stInd<span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'['<\/span><span style=\"color: #339933;\">,<\/span> i<span style=\"color: #339933;\">,<\/span> <span style=\"color: #0000ff;\">']'<\/span><span style=\"color: #339933;\">,<\/span> harms$station<span style=\"color: #009900;\">[<\/span>stInd<span style=\"color: #009900;\">[<\/span>i<span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">]<\/span><span style=\"color: #339933;\">,<\/span><span style=\"color: #0000ff;\">'<span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #009900;\">}<\/span>\r\nchoice = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/scan\"><span style=\"color: #003399; font-weight: bold;\">scan<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/file\"><span style=\"color: #003399; font-weight: bold;\">file<\/span><\/a> = <span style=\"color: #0000ff;\">''<\/span><span style=\"color: #339933;\">,<\/span> what = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/numeric\"><span style=\"color: #003399; font-weight: bold;\">numeric<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">,<\/span> n = <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #339933;\">,<\/span> quiet = <span style=\"color: #000000; font-weight: bold;\">TRUE<\/span><span style=\"color: #009900;\">)<\/span>\r\nstInd = stInd<span style=\"color: #009900;\">[<\/span>choice<span style=\"color: #009900;\">]<\/span>\r\n<span style=\"color: #009900;\">}<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Show the name of the station being used<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Using station: '<\/span><span style=\"color: #339933;\">,<\/span> harms$station<span style=\"color: #009900;\">[<\/span>stInd<span style=\"color: #009900;\">]<\/span><span style=\"color: #339933;\">,<\/span><span style=\"color: #0000ff;\">'<span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Specify number of minutes between tide predictions<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Enter desired frequency of predictions in minutes (1-60): <span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\nfreq = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/scan\"><span style=\"color: #003399; font-weight: bold;\">scan<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/file\"><span style=\"color: #003399; font-weight: bold;\">file<\/span><\/a> = <span style=\"color: #0000ff;\">''<\/span><span style=\"color: #339933;\">,<\/span> <a href=\"http:\/\/inside-r.org\/r-doc\/base\/numeric\"><span style=\"color: #003399; font-weight: bold;\">numeric<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">,<\/span> quiet = <span style=\"color: #000000; font-weight: bold;\">TRUE<\/span><span style=\"color: #339933;\">,<\/span> n = <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#freq = 6 # units of minutes, hard coded version<\/span>\r\n\r\nfreq = freq * <span style=\"color: #cc66cc;\">60<\/span> <span style=\"color: #666666; font-style: italic;\"># convert minutes to seconds<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Specify start and end times for the tide predictions<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># If you cross a year boundary, the predictions must use the<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># correct equilibrium and nodefactors for each year.<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Enter starting time (YYYY-MM-DD HH:MM) in UTC\/GMT time zone: <span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\nt1 = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/scan\"><span style=\"color: #003399; font-weight: bold;\">scan<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/file\"><span style=\"color: #003399; font-weight: bold;\">file<\/span><\/a> = <span style=\"color: #0000ff;\">''<\/span><span style=\"color: #339933;\">,<\/span> <a href=\"http:\/\/inside-r.org\/r-doc\/base\/character\"><span style=\"color: #003399; font-weight: bold;\">character<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">,<\/span> quiet = <span style=\"color: #000000; font-weight: bold;\">TRUE<\/span><span style=\"color: #339933;\">,<\/span> n = <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #009900;\">)<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Enter ending time (YYYY-MM-DD HH:MM) in UTC\/GMT time zone: <span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\nt2 = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/scan\"><span style=\"color: #003399; font-weight: bold;\">scan<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/file\"><span style=\"color: #003399; font-weight: bold;\">file<\/span><\/a> = <span style=\"color: #0000ff;\">''<\/span><span style=\"color: #339933;\">,<\/span> <a href=\"http:\/\/inside-r.org\/r-doc\/base\/character\"><span style=\"color: #003399; font-weight: bold;\">character<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">,<\/span> quiet = <span style=\"color: #000000; font-weight: bold;\">TRUE<\/span><span style=\"color: #339933;\">,<\/span> n = <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Hard coded version:<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#t1 = '2012-12-31 23:00'<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">#t2 = '2013-01-01 09:00'<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Convert to POSIXct time format, with UTC time zone<\/span>\r\nt1 = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/as.POSIXct\"><span style=\"color: #003399; font-weight: bold;\">as.POSIXct<\/span><\/a><span style=\"color: #009900;\">(<\/span>t1<span style=\"color: #339933;\">,<\/span> tz = <span style=\"color: #0000ff;\">'UTC'<\/span><span style=\"color: #009900;\">)<\/span>\r\nt2 = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/as.POSIXct\"><span style=\"color: #003399; font-weight: bold;\">as.POSIXct<\/span><\/a><span style=\"color: #009900;\">(<\/span>t2<span style=\"color: #339933;\">,<\/span> tz = <span style=\"color: #0000ff;\">'UTC'<\/span><span style=\"color: #009900;\">)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Create data frame with sequence of times at desired frequency<\/span>\r\ntimes = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/data.frame\"><span style=\"color: #003399; font-weight: bold;\">data.frame<\/span><\/a><span style=\"color: #009900;\">(<\/span>POStime = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/seq\"><span style=\"color: #003399; font-weight: bold;\">seq<\/span><\/a><span style=\"color: #009900;\">(<\/span>t1<span style=\"color: #339933;\">,<\/span>t2<span style=\"color: #339933;\">,<\/span>freq<span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Extract the year for each of those time points<\/span>\r\ntimes$yr = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/as.POSIXlt\"><span style=\"color: #003399; font-weight: bold;\">as.POSIXlt<\/span><\/a><span style=\"color: #009900;\">(<\/span>times$POStime<span style=\"color: #009900;\">)<\/span>$year + <span style=\"color: #cc66cc;\">1900<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Use the year to make a character value representing the start of the year<\/span>\r\ntimes$yrstart = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/paste\"><span style=\"color: #003399; font-weight: bold;\">paste<\/span><\/a><span style=\"color: #009900;\">(<\/span>times$yr<span style=\"color: #339933;\">,<\/span> <span style=\"color: #0000ff;\">'01'<\/span><span style=\"color: #339933;\">,<\/span> <span style=\"color: #0000ff;\">'01'<\/span><span style=\"color: #339933;\">,<\/span> sep = <span style=\"color: #0000ff;\">'-'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Calculate hours since the start of the year for each time point<\/span>\r\ntimes$hours = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/as.numeric\"><span style=\"color: #003399; font-weight: bold;\">as.numeric<\/span><\/a><span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/difftime\"><span style=\"color: #003399; font-weight: bold;\">difftime<\/span><\/a><span style=\"color: #009900;\">(<\/span>times$POStime<span style=\"color: #339933;\">,<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/as.POSIXct\"><span style=\"color: #003399; font-weight: bold;\">as.POSIXct<\/span><\/a><span style=\"color: #009900;\">(<\/span>times$yrstart<span style=\"color: #339933;\">,<\/span> tz = <span style=\"color: #0000ff;\">'UTC'<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #339933;\">,<\/span> <a href=\"http:\/\/inside-r.org\/r-doc\/base\/units\"><span style=\"color: #003399; font-weight: bold;\">units<\/span><\/a> = <span style=\"color: #0000ff;\">'hours'<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Make a year index to pull correct starting values from harms for the year<\/span>\r\ntimes$yrindx = times$yr - harms$startyear + <span style=\"color: #cc66cc;\">1<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\">########################################<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Tide height calculation - Magic happens here<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Input times behave as if they are given in UTC, so output tides correspond to<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># the UTC times.<\/span>\r\npred = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/vector\"><span style=\"color: #003399; font-weight: bold;\">vector<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'numeric'<\/span><span style=\"color: #339933;\">,<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/nrow\"><span style=\"color: #003399; font-weight: bold;\">nrow<\/span><\/a><span style=\"color: #009900;\">(<\/span>times<span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span>\r\npred<span style=\"color: #009900;\">[<\/span><span style=\"color: #cc66cc;\">1<\/span>:<a href=\"http:\/\/inside-r.org\/r-doc\/base\/nrow\"><span style=\"color: #003399; font-weight: bold;\">nrow<\/span><\/a><span style=\"color: #009900;\">(<\/span>times<span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">]<\/span> = harms$datum<span style=\"color: #009900;\">[<\/span>stInd<span style=\"color: #009900;\">]<\/span>\r\n<span style=\"color: #000000; font-weight: bold;\">for<\/span> <span style=\"color: #009900;\">(<\/span>j <span style=\"color: #000000; font-weight: bold;\">in<\/span> <span style=\"color: #cc66cc;\">1<\/span>:<a href=\"http:\/\/inside-r.org\/r-doc\/base\/nrow\"><span style=\"color: #003399; font-weight: bold;\">nrow<\/span><\/a><span style=\"color: #009900;\">(<\/span>times<span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\r\n<span style=\"color: #000000; font-weight: bold;\">for<\/span> <span style=\"color: #009900;\">(<\/span>i <span style=\"color: #000000; font-weight: bold;\">in<\/span> <span style=\"color: #cc66cc;\">1<\/span>:<a href=\"http:\/\/inside-r.org\/r-doc\/base\/length\"><span style=\"color: #003399; font-weight: bold;\">length<\/span><\/a><span style=\"color: #009900;\">(<\/span>harms$name<span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span> <span style=\"color: #009900;\">{<\/span>\r\npred<span style=\"color: #009900;\">[<\/span>j<span style=\"color: #009900;\">]<\/span> = pred<span style=\"color: #009900;\">[<\/span>j<span style=\"color: #009900;\">]<\/span> + <span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">(<\/span>harms$nodefactor<span style=\"color: #009900;\">[<\/span>i<span style=\"color: #339933;\">,<\/span>times$yrindx<span style=\"color: #009900;\">[<\/span>j<span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">]<\/span> *\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/t\"><span style=\"color: #003399; font-weight: bold;\">t<\/span><\/a><span style=\"color: #009900;\">(<\/span>harms$A<span style=\"color: #009900;\">[<\/span>stInd<span style=\"color: #339933;\">,<\/span>i<span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">)<\/span> *\r\n<span style=\"color: #009900;\">(<\/span><a href=\"http:\/\/inside-r.org\/r-doc\/base\/cos\"><span style=\"color: #003399; font-weight: bold;\">cos<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #009900;\">(<\/span>harms$speed<span style=\"color: #009900;\">[<\/span>i<span style=\"color: #009900;\">]<\/span> *\r\ntimes$hours<span style=\"color: #009900;\">[<\/span>j<span style=\"color: #009900;\">]<\/span> +\r\nharms$equilarg<span style=\"color: #009900;\">[<\/span>i<span style=\"color: #339933;\">,<\/span> times$yrindx<span style=\"color: #009900;\">[<\/span>j<span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">]<\/span> -\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/t\"><span style=\"color: #003399; font-weight: bold;\">t<\/span><\/a><span style=\"color: #009900;\">(<\/span>harms$kappa<span style=\"color: #009900;\">[<\/span>stInd<span style=\"color: #339933;\">,<\/span>i<span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span> *\r\npi\/<span style=\"color: #cc66cc;\">180<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span><span style=\"color: #009900;\">)<\/span>\t\r\n<span style=\"color: #009900;\">}<\/span>\r\n<span style=\"color: #009900;\">}<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Finished tide height calculations, units of feet (sorry, that's the way it is)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\">####################################<\/span>\r\n\r\ntimesout = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/as.POSIXct\"><span style=\"color: #003399; font-weight: bold;\">as.POSIXct<\/span><\/a><span style=\"color: #009900;\">(<\/span>times$hours * <span style=\"color: #cc66cc;\">3600<\/span><span style=\"color: #339933;\">,<\/span> origin = times$yrstart<span style=\"color: #339933;\">,<\/span> tz = <span style=\"color: #0000ff;\">'UTC'<\/span><span style=\"color: #009900;\">)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># Make an output data frame<\/span>\r\nresults = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/data.frame\"><span style=\"color: #003399; font-weight: bold;\">data.frame<\/span><\/a><span style=\"color: #009900;\">(<\/span>TimeUTC = timesout<span style=\"color: #339933;\">,<\/span> TideHt.ft = pred<span style=\"color: #009900;\">)<\/span>\r\n\r\n<span style=\"color: #666666; font-style: italic;\"># This will produce a column of times in the current R session's time zone,<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># which isn't necessarily the time zone of your tide station.<\/span>\r\nresults$TimeLocal = <a href=\"http:\/\/inside-r.org\/r-doc\/base\/c\"><span style=\"color: #003399; font-weight: bold;\">c<\/span><\/a><span style=\"color: #009900;\">(<\/span>results$TimeUTC<span style=\"color: #009900;\">)<\/span>\r\n\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/base\/cat\"><span style=\"color: #003399; font-weight: bold;\">cat<\/span><\/a><span style=\"color: #009900;\">(<\/span><span style=\"color: #0000ff;\">'Finished. See \"results\" data frame for output.<span style=\"color: #000099; font-weight: bold;\">\\n<\/span>'<\/span><span style=\"color: #009900;\">)<\/span>\r\n<span style=\"color: #666666; font-style: italic;\"># Optionally print the results<\/span>\r\n<a href=\"http:\/\/inside-r.org\/r-doc\/graphics\/plot\"><span style=\"color: #003399; font-weight: bold;\">plot<\/span><\/a><span style=\"color: #009900;\">(<\/span>results$TimeUTC<span style=\"color: #339933;\">,<\/span>results$TideHt.ft<span style=\"color: #339933;\">,<\/span> type = <span style=\"color: #0000ff;\">'l'<\/span><span style=\"color: #339933;\">,<\/span> <a href=\"http:\/\/inside-r.org\/r-doc\/base\/col\"><span style=\"color: #003399; font-weight: bold;\">col<\/span><\/a> = <span style=\"color: #0000ff;\">'blue'<\/span><span style=\"color: #339933;\">,<\/span> las = <span style=\"color: #cc66cc;\">1<\/span><span style=\"color: #339933;\">,<\/span>\r\nxlab = <span style=\"color: #0000ff;\">'Time, UTC time zone'<\/span><span style=\"color: #339933;\">,<\/span> ylab = <span style=\"color: #0000ff;\">'Tide Height, ft'<\/span><span style=\"color: #339933;\">,<\/span>\r\nmain = harms$station<span style=\"color: #009900;\">[<\/span>stInd<span style=\"color: #009900;\">]<\/span><span style=\"color: #009900;\">)<\/span><\/pre>\n<\/div>\n<\/div>\n<p>In addition to these tide prediction routines, I have also previously provided R scripts to query the NOAA servers to retrieve measured, verified historical tide height data. That process is shown in <a href=\"https:\/\/lukemiller.org\/index.php\/2011\/02\/accessing-noaa-tide-data-with-r\/\">this older post.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Edit: There is now a full-fledged R package, rtide, to accomplish the same basic task of generating time series of tide predictions that is outlined here. See this more recent post for information. In the previous post I outlined how to query the XTide software with R and parse the results into a handy-dandy data [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[218,240],"tags":[58,62,157,153],"class_list":["post-1549","post","type-post","status-publish","format-standard","hentry","category-r-project","category-tide-prediction","tag-r-project","tag-tide-height","tag-tide-prediction","tag-xtide"],"_links":{"self":[{"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/posts\/1549","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/comments?post=1549"}],"version-history":[{"count":5,"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/posts\/1549\/revisions"}],"predecessor-version":[{"id":2317,"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/posts\/1549\/revisions\/2317"}],"wp:attachment":[{"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/media?parent=1549"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/categories?post=1549"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lukemiller.org\/index.php\/wp-json\/wp\/v2\/tags?post=1549"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}