<- 5
myIterAtoR.max <-7
second_iterator.max= 10
col.NUM=10
row.cnt <- matrix(rep(1, col.NUM*row.cnt),nrow=row.cnt)
fwzy45 for(haystack in (2-1):col.NUM){
for(needle in 1:row.cnt) {
if(haystack>=myIterAtoR.max){
<-NA}
fwzy45[haystack, needle] }}
The objective of this lab is to improve your coding skills by focusing on coding style, code benchmarking and optimization. Below, you will find a number of tasks connected to the topics covered in the Best Coding Practices lecture. Some tasks extend lectures content and require you to find some more information online. Please, note that while we are providing example solutions to many tasks, these are only examples. If you solve a task in a different way it does not matter your solution is wrong. In fact, it may be better than our solution. If in doubt, ask PI for help. We are here for you!
1 Coding Style
1.1 Task: Valid Variable Names.
Which of the following are valid/good variable names in R. What is wrong with the ones that are invalid/bad?
var1
3way_handshake
.password
__test__
my-matrix-M
three.dimensional.array
3D.distance
.2objects
wz3gei92
next
P
Q
R
S
T
X
is.larger?
1.2 Task: Obscure Code.
The code below works, but can be improved. Do improve it!
<- 5
iter_max <- 10
col_num <- 10
row_num <- matrix(rep(1, col_num * row_num), nrow = row_num)
A for (i in 1:col_num) {
for (j in 1:row_num) {
if (i >= iter_max) {
<- NA
A[i, j]
}
}
}
# Can you improve the code more by eliminating loops or at least one of them?
1.3 Task: Better Formatting.
Improve formatting and style of the following code:
<- function( q, N=100 ) {
simulate_genotype if( length(q)==1 ){
<- (1 - q)
p <- c(p^2, 2*p*q, q^2) # AA, AB, BB
f_gt else{
}<-q
f_gt
}<- sample( c('AA','AB','BB'), size =N, prob=f_gt, replace=T )
tmp return(tmp)
}
<- function(q, N = 100) {
simulate_genotype if (length(q) == 1) {
<- (1 - q)
p <- c(p^2, (2 * p * q), q^2) # AA, AB, BB
f_gt else {
} <- q
f_gt
}sample(c('AA', 'AB', 'BB'),
size = N,
prob = f_gt,
replace = TRUE)
}
1.5 Task: Pipeline-friendly Function.
Modify the function below so that it works with R pipes %>%
:
<- function(threshold = 1, x, scalar = 5) {
my_filter >= threshold] <- NA
x[x <- x * scalar
x return(x)
}
You need to have the magrittr
or tidyverse
package loaded in order to be able to use the pipe %>%
!
<- function(x, threshold = 1, scalar = 5) {
my_filter >= threshold] <- NA
x[x * scalar
x
}
# Test:
c(-5, 5) %>% my_filter()
1.6 Task: Untidy Code?
Is the code below correct? Can it be improved?
<- function(pop_params, gp_map, gtype) {
simulate_phenotype <- pop_params[1]
pop_mean <- pop_params[2]
pop_var <- rnorm(n = N, mean = pop_mean, sd = sqrt(pop_var))
pheno <- rep(0, times = length(N))
effect for (gt_iter in c('AA', 'AB', 'BB')) {
== gt_iter] <- rnorm(n = sum(gtype == gt_iter),
effect[gtype mean = gp_map[gt_iter, 'mean_eff'],
sd = sqrt(gp_map[gt_iter, 'var_eff']))
}<- data.frame(gt = gtype, raw_pheno = pheno, effect = effect, pheno = pheno + effect)
dat return(dat)
}
in principle the code is clean! Except that... the N is not initialized anywhere. Maybe some small improvements can be done, but
2 Structuring the Code
2.1 Task: Computing Variance.
Write a modular code (function or functions) that computes the sample standard deviation given a vector of numbers. Decide how to logically structure the code. Assume there are no built-in R functions for computing mean and variance available. The formula for variance is: \(SD = \sqrt{\frac{\Sigma_{i=1}^{N}(x_i - \bar{x})^2}{N-1}}\). Standard deviation is \(Var=SD^2\).
Consider that you may want to re-use some computed values in future, e.g. variance.
<- function(x) {
sample_mean sum(x) / length(x)
}
<- function(x) {
sum_squared_deviations <- (x - sample_mean(x))^2
tmp sum(tmp)
}
<- function(x) {
std_dev sqrt(sum_squared_deviations(x) / (length(x) - 1))
}
<- function(x) {
variance std_dev(x)^2
}
2.2 Task: Writing a Wrapper Function.
You found two functions in two different packages: the randomSampleInt
function that generates a random sample of integer numbers and the randomSampleLetter
function for generating a random sample of letters. Unfortunately, the functions are called in different ways which you want to unify in order to use them interchangeably in your code. Write a wrapper function around the randomSampleLetter
that will provide the same interface to the function as the randomSampleInt
. Also, the randomSampleLetter
cannot handle the seed. Can you add this feature to your wrapper?
<- function(x, verbose, length, seed = 42) {
randomSampleInt if (verbose) {
print(paste0('Generating random sample of ', length, ' integers using seed ', seed))
}set.seed(seed)
<- sample(x = x, size = length, replace = TRUE)
sampleInt return(sampleInt)
}
<- function(N, silent=T, lett) {
randomSampleLetter if (!silent) {
print(paste0('Generating random sample of ', N, ' letters.'))
}<- sample(x = lett, size = N, replace = TRUE)
sample return(sample)
}
<- function(x, verbose, length, seed = 42) {
randomSampleLetterWrapper set.seed(seed)
randomSampleLetter(N = length, silent = !verbose, lett = x)
}
2.3 Task: Customizing plot
.
Write a wrapper around the graphics::plot
function that modifies its default behavior so that it plots red crosses instead of black points. Do it in a way that enables the user to modify other function arguments.
You may want to have a look at graphics::plot.default
.
<- function(x, ...) {
my_plot plot(x, pch = 3, col = 'red', ...)
}
2.4 Task: Adding Arguments to a Function.
What if you want to pass some additional parameters to a function and, sadly, the authors forgot to add ...
to the list of function arguments. There is a way out – you can bind extra arguments supplied as alist
structure to the original function arguments retrieved by formals
. Try to fix the function below, so that the call red_plot(1, 1, col = 'red', pch = 19)
will result in points being represented by red circles. Do use alist
and formals
and do not edit the red_plot
itself!
Read help for alist
and formals
.
Original function:
<- function(x, y) {
red_plot plot(x, y, las=1, cex.axis=.8, ...)
}
<- function(x, y) {
red_plot plot(x, y, las = 1, cex.axis = .8, ...)
}
red_plot(1, 1, col = 'red', pch = 19) # Does not work.
formals(red_plot) <- c(formals(red_plot), alist(... = )) # Fix.
red_plot(1, 1, col = 'red', pch = 19) # Works!
2.5 Task: Using options
.
Use options
to change the default prompt in R to hello :-) >
.
Check what options are stored in the hidden variable called Options.
options(prompt = "hello :-) > ")
.Optionsoptions(prompt = "> ") # restoring the default