output from "for" loop - r

based on Roland's suggestion from Plot titles in R using sapply(), I have created the following loop to make boxplots out of every selected variable in my dataset.
all.box=function(x) {
for (i in seq_along(x)) {
boxplot(x[,i], main = names(x)[i])
}
}
It does the job nicely in that it provides the graphs. Could someone point out to me how to make the loop to return some output, say the $out from the boxplot to be able to see the number of outliers calculated by it?
Thanx a lot!

Using lapply here is better to avoid side-effect of the for:
all.box=function(x) {
res <- lapply(seq_along(x),function(i){
boxplot(x[,i], main = names(x)[i])$out
})
res
}
PS: you can continue to use for, but you will need either to append a list as a result within your loop or to allocate memory for the output object before calling boxplot. So I think it is simpler to use xxapply family function here.

If you want to return something from a for loop, it's very important to pre-allocate the return object if it's not a list. Otherwise for loops with many iterations will be slow. I suggest to read the R inferno and Circle 2 in particular.
all.box=function(x) {
result <- list()
for (i in seq_along(x)) {
result[[i]] <- boxplot(x[,i], main = names(x)[i])$out
}
result
}

Related

Encountering errors when writing a quicksort function in R using a partition function

I've been writing this quicksort function in R trying to incorporate a partition function I've created as well. However, I've been encountering bugs when comparing p and r. It keeps telling me my argument is of length 0, however, I thought I declared the p and r objects when I initially called the quicksort function.
partition <- function(input,p, r){
pivot = input[r]
while(p<r){
while(input[p]<pivot) {p<-p+1}
while(input[r]>pivot) {r<-r-1}
if(input[p]==input[r]) {p<-p+1}
else if (p<r){
tmp <- input[p]
input[p] = input[r]
input[r] = tmp
}
}
return(r)
}
quicksort<- function(input,p,r){
if(p<r){
j<- partition(input,p,r)
input <- quicksort(input,p,j-1)
input <- quicksort(input,j+1,r)
}
}
input <- c(500,700,800,100,300,200,900,400,1000,600)
print("Input:")
print(input)
quicksort(input,1,10)
print("Output:")
print(input)
The error in question is caused because input[p] is of length zero. Why? Because in this instance input is NULL. input isn't NULL for the first few goes, so what would make it NULL?
Your quicksort function is designed to take an input, change it (if p<r), and then output it. But, you've left out the output step. If p<r then this is taken care of implicitly by the last input <- ... line, but if not then the function doesn't do anything and just returns NULL.
The output from one call to quicksort is the input to the next, and so this NULL propagates and breaks the next call.
Recursive functions are beautiful but often frustrating to debug. I recommend liberally sprinkling print() statements around while you're still developing it so you can see what it's doing more easily.

Correcting unfinished function in R

I should correct unfinished function Rfun() but I haven't managed to find all of the problems.
Rfun(N){
A=matrix(0,nrow=50,ncol=300)
t=c(0:30,0:-30)
for(j in 1:50)
x=N[j,]
y=cumsum(x)
for(i in 1:300){
A[j,i]=y[i]/3
}
}
return(A)
}
Well since you didn't precise what the function should do, let me help you with what is apparently false to me:
This is not how you define a function in R you need to write Rfun = function(N){}.
The return(A) should be inside the function. Therefore you should remove one parenthesis.
the variable t is not used at all.

How to call a result from a function in another one in R

can please somebody tell me how I can call my output which are two matrices as an input into another function?
X1=function(y,z)
{
output1=y*z
output2=y/z
}
X2=function(p,q)
{
input=X1(y,z)
input1=input$output1 ??? How to specify the output that I can call it this way? output1 and output2 are matrices!
input2=input$output2
equation=input1+input2
}
I tried return() and data.frame but both didn't work. Any tipps?
You can't use c as some might otherwise expect because you'll lose the structure of the matrices. Instead, use list when you want to return multiple objects from an R function.
X1 <- function(y,z)
{
list(
output1=y*z,
output2=y/z
)
}

R number of times an expression evaluates in a for loop

How many times the list.files('dir_path') evaluates in a for loop? Is it equal to the number of files present in a directory? How do we verify it?
for (infile in list.files('dir_path')){
#doSomething()
}
Should I have to create a variable first and then pass it in for loop?
For example:
selected_files = list.files('dir_path')
for (infile in selected_files){
#doSomething()
}
Thanks
list.files will only be evaluated once when you use it in a for-loop like the one you propose. The easiest way to test this is to wrap the call to list.files in another function call, like this:
f <- function() { print("Calling f"); list.files() }
and use that in the for-loop:
for (infile in f())
{
print(infile)
}

QQline command works only on the last plot

The formula below applies lm to a list 'dsets' that contains multiple datasets and stores the output in object 'models'.
models<-lapply(dsets,function(data){
lm(reformulate(termlabels=".",response=names(data)[1]),data)
})
I created this function to plot qqplot for each of the model outputs stored in object 'models' but it won't work
rstest<-function(x){
for (i in 1:length(x))
qqnorm(residuals(x[[i]]))
qqline(residuals(x[[i]]))
}
rstest(models)
I get the plots, but qqline works only on the last plot not all of the plots being generated. What am I missing in my function thats not making qqline iterate?
Only the first expression after for(...) is looped. Wrap the body of the for loop in {} to combine the two expressions.
rstest <- function(x) {
for (i in seq_along(x)) {
qqnorm(residuals(x[[i]]))
qqline(residuals(x[[i]]))
}
}
rstest(models)
Using an editor/IDE that indents your code would have helped you to recognize this yourself.

Resources