Skip to content

Commit aec23fb

Browse files
committed
add defensive programming example as exercise
1 parent 05b930a commit aec23fb

File tree

3 files changed

+120
-34
lines changed

3 files changed

+120
-34
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
perl -pi -e 's/^## (--.+)?//' $@
1111

1212
all:
13-
make 01-intro.md 02-funprog.md 03-debug.md 04-perf.md
13+
make 01-intro.md 02-funprog.md 03-debug.md 04-perf.md unittesting.md
1414
make 01-intro.R 02-funprog.R 03-debug.R 04-perf.R
1515

1616
.PHONY: all

unittesting.Rmd

+26
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,32 @@ test_file("./unittests/test_foo.R")
120120

121121
# Exercises
122122

123+
## Column means
124+
125+
## Problem
126+
127+
The `col_means` function computes the means of all numeric columns in
128+
a data frame (example from *Advanced R*, to illustrate defensive
129+
programming).
130+
131+
```{r}
132+
col_means <- function(df) {
133+
numeric <- sapply(df, is.numeric)
134+
numeric_cols <- df[, numeric]
135+
data.frame(lapply(numeric_cols, mean))
136+
}
137+
138+
## Expected
139+
col_means(mtcars)
140+
141+
## Bugs
142+
col_means(mtcars[, "mpg"])
143+
col_means(mtcars[, "mpg", drop=FALSE])
144+
col_means(mtcars[, 0])
145+
col_means(mtcars[0, ])
146+
col_means(as.list(mtcars))
147+
```
148+
123149
## Character matching
124150

125151
### Problem

unittesting.md

+93-33
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ isIn(x, LETTERS)
5757
```
5858

5959
```
60-
## [1] "K" "E" "G" "S" "V"
60+
## [1] "V" "Z" "E" "G" "W"
6161
```
6262
But
6363

@@ -68,7 +68,7 @@ isIn(c(x, "a"), LETTERS)
6868
```
6969

7070
```
71-
## [1] "K" "E" "G" "S" "V" NA
71+
## [1] "V" "Z" "E" "G" "W" NA
7272
```
7373

7474
### Solution
@@ -148,6 +148,80 @@ test_file("./unittests/test_foo.R")
148148

149149
# Exercises
150150

151+
## Column means
152+
153+
## Problem
154+
155+
The `col_means` function computes the means of all numeric columns in
156+
a data frame (example from *Advanced R*, to illustrate defensive
157+
programming).
158+
159+
160+
```r
161+
col_means <- function(df) {
162+
numeric <- sapply(df, is.numeric)
163+
numeric_cols <- df[, numeric]
164+
data.frame(lapply(numeric_cols, mean))
165+
}
166+
167+
## Expected
168+
col_means(mtcars)
169+
```
170+
171+
```
172+
## mpg cyl disp hp drat wt qsec vs
173+
## 1 20.09062 6.1875 230.7219 146.6875 3.596563 3.21725 17.84875 0.4375
174+
## am gear carb
175+
## 1 0.40625 3.6875 2.8125
176+
```
177+
178+
```r
179+
## Bugs
180+
col_means(mtcars[, "mpg"])
181+
```
182+
183+
```
184+
## Error in df[, numeric]: incorrect number of dimensions
185+
```
186+
187+
```r
188+
col_means(mtcars[, "mpg", drop=FALSE])
189+
```
190+
191+
```
192+
## X21 X21.1 X22.8 X21.4 X18.7 X18.1 X14.3 X24.4 X22.8.1 X19.2 X17.8 X16.4
193+
## 1 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4
194+
## X17.3 X15.2 X10.4 X10.4.1 X14.7 X32.4 X30.4 X33.9 X21.5 X15.5 X15.2.1
195+
## 1 17.3 15.2 10.4 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2
196+
## X13.3 X19.2.1 X27.3 X26 X30.4.1 X15.8 X19.7 X15 X21.4.1
197+
## 1 13.3 19.2 27.3 26 30.4 15.8 19.7 15 21.4
198+
```
199+
200+
```r
201+
col_means(mtcars[, 0])
202+
```
203+
204+
```
205+
## Error in .subset(x, j): invalid subscript type 'list'
206+
```
207+
208+
```r
209+
col_means(mtcars[0, ])
210+
```
211+
212+
```
213+
## mpg cyl disp hp drat wt qsec vs am gear carb
214+
## 1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
215+
```
216+
217+
```r
218+
col_means(as.list(mtcars))
219+
```
220+
221+
```
222+
## Error in df[, numeric]: incorrect number of dimensions
223+
```
224+
151225
## Character matching
152226

153227
### Problem
@@ -279,29 +353,29 @@ y <- rnorm(5)
279353
```
280354

281355
```
282-
## x y
283-
## [1,] 0.5365683 1.6602057690
284-
## [2,] -0.1665628 -0.2975653902
285-
## [3,] -0.7467376 1.8558080246
286-
## [4,] 0.7382947 -0.6899443868
287-
## [5,] -0.9602598 -0.0008467193
356+
## x y
357+
## [1,] -0.7302789 1.41529114
358+
## [2,] 1.5499547 -0.76196247
359+
## [3,] 0.2118003 1.11505334
360+
## [4,] -0.5818516 -1.41958661
361+
## [5,] 0.2510727 0.06363576
288362
```
289363

290364
```r
291365
(p <- m[1, ])
292366
```
293367

294368
```
295-
## x y
296-
## 0.5365683 1.6602058
369+
## x y
370+
## -0.7302789 1.4152911
297371
```
298372

299373
```r
300374
distances(p, m)
301375
```
302376

303377
```
304-
## [1] 0.000000 2.080207 1.298127 2.358792 2.235976
378+
## [1] 0.0000000 3.1527604 0.9887648 2.8387607 1.6703363
305379
```
306380

307381
```r
@@ -310,21 +384,21 @@ distances(p, m)
310384
```
311385

312386
```
313-
## x y
314-
## 1 0.5365683 1.6602057690
315-
## 2 -0.1665628 -0.2975653902
316-
## 3 -0.7467376 1.8558080246
317-
## 4 0.7382947 -0.6899443868
318-
## 5 -0.9602598 -0.0008467193
387+
## x y
388+
## 1 -0.7302789 1.41529114
389+
## 2 1.5499547 -0.76196247
390+
## 3 0.2118003 1.11505334
391+
## 4 -0.5818516 -1.41958661
392+
## 5 0.2510727 0.06363576
319393
```
320394

321395
```r
322396
(q <- dd[1, ])
323397
```
324398

325399
```
326-
## x y
327-
## 1 0.5365683 1.660206
400+
## x y
401+
## 1 -0.7302789 1.415291
328402
```
329403

330404
```r
@@ -464,20 +538,6 @@ data(package = "pRolocdata")
464538
- To test the validity of an object, use `validObject`
465539

466540

467-
```
468-
## Warning: replacing previous import by 'ggplot2::Position' when loading
469-
## 'MSnbase'
470-
```
471-
472-
```
473-
## Warning: replacing previous import by 'ggplot2::unit' when loading
474-
## 'MSnbase'
475-
```
476-
477-
```
478-
## Warning: replacing previous import by 'ggplot2::arrow' when loading
479-
## 'MSnbase'
480-
```
481541

482542

483543
```r

0 commit comments

Comments
 (0)