<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/"> R – Monkeys Working</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Hi everyone!</p>
<p>  In this post we’re going to work with time series data, and write R functions to aggregate hourly and daily time series in monthly time series to catch a glimpse of their underlying patterns. For this analysis we’re going to use public meteorological data recorded by the government of the Argentinian province of San Luis. Data about rainfalls, temperature, humidity and in some cases winds, is published in the REM website (Red de Estaciones Meteorológicas, <a rel="nofollow" href="http://www.clima.edu.ar/" target="_blank">http://www.clima.edu.ar/</a>). Also, <a rel="nofollow" href="http://www.clima.edu.ar/InformePorPeriodo.aspx" target="_blank">here</a> you can download meteorological data (in .csv format) that has been recorded by weather stations around different places from San Luis.</p>
<p>   Even though weather stations are capable to record a huge amount of data, there is also a lot of work to do to obtain some information. For example, if observations are taken every hour, you’ll have 8700 records in 1 year!</p>
<p>So, in this post we’re going to:</p>
<ul>
<li>Write functions in R to aggregate the big amount of information provided by weather stations.</li>
<li>Make these functions as general as possible in terms of the structure of the input data (time series data) in order to simplify downstream analysis of this data.</li>
<li>Finally, we’re going to plot our results to reach some conclusions about the weather in one town in San Luis Province, Argentina.</li>
</ul>
<p>    We chose to work with data from La Calera. Take a look to our target site on the map! It’s a little town in the Northwest of the San Luis Province, located in a semiarid region. It makes this town and its neighbors really interesting places to work with because in this desert places, climate has well defined seasons and rainfalls occurs mainly in a few months of the year.</p>
<div><iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d20429.48980647832!2d-66.86110924123125!3d-32.877545858852166!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0:0x0!2zMzLCsDUyJzM5LjIiUyA2NsKwNTAnMzcuMSJX!5e1!3m2!1sen!2sar!4v1532448508178" width="450"></iframe></div>
<p>    We have already downloaded the .csv file of La Calera from the REM website, and you can find it<a rel="nofollow" href="https://github.com/federiva/Monkeys-Working/blob/master/la_calera/raw_data/meteorologicos_la_calera.csv" target="_blank"> here</a> . Ok! Let’s work!</p>
<h2>Tidying data – Writing an R function</h2>
<p>    First, we’re going to read the .csv with R and see its structure. How many rows does it have? Which are the first and the last dates? Which are the variables recorded? We’ll use head(), nrow() and str() to see it.</p>
<p></p>
<p>    As you can see, this weather station recorded rainfalls (mm), humidity (%) and temperature (°C) every hour. Data recording started on October 2007 and finished on April 2018 (the day that we downloaded the .csv). There are in total more than 91.000 observations for each variable!. Hourly data won’t allow us to find some of the climatic patterns that we are looking for, so, we need to summarize its information first as daily data and then as monthly data.</p>
<p>   We’re going to start writing an R function that will be useful for organize data in different stages of the analysis (<span>see the flowchart below</span>) . It takes the date of every row and splits it up in 3 columns: one column with the day’s number, a second column with the month’s number, and the last one with the year. In this function, we’re going to use the<a rel="nofollow" href="https://cran.r-project.org/web/packages/lubridate/lubridate.pdf" target="_blank"> lubridate package.</a> This package has some useful functions that we need: day(), month() and year() which extract the corresponding time component from a given date. In the following functions, we’ll use these new columns to subset the data.</p>
<p><img data-orig-file="https://monkeysworking.files.wordpress.com/2018/08/diagrama_de_flujo_funcion.png?w=392&amp;h=541&amp;fit=392%2C541&amp;resize=392%2C541" data-orig-size="3495,4819" data-medium-file="https://monkeysworking.files.wordpress.com/2018/08/diagrama_de_flujo_funcion.png?w=392&amp;h=541&amp;fit=392%2C541&amp;resize=392%2C541?w=218" data-attachment-id="128" data-image-meta="{" data-image-description="" src="https://monkeysworking.files.wordpress.com/2018/08/diagrama_de_flujo_funcion.png?w=392&h=541&fit=392%2C541&resize=392%2C541" data-permalink="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/diagrama_de_flujo_funcion/" data-large-file="https://monkeysworking.files.wordpress.com/2018/08/diagrama_de_flujo_funcion.png?w=392&amp;h=541&amp;fit=392%2C541&amp;resize=392%2C541?w=723" alt="diagrama_de_flujo_funcion" data-image-title="diagrama_de_flujo_funcion" sizes="(max-width: 392px) 100vw, 392px" width="392" data-comments-opened="1" class="wp-image-128" data-recalc-dims="1" height="541"></p>
<p></p>
<p>If we use our function, we get:</p>
<p></p>
<h2>Aggregate daily data – Writing an R function</h2>
<p>    Now, we’re going to aggregate our hourly data in daily data. We wrote another function that uses the columns that we have obtained to subset the data. For each day,  we created a subset with its corresponding hours and calculated the daily mean or the sum for data (<span>see the diagram below</span>).</p>
<p><img data-orig-file="https://monkeysworking.files.wordpress.com/2018/08/flowchart_funcion21.png?w=456" data-orig-size="2362,840" data-medium-file="https://monkeysworking.files.wordpress.com/2018/08/flowchart_funcion21.png?w=456?w=300" data-attachment-id="130" data-image-meta="{" data-image-description="" src="https://monkeysworking.files.wordpress.com/2018/08/flowchart_funcion21.png?w=456" data-permalink="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/flowchart_funcion2-2/" data-large-file="https://monkeysworking.files.wordpress.com/2018/08/flowchart_funcion21.png?w=456?w=723" alt="flowchart_funcion2" data-image-title="flowchart_funcion2" sizes="(max-width: 723px) 100vw, 723px" data-comments-opened="1" class="wp-image-130" data-recalc-dims="1"></p>
<p> As we’re working with meteorological data, the sum will be useful for precipitations, and the mean for temperature. We calculated the daily mean value as an average of extreme hourly values, due to daily mean temperature it’s commonly estimated as the average of minimum and maximum temperatures (see <a rel="nofollow" href="http://climod.nrcc.cornell.edu/static/glossary.html" target="_blank">http://climod.nrcc.cornell.edu/static/glossary.html</a> and <span><a rel="nofollow" href="https://rmets.onlinelibrary.wiley.com/doi/epdf/10.1002/joc.1363" target="_blank">Dall’Amico and </a><span><a rel="nofollow" href="https://rmets.onlinelibrary.wiley.com/doi/epdf/10.1002/joc.1363" target="_blank">Hornsteiner, 2006</a>)</span></span>.  This is:</p>
<p>For each day of hourly data we have the following set: <img alt="T={T_0,...,T_{23}} " title="T={T_0,...,T_{23}} " src="https://s0.wp.com/latex.php?latex=T%3D%5C%7BT_0%2C...%2CT_%7B23%7D%5C%7D+&bg=ffffff&%23038;fg=3a3a3a&%23038;s=0" class="latex"> so we calculate the average as:</p>
<div align="center"><img alt="average_T= {{max(T) + min(T)} over {2}} " title="average_T= {{max(T) + min(T)} over {2}} " src="https://s0.wp.com/latex.php?latex=average_T%3D+%7B%7Bmax%28T%29+%2B+min%28T%29%7D+%5Cover+%7B2%7D%7D+&bg=ffffff&%23038;fg=3a3a3a&%23038;s=2" class="latex"></div>
<p>In R, we can do it using max() and min() functions. But wait! It’s normal that weather stations don’t work during some days, so you can have entire days where they only recorded “NAs”. So, you have to keep this in mind, because max() and min() functions will return you:</p>
<pre>
In min(x) : no non-missing arguments to min; returning Inf
In max(x) : no non-missing arguments to min; returning Inf
</pre>
<p>    To avoid that, we used an if…else statement in  line 32.</p>
<p></p>
<h3>Exploratory plots – Daily data from La Calera</h3>
<p>Let’s plot daily data to look for patterns!</p>
<pre>
# 1) a) Daily accumulated rainfall
d_mm_ac &lt;- HourlyToDaily(data.x = calera_organized, ncol.obs = 2, na.presence = TRUE, value = &quot;accumulated&quot;, ncol.date = 1)
head(d_mm_ac)
#
plot(x = d_mm_ac$date,
     y = d_mm_ac$value,
     type = &quot;l&quot;,
     xlab = &quot;Date&quot;,
     ylab = &quot;daily accumulated precipitation (mm)&quot;)
#
# 1) b) Daily mean temperature (°C)
d_t_mean &lt;- HourlyToDaily(data.x = calera_organized, ncol.obs = 3, na.presence = TRUE, value = &quot;mean&quot;, ncol.date = 1)
head(d_t_mean)
#
plot(x = d_t_mean$date,
     y = d_t_mean$value,
     type = &quot;l&quot;,
     xlab = &quot;Date&quot;,
     ylab = &quot;daily mean temperature (°C)&quot;)
</pre>
<p><img data-orig-file="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_precipitations.jpeg?w=450&amp;h=367&amp;fit=686%2C367" data-orig-size="4409,2362" data-medium-file="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_precipitations.jpeg?w=450&amp;h=367&amp;fit=686%2C367?w=300" data-attachment-id="121" data-image-meta="{" data-image-description="" src="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_precipitations.jpeg?w=450&h=367&fit=686%2C367" data-permalink="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/calera_daily_precipitations/" data-large-file="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_precipitations.jpeg?w=450&amp;h=367&amp;fit=686%2C367?w=723" alt="calera_daily_precipitations" data-image-title="calera_daily_precipitations" sizes="(max-width: 686px) 100vw, 686px" data-comments-opened="1" class="wp-image-121" data-recalc-dims="1"> <img data-orig-file="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_mean_temperature.jpeg?w=456" data-orig-size="4409,2362" data-medium-file="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_mean_temperature.jpeg?w=456?w=300" data-attachment-id="122" data-image-meta="{" data-image-description="" src="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_mean_temperature.jpeg?w=456" data-permalink="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/calera_daily_mean_temperature/" data-large-file="https://monkeysworking.files.wordpress.com/2018/07/calera_daily_mean_temperature.jpeg?w=456?w=723" alt="calera_daily_mean_temperature" data-image-title="calera_daily_mean_temperature" sizes="(max-width: 723px) 100vw, 723px" data-comments-opened="1" class="wp-image-122" data-recalc-dims="1"></p>
<p>We’ve already have our first results! Rainfalls are higher during a period of each year, and between periods there are gaps of dry weather. On the other side, mean temperatures have an oscillating pattern, reaching 30°C in summer and 0°C in winter. So, as we expected from this temperate desert place, seasons are well-defined and temperature have a wide range through the year.</p>
<h2>Aggregate monthly data – Writing an R function</h2>
<p>  Ok, let’s continue a bit more! To aggregate from daily data to monthly data, we have to use again the first function (add the time component’s columns) and then build a function with “for loops” similar to the second function. In this case, we didn’t use max() or min() functions, because monthly means are simply the average of daily means per month.</p>
<p>    We ran the function:</p>
<pre>
# 2) Getting monthly data from daily data
#
MonthlyValue &lt;- function(data.x, ncol.obs, value = &quot;mean&quot;,
                         na.presence = TRUE) {
  #
  if (!any(value == c(&quot;mean&quot;, &quot;accumulated&quot;))) {
    stop(&quot;value must be 'mean' or 'accumulated'&quot;)
  }
  #
  # Calculate the mean of the variable of interest
  first.year &lt;- min(data.x$year, na.rm = na.presence)
  last.year  &lt;- max(data.x$year, na.rm = na.presence)
  x.per.month &lt;- list()
  name.month.tot &lt;- list()
  name.year.tot  &lt;- list()
  c = 1
  #  Creates a temporary i data.frame for each year == i
  for (i in first.year:last.year) {
    x.anual &lt;- data.x[data.x$year == i, ]
    # It takes the i year df and creates a j df for each month == j
    first.month = min(x.anual$month, na.rm = na.presence)
    last.month  = max(x.anual$month, na.rm = na.presence)
    name.month &lt;- list()
    name.year  &lt;- list()
    x.value &lt;- list()
    for (j in first.month:last.month) {
      x.month &lt;- x.anual[x.anual$month == j, ]
      # Calculates the mean value or the accumulated value
      if (value == &quot;mean&quot;) {
        x.value[j] &lt;- mean(x = x.month[ , ncol.obs], na.rm = na.presence)
        name.month[j] &lt;- j
        name.year[j]  &lt;- i
      } else {
        x.value[j] &lt;- sum(x = x.month[ , ncol.obs], na.rm = na.presence)
        name.month[j] &lt;- j
        name.year[j]  &lt;- i
      }
    } # end cycle month
    x.per.month[[c]] &lt;- unlist(x.value)
    name.month.tot[[c]]    &lt;- unlist(name.month)
    name.year.tot[[c]]     &lt;- unlist(name.year)
    c = c + 1
  } # end cycle year
  monthly.data &lt;- as.data.frame(cbind(unlist(name.month.tot),
                                      unlist(name.year.tot),
                                      unlist(x.per.month)))
  if (value == &quot;mean&quot;) {
    colnames(monthly.data) &lt;- c(&quot;month.order&quot;, &quot;year&quot;, &quot;mean.value&quot;)
  } else {
    colnames(monthly.data) &lt;- c(&quot;month.order&quot;, &quot;year&quot;, &quot;accumulated.value&quot;)
  }
  return(monthly.data)
}
</pre>
<p>and we obtained the followings monthly time series:</p>
<p></p>
<h3>Exploratory plots – Monthly data from La Calera</h3>
<p>    To end this analysis, we’re going to do an exploratory analysis of our monthly data. For this we are going to make a multiple barplot using a ‘for loop’ and an overlayed lineplot for each one of the years in the dataset.</p>
<pre>
# plot with monthly data
plot.calera &lt;- function() {
  parameters.1 &lt;- par(mfrow = c(4, 3),
                    mar = c(3,3,3,1.5),
                    oma = c(3,3,3,3))
  for (i in seq(from = unique(m_mm_ac$year)[1],
                to = unique(m_mm_ac$year)[length(unique(m_mm_ac$year))])) {
    barplot(height = m_mm_ac[m_mm_ac$year == i, 3],
            names.arg = m_mm_ac[m_mm_ac$year == i, 1],
            col = &quot;lightgreen&quot;,
            axes = TRUE,
            main = i,
            cex.main = 0.8,
            ylim = c(0, 140),
            xlim = c(0,12),
            space = 0)
    lines(y = (m_t_mean[m_t_mean$year == i, 3]),
          ylim = c(0, 70),
          x = ((m_mm_ac[m_mm_ac$year == i, 1]) - 0.5),
          type = &quot;o&quot;,
          col = &quot;darkorange&quot;,
          lwd = 2,
          pch = 16)
    axis(side = 4)
  }
  title(main = &quot;Accumulated rainfalls and temperature per month in La Calera&quot;,
        cex.main = 1.3,
        xlab = &quot;Months&quot;,
        cex.lab = 1.5,
        ylab = &quot;Monthly accumulated precipitation&quot;,
        outer = TRUE,
        line = 0)
  mtext(text = &quot;Monthly mean temperature °C&quot;,
        side = 4,
        cex = 1,
        outer = TRUE,
        line = 1.2)
  par(parameters.1)
}
plot_calera &lt;- plot.calera()
</pre>
<p><img data-orig-file="https://monkeysworking.files.wordpress.com/2018/07/la_calera.png?w=456" data-orig-size="2953,2953" data-medium-file="https://monkeysworking.files.wordpress.com/2018/07/la_calera.png?w=456?w=300" data-attachment-id="124" data-image-meta="{" data-image-description="" src="https://monkeysworking.files.wordpress.com/2018/07/la_calera.png?w=456" data-permalink="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/la_calera/" data-large-file="https://monkeysworking.files.wordpress.com/2018/07/la_calera.png?w=456?w=723" alt="la_calera" data-image-title="la_calera" sizes="(max-width: 723px) 100vw, 723px" data-comments-opened="1" class="wp-image-124" data-recalc-dims="1"></p>
<p>    As we previously saw, rains are concentrated only in some months. We can distinguish from the bar charts that La Calera has a dry period during winter, when temperatures are lower, and a rainy period during the warm seasons.</p>
<p>    Well, the analysis about yearly means of accumulated precipitations and temperatures  it is now up to you!</p>
<p>   You can see the entire R script of this post in<a rel="nofollow" href="https://github.com/federiva/Monkeys-Working/blob/master/la_calera/la_calera.R" target="_blank"> here</a>, and remember that all of our scripts and data used for the blog are available in<a rel="nofollow" href="https://monkeysworking.wordpress.com/about-us/" target="_blank"> our GitHubs.</a></p>
<p>    And, if you’re interested in other analysis of different kinds of time series data, you could take a look to our other post:</p>
<ul>
<li><a rel="nofollow" href="https://monkeysworking.wordpress.com/2018/06/08/time-series-data-analysis-part-1/" target="_blank">Exchange rate (ARS / USD) – Part I – Getting data – AWK and R</a></li>
<li><a rel="nofollow" href="https://monkeysworking.wordpress.com/2018/06/14/exchange-rate-ars-usd-part-ii-writing-r-functions-to-analyze-simple-variations-and-making-animations-to-visualize-them/" target="_blank">Exchange rate (ARS / USD) – Part II – Writing R functions to analyze simple variations and making animations to visualize them</a></li>
</ul>
<p>See you in the next post!</p>
<p> </p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://monkeysworking.wordpress.com/2018/08/06/temporal-aggregations-on-time-series-data-writing-r-functions-to-tidy-meteorological-data-and-getting-some-insights-from-it/"> R – Monkeys Working</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/esuvi2uW4sM" height="1"></a></div>