-
Notifications
You must be signed in to change notification settings - Fork 0
/
06-func-R.html
378 lines (364 loc) · 26.7 KB
/
06-func-R.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<title>Software Carpentry: R for reproducible scientific analysis</title>
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="css/bootstrap/bootstrap-theme.css" />
<link rel="stylesheet" type="text/css" href="css/swc.css" />
<link rel="alternate" type="application/rss+xml" title="Software Carpentry Blog" href="http://software-carpentry.org/feed.xml"/>
<meta charset="UTF-8" />
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body class="lesson">
<div class="container card">
<div class="banner">
<a href="http://software-carpentry.org" title="Software Carpentry">
<img alt="Software Carpentry banner" src="img/software-carpentry-banner.png" />
</a>
</div>
<article>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<a href="index.html"><h1 class="title">R for reproducible scientific analysis</h1></a>
<h2 class="subtitle">Creating functions</h2>
<section class="objectives panel panel-warning">
<div class="panel-heading">
<h2 id="learning-objectives"><span class="glyphicon glyphicon-certificate"></span>Learning objectives</h2>
</div>
<div class="panel-body">
<ul>
<li>Define a function that takes arguments.</li>
<li>Return a value from a function.</li>
<li>Set default values for function arguments.</li>
<li>Explain why we should divide programs into small, single-purpose functions.</li>
</ul>
</div>
</section>
<p>If we only had one data set to analyse, it would probably be faster to load the file into a spreadsheet and use that to plot simple statistics. However, the gapminder data is updated periodically, and we may want to pull in that new information later and re-run our analysis again. We may also obtain similar data from a different source in the future.</p>
<p>In this lesson, we’ll learn how to write a function so that we can repeat several operations with a single command.</p>
<h3 id="defining-a-function">Defining a function</h3>
<p>Let’s start by defining a function <code>fahr_to_kelvin</code> that converts temperatures from Fahrenheit to Kelvin:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">fahr_to_kelvin <-<span class="st"> </span>function(temp) {
kelvin <-<span class="st"> </span>((temp -<span class="st"> </span><span class="dv">32</span>) *<span class="st"> </span>(<span class="dv">5</span> /<span class="st"> </span><span class="dv">9</span>)) +<span class="st"> </span><span class="fl">273.15</span>
<span class="kw">return</span>(kelvin)
}</code></pre></div>
<p>We define <code>fahr_to_kelvin</code> by assigning it to the output of <code>function</code>. The list of argument names are containted within parentheses. Next, the <a href="reference.html#function-body">body</a> of the function–the statements that are executed when it runs–is contained within curly braces (<code>{}</code>). The statements in the body are indented by two spaces. This makes the code easier to read but does not affect how the code operates.</p>
<p>When we call the function, the values we pass to it are assigned to those variables so that we can use them inside the function. Inside the function, we use a <a href="reference.html#return-statement">return statement</a> to send a result back to whoever asked for it.</p>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h2 id="tip"><span class="glyphicon glyphicon-pushpin"></span>Tip</h2>
</div>
<div class="panel-body">
<p>One feature unique to R is that the return statement is not required. R automatically returns whichever variable is on the last line of the body of the function. Since we are just learning, we will explicitly define the return statement.</p>
</div>
</aside>
<p>Let’s try running our function. Calling our own function is no different from calling any other function:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co"># freezing point of water</span>
<span class="kw">fahr_to_kelvin</span>(<span class="dv">32</span>)</code></pre></div>
<pre class="output"><code>[1] 273.15
</code></pre>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co"># boiling point of water</span>
<span class="kw">fahr_to_kelvin</span>(<span class="dv">212</span>)</code></pre></div>
<pre class="output"><code>[1] 373.15
</code></pre>
<p>We’ve successfully called the function that we defined, and we have access to the value that we returned.</p>
<h3 id="composing-functions">Composing Functions</h3>
<p>Now that we’ve seen how to turn Fahrenheit into Kelvin, it’s easy to turn Kelvin into Celsius:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">kelvin_to_celsius <-<span class="st"> </span>function(temp) {
celsius <-<span class="st"> </span>temp -<span class="st"> </span><span class="fl">273.15</span>
<span class="kw">return</span>(celsius)
}
<span class="co">#absolute zero in Celsius</span>
<span class="kw">kelvin_to_celsius</span>(<span class="dv">0</span>)</code></pre></div>
<pre class="output"><code>[1] -273.15
</code></pre>
<p>What about converting Fahrenheit to Celsius? We could write out the formula, but we don’t need to. Instead, we can <a href="reference.html#function-composition">compose</a> the two functions we have already created:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">fahr_to_celsius <-<span class="st"> </span>function(temp) {
temp_k <-<span class="st"> </span><span class="kw">fahr_to_kelvin</span>(temp)
result <-<span class="st"> </span><span class="kw">kelvin_to_celsius</span>(temp_k)
<span class="kw">return</span>(result)
}
<span class="co"># freezing point of water in Celsius</span>
<span class="kw">fahr_to_celsius</span>(<span class="fl">32.0</span>)</code></pre></div>
<pre class="output"><code>[1] 0
</code></pre>
<p>This is our first taste of how larger programs are built: we define basic operations, then combine them in ever-large chunks to get the effect we want. Real-life functions will usually be larger than the ones shown here–typically half a dozen to a few dozen lines–but they shouldn’t ever be much longer than that, or the next person who reads it won’t be able to understand what’s going on.</p>
<section class="challenge panel panel-success">
<div class="panel-heading">
<h2 id="challenge---create-a-function"><span class="glyphicon glyphicon-pencil"></span>Challenge - Create a function</h2>
</div>
<div class="panel-body">
<ul>
<li>In the first lesson, we learned to <strong>c</strong>oncatenate elements into a vector using the <code>c</code> function, e.g. <code>x <- c("A", "B", "C")</code> creates a vector <code>x</code> with three elements. Furthermore, we can extend that vector again using <code>c</code>, e.g. <code>y <- c(x, "D")</code> creates a vector <code>y</code> with four elements. Write a function called <code>fence</code> that takes two vectors as arguments, called <code>original</code> and <code>wrapper</code>, and returns a new vector that has the wrapper vector at the beginning and end of the original:</li>
</ul>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">best_practice <-<span class="st"> </span><span class="kw">c</span>(<span class="st">"Write"</span>, <span class="st">"programs"</span>, <span class="st">"for"</span>, <span class="st">"people"</span>, <span class="st">"not"</span>, <span class="st">"computers"</span>)
asterisk <-<span class="st"> "***"</span> <span class="co"># R interprets a variable with a single value as a vector</span>
<span class="co"># with one element.</span>
<span class="kw">fence</span>(best_practice, asterisk)</code></pre></div>
<pre class="output"><code>[1] "***" "Write" "programs" "for" "people" "not"
[7] "computers" "***"
</code></pre>
<ul>
<li>If the variable <code>v</code> refers to a vector, then <code>v[1]</code> is the vector’s first element and <code>v[length(v)]</code> is its last (the function <code>length</code> returns the number of elements in a vector). Write a function called <code>outside</code> that returns a vector made up of just the first and last elements of its input:</li>
</ul>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">dry_principle <-<span class="st"> </span><span class="kw">c</span>(<span class="st">"Don't"</span>, <span class="st">"repeat"</span>, <span class="st">"yourself"</span>, <span class="st">"or"</span>, <span class="st">"others"</span>)
<span class="kw">outside</span>(dry_principle)</code></pre></div>
<pre class="output"><code>[1] "Don't" "others"
</code></pre>
</div>
</section>
<p>Going back to our data, we’re going to define a function, called <code>calcGDP</code>, that calculates the Gross Domestic Product of a nation from the data available in our dataset by multiplying the total population with the gross national income per capita.</p>
<p>Let’s create a new folder within our project called <code>functions/</code>. Then open a new R script file and save it under the <code>functions/</code> directory with the name <code>calcGDP-function.R</code>.</p>
<p>Then within the R script type:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co"># Takes a dataset and multiplies the population column</span>
<span class="co"># with the GDP per capita column.</span>
calcGDP <-<span class="st"> </span>function(dat) {
gdp <-<span class="st"> </span>dat$pop *<span class="st"> </span>dat$gdpPercap
<span class="kw">return</span>(gdp)
}</code></pre></div>
<p>Source the file and then apply the function <code>calcGDP</code> to the first few rows of our <code>gapminder</code> data frame.</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">calcGDP</span>(<span class="kw">head</span>(gapminder))</code></pre></div>
<p>What we get is a vector:</p>
<pre class="output"><code>[1] 6567086330 7585448670 8758855797 9648014150 9678553274 11697659231
</code></pre>
<h3 id="defining-defaults">Defining Defaults</h3>
<p>Let’s expand the <code>calcGDP</code> function, by adding some more arguments, so that we can extract the Gross Domestic Product for a specific year and a specific country. Another feature of the new function is to return the Gross Domestic Product as an added column to the input data frame. Edit the function as follows:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co"># Takes a dataset and multiplies the population column</span>
<span class="co"># with the GDP per capita column.</span>
calcGDP <-<span class="st"> </span>function(dat, <span class="dt">year=</span><span class="ot">NULL</span>, <span class="dt">country=</span><span class="ot">NULL</span>) {
dat <-<span class="st"> </span>dat[dat$year ==<span class="st"> </span>year, ]
dat <-<span class="st"> </span>dat[dat$country ==<span class="st"> </span>country,]
gdp <-<span class="st"> </span>dat$pop *<span class="st"> </span>dat$gdpPercap
new <-<span class="st"> </span><span class="kw">cbind</span>(dat, <span class="dt">gdp=</span>gdp)
<span class="kw">return</span>(new)
}</code></pre></div>
<p>Here we’ve added two arguments, <code>year</code> and <code>country</code>, which we use to slice our <code>dat</code> data.frame and then compute the Gross Domestic Product on a subset of the data.</p>
<p>To add a column to the data.frame, we used the function <code>cbind</code>, which is a two-dimensional equivalents of the <code>c</code> function, and assigned the name <code>gdp</code> to the new column.</p>
<p>So let’s take a look at the output when we call <code>calcGDP</code> for Australia in 2007:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">source</span>(<span class="st">"functions/calcGDP-function.R"</span>)
<span class="kw">calcGDP</span>(gapminder, <span class="dt">year=</span><span class="dv">2007</span>, <span class="dt">country=</span><span class="st">"Australia"</span>)</code></pre></div>
<pre class="output"><code> country year pop continent lifeExp gdpPercap gdp
72 Australia 2007 20434176 Oceania 81.235 34435.37 703658358894</code></pre>
<p>We’ve set <em>default arguments</em> for both <code>year</code> and <code>country</code> variables to <code>NULL</code> using the <code>=</code> operator in the function definition. This means that those arguments will take on those values unless the user specifies otherwise.</p>
<p>This is handy because by default we can run the function <code>calcGDP</code> on the whole data frame, but also have the option to run in a subset of the data frame by passing an argument to either or both optional arguments.</p>
<p>So let us check that our function is still working for the first few rows of our <code>gapminder</code> data frame as before.</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">calcGDP</span>(<span class="kw">head</span>(gapminder))</code></pre></div>
<pre class="output"><code>[1] country year pop continent lifeExp gdpPercap gdp
<0 rows> (or 0-length row.names)
</code></pre>
<p>It doesn’t return any output. Why?</p>
<p>The <code>year</code> and <code>country</code> arguments of our function <code>calcGDP</code> are by default set to <code>NULL</code>. But within the function body we slice the <code>dat</code> data frame based on these values. So when these are set to NULL the slicing returns:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">year <-<span class="st"> </span><span class="ot">NULL</span>
gapminder[gapminder$year ==<span class="st"> </span>year, ]</code></pre></div>
<pre class="output"><code>[1] country year pop continent lifeExp gdpPercap gdp
<0 rows> (or 0-length row.names)
</code></pre>
<h3 id="conditionals">Conditionals</h3>
<p>In order to update our function to decide between slicing the dataframe or not, we need to write code that automatically decides between multiple options. The tool R gives us for doing this is called a conditional statement, and looks like this:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">num <-<span class="st"> </span><span class="dv">37</span>
if (num ><span class="st"> </span><span class="dv">100</span>) {
<span class="kw">print</span>(<span class="st">"greater"</span>)
} else {
<span class="kw">print</span>(<span class="st">"not greater"</span>)
}</code></pre></div>
<pre class="output"><code>[1] "not greater"
</code></pre>
<p>In our case we want to check whether the arguments <code>year</code> and <code>country</code> are not NULL. To do so we will use a built in function called <code>is.null</code> and the special operator <code>!</code>.</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r">year <-<span class="st"> </span><span class="ot">NULL</span>
if (!<span class="kw">is.null</span>(year)) {
<span class="kw">print</span>(<span class="st">"year is defined"</span>)
} else {
<span class="kw">print</span>(<span class="st">"year is NULL"</span>)
}</code></pre></div>
<pre class="output"><code>[1] "year is NULL"
</code></pre>
<section class="challenge panel panel-success">
<div class="panel-heading">
<h4 id="challenge---adding-conditional-statements"><span class="glyphicon glyphicon-pencil"></span>Challenge - Adding conditional statements</h4>
</div>
<div class="panel-body">
<p>Modify the <code>calcGDP</code> function to check whether each additional argument is set to <code>null</code>. Whenever they’re not <code>null</code> overwrite the dataset stored in <code>dat</code> with a subset given by the non-<code>null</code> argument.</p>
</div>
</section>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co"># Takes a dataset and multiplies the population column</span>
<span class="co"># with the GDP per capita column.</span>
calcGDP <-<span class="st"> </span>function(dat, <span class="dt">year=</span><span class="ot">NULL</span>, <span class="dt">country=</span><span class="ot">NULL</span>) {
if(!<span class="kw">is.null</span>(year)){
dat <-<span class="st"> </span>dat[dat$year ==<span class="st"> </span>year, ]
}
if(!<span class="kw">is.null</span>(country))
{
dat <-<span class="st"> </span>dat[dat$country ==<span class="st"> </span>country,]
}
gdp <-<span class="st"> </span>dat$pop *<span class="st"> </span>dat$gdpPercap
new <-<span class="st"> </span><span class="kw">cbind</span>(dat, <span class="dt">gdp=</span>gdp)
<span class="kw">return</span>(new)
}</code></pre></div>
<p>Now when calling the <code>calcGDP</code> function specifying only the country:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">calcGDP</span>(gapminder, <span class="dt">country=</span><span class="st">"Australia"</span>)</code></pre></div>
<pre class="output"><code> country year pop continent lifeExp gdpPercap gdp
61 Australia 1952 8691212 Oceania 69.120 10039.60 87256254102
62 Australia 1957 9712569 Oceania 70.330 10949.65 106349227169
63 Australia 1962 10794968 Oceania 70.930 12217.23 131884573002
64 Australia 1967 11872264 Oceania 71.100 14526.12 172457986742
65 Australia 1972 13177000 Oceania 71.930 16788.63 221223770658
66 Australia 1977 14074100 Oceania 73.490 18334.20 258037329175
67 Australia 1982 15184200 Oceania 74.740 19477.01 295742804309
68 Australia 1987 16257249 Oceania 76.320 21888.89 355853119294
69 Australia 1992 17481977 Oceania 77.560 23424.77 409511234952
70 Australia 1997 18565243 Oceania 78.830 26997.94 501223252921
71 Australia 2002 19546792 Oceania 80.370 30687.75 599847158654
72 Australia 2007 20434176 Oceania 81.235 34435.37 703658358894
</code></pre>
<p>We did this so that our function is more flexible for later. We can ask it to calculate the GDP for:</p>
<ul>
<li>The whole dataset;</li>
<li>A single year;</li>
<li>A single country;</li>
<li>A single combination of year and country.</li>
</ul>
<p>By using another speecial operator, <code>%in%</code> instead of <code>==</code> for the conditional splicing of the dataframe, we can also give multiple years or countries to those arguments. So the function becomes general enough:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="co"># Takes a dataset and multiplies the population column</span>
<span class="co"># with the GDP per capita column.</span>
calcGDP <-<span class="st"> </span>function(dat, <span class="dt">year=</span><span class="ot">NULL</span>, <span class="dt">country=</span><span class="ot">NULL</span>) {
if(!<span class="kw">is.null</span>(year)){
dat <-<span class="st"> </span>dat[dat$year %in%<span class="st"> </span>year, ]
}
if(!<span class="kw">is.null</span>(country))
{
dat <-<span class="st"> </span>dat[dat$country %in%<span class="st"> </span>country,]
}
gdp <-<span class="st"> </span>dat$pop *<span class="st"> </span>dat$gdpPercap
new <-<span class="st"> </span><span class="kw">cbind</span>(dat, <span class="dt">gdp=</span>gdp)
<span class="kw">return</span>(new)
}</code></pre></div>
<p>Now when calling the <code>calcGDP</code> function specifying two countries and a year:</p>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"><span class="kw">calcGDP</span>(gapminder, <span class="dt">year=</span><span class="dv">2007</span>, <span class="dt">country=</span><span class="kw">c</span>(<span class="st">"Argentina"</span>, <span class="st">"Australia"</span>))</code></pre></div>
<pre class="output"><code> country year pop continent lifeExp gdpPercap gdp
60 Argentina 2007 40301927 Americas 75.320 12779.38 515033625357
72 Australia 2007 20434176 Oceania 81.235 34435.37 703658358894
</code></pre>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h4 id="tip-pass-by-value"><span class="glyphicon glyphicon-pushpin"></span>Tip: Pass by value</h4>
</div>
<div class="panel-body">
<p>Functions in R almost always make copies of the data to operate on inside of a function body. When we modify <code>dat</code> inside the function we are modifying the copy of the gapminder dataset stored in <code>dat</code>, not the original variable we gave as the first argument.</p>
<p>This is called “pass-by-value” and it makes writing code much safer: you can always be sure that whatever changes you make within the body of the function, stay inside the body of the function.</p>
</div>
</aside>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h4 id="tip-function-scope"><span class="glyphicon glyphicon-pushpin"></span>Tip: Function scope</h4>
</div>
<div class="panel-body">
<p>Another important concept is scoping: any variables (or functions!) you create or modify inside the body of a function only exist for the lifetime of the function’s execution. When we call <code>calcGDP</code>, the variables <code>dat</code>, <code>gdp</code> and <code>new</code> only exist inside the body of the function. Even if we have variables of the same name in our interactive R session, they are not modified in any way when executing a function.</p>
</div>
</aside>
<div class="sourceCode"><pre class="sourceCode r"><code class="sourceCode r"> gdp <-<span class="st"> </span>dat$pop *<span class="st"> </span>dat$gdpPercap
new <-<span class="st"> </span><span class="kw">cbind</span>(dat, <span class="dt">gdp=</span>gdp)
<span class="kw">return</span>(new)</code></pre></div>
<p>Finally, we calculated the GDP on our new subset, and created a new data frame with that column added. This means when we call the function later we can see the context for the returned GDP values, which is much better than in our first attempt where we just got a vector of numbers.</p>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h2 id="tip-1"><span class="glyphicon glyphicon-pushpin"></span>Tip</h2>
</div>
<div class="panel-body">
<p>R has some unique aspects that can be exploited when performing more complicated operations. We will not be writing anything that requires knowledge of these more advanced concepts. In the future when you are comfortable writing functions in R, you can learn more by reading the <a href="http://cran.r-project.org/doc/manuals/r-release/R-lang.html#Environment-objects">R Language Manual</a> or this <a href="http://adv-r.had.co.nz/Environments.html">chapter</a> from <a href="http://adv-r.had.co.nz/">Advanced R Programming</a> by Hadley Wickham. For context, R uses the terminology “environments” instead of frames.</p>
</div>
</aside>
<aside class="callout panel panel-info">
<div class="panel-heading">
<h4 id="tip-testing-and-documenting"><span class="glyphicon glyphicon-pushpin"></span>Tip: Testing and documenting</h4>
</div>
<div class="panel-body">
<p>It’s important to both test functions and document them: Documentation helps you, and others, understand what the purpose of your function is, and how to use it, and its important to make sure that your function actually does what you think.</p>
<p>When you first start out, your workflow will probably look a lot like this:</p>
<ol style="list-style-type: decimal">
<li>Write a function</li>
<li>Comment parts of the function to document its behaviour</li>
<li>Load in the source file</li>
<li>Experiment with it in the console to make sure it behaves as you expect</li>
<li>Make any necessary bug fixes</li>
<li>Rinse and repeat.</li>
</ol>
<p>Formal documentation for functions, written in separate <code>.Rd</code> files, gets turned into the documentation you see in help files. The <a href="http://cran.r-project.org/web/packages/roxygen2/vignettes/rd.html">roxygen2</a> package allows R coders to write documentation alongside the function code and then process it into the appropriate <code>.Rd</code> files. You will want to switch to this more formal method of writing documentation when you start writing more complicated R projects.</p>
<p>Formal automated tests can be written using the <a href="http://r-pkgs.had.co.nz/tests.html">testthat</a> package.</p>
</div>
</aside>
<!---
## Challenge solutions
> #### Solution to challenge 1 {.challenge}
>
> Write a function called `kelvin_to_celsius` that takes a temperature in Kelvin
> and returns that temperature in Celsius
>
>
> ~~~{.r}
> kelvin_to_celsius <- function(temp) {
> celsius <- temp - 273.15
> return(celsius)
> }
> ~~~
> #### Solution to challenge 2 {.challenge}
>
> Define the function to convert directly from Fahrenheit to Celsius,
> by reusing these two functions above
>
>
>
> ~~~{.r}
> fahr_to_celsius <- function(temp) {
> temp_k <- fahr_to_kelvin(temp)
> result <- kelvin_to_celsius(temp_k)
> return(result)
> }
> ~~~
>
> #### Solution to challenge 3 {.challenge}
>
>
> Write a function called `fence` that takes two vectors as arguments, called
> `text` and `wrapper`, and prints out the text wrapped with the `wrapper`:
>
>
> ~~~{.r}
> fence <- function(text, wrapper){
> text <- c(wrapper, text, wrapper)
> result <- paste(text, collapse = " ")
> return(result)
> }
> best_practice <- c("Write", "programs", "for", "people", "not", "computers")
> fence(text=best_practice, wrapper="***")
> ~~~
>
>
>
> ~~~{.output}
> [1] "*** Write programs for people not computers ***"
>
> ~~~
>
-->
</div>
</div>
</article>
<div class="footer">
<a class="label swc-blue-bg" href="http://software-carpentry.org">Software Carpentry</a>
<a class="label swc-blue-bg" href="https://github.com/swcarpentry/lesson-template">Source</a>
<a class="label swc-blue-bg" href="mailto:admin@software-carpentry.org">Contact</a>
<a class="label swc-blue-bg" href="LICENSE.html">License</a>
</div>
</div>
<!-- Javascript placed at the end of the document so the pages load faster -->
<script src="http://software-carpentry.org/v5/js/jquery-1.9.1.min.js"></script>
<script src="css/bootstrap/bootstrap-js/bootstrap.js"></script>
</body>
</html>