Why aren't R objects printed in a function or in a for loop?

I have an R matrix called ddd. When I get into this, everything works fine:

i <- 1 shapiro.test(ddd[,y]) ad.test(ddd[,y]) stem(ddd[,y]) print(y) 

Calls to Shapiro Wilk, Anderson Darling, and they all work, and retrieve the same column.

If I put this code in the "for" loop, the calls to Shapiro Wilk and Anderson Darling will stop working, while the call to stem and leaves and the call to print continue to work.

 for (y in 7:10) { shapiro.test(ddd[,y]) ad.test(ddd[,y]) stem(ddd[,y]) print(y) } The decimal point is 1 digit(s) to the right of the | 0 | 0 0 | 899999 1 | 0 [1] 7 

The same thing happens if I try to write a function. SW and AD do not work. Other calls.

 > D <- function (y) { + shapiro.test(ddd[,y]) + ad.test(ddd[,y]) + stem(ddd[,y]) + print(y) } > D(9) The decimal point is at the | 9 | 000 9 | 10 | 00000 [1] 9 

Why don't all calls behave the same?

+44
for-loop r r-faq printing
Jan 17 2018-11-17T00:
source share
3 answers

In a cycle, automatic printing is turned off because it is inside a function. You need to explicitly tell print something in both cases if you want to see the result. [1] 9 things you get are that you explicitly print y values.

Here is an example of how you might think about it.

 > DF <- data.frame(A = rnorm(100), B = rlnorm(100)) > y <- 1 > shapiro.test(DF[,y]) Shapiro-Wilk normality test data: DF[, y] W = 0.9891, p-value = 0.5895 

So, we have automatic printing. In a loop, we would have to do this:

 for(y in 1:2) { print(shapiro.test(DF[,y])) } 

If you want to print more tests, just add them to additional lines in the loop:

 for(y in 1:2) { writeLines(paste("Shapiro Wilks Test for column", y)) print(shapiro.test(DF[,y])) writeLines(paste("Anderson Darling Test for column", y)) print(ad.test(DF[,y])) } 

But this is not very attractive if you do not like to read the cross-cutting findings. Instead, why not save the installed test objects, and then you can print them and examine them, maybe even process them to aggregate the test statistics and p values ​​into a table? You can do this with a loop:

 ## object of save fitted objects in obj <- vector(mode = "list", length = 2) ## loop for(y in seq_along(obj)) { obj[[y]] <- shapiro.test(DF[,y]) } 

Then we can look at the models using

 > obj[[1]] Shapiro-Wilk normality test data: DF[, y] W = 0.9891, p-value = 0.5895 

for example, or using lapply , which takes care of setting up the object that we use to store the results for us:

 > obj2 <- lapply(DF, shapiro.test) > obj2[[1]] Shapiro-Wilk normality test data: X[[1L]] W = 0.9891, p-value = 0.5895 

Say, now I wanted to extract the W and p-value data, we can process an object that stores all the results to extract the desired bits, for example:

 > tab <- t(sapply(obj2, function(x) c(x$statistic, x$p.value))) > colnames(tab) <- c("W", "p.value") > tab W p.value A 0.9890621 5.894563e-01 B 0.4589731 1.754559e-17 

Or for those who have a penchant for stars of significance:

 > tab2 <- lapply(obj2, function(x) c(W = unname(x$statistic), + `p.value` = x$p.value)) > tab2 <- data.frame(do.call(rbind, tab2)) > printCoefmat(tab2, has.Pvalue = TRUE) W p.value A 0.9891 0.5895 B 0.4590 <2e-16 *** --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 

Should it be better than running the screen output you need to shed?

+47
Jan 17 '11 at 18:15
source share

Not a new answer, but in addition to the above: "flush.console ()" is needed to force printing during a loop, not after. The only reason I use print () during a loop is to show progress, such as reading many files.

 for (i in 1:10) { print(i) flush.console() for(j in 1:100000) k <- 0 } 
+32
Jan 17 '11 at 20:18
source share

Fantastic response from Gavin Simpson. I took the last bit of magic and turned it into a function.

 sw.df <- function ( data ) { obj <- lapply(data, shapiro.test) tab <- lapply(obj, function(x) c(W = unname(x$statistic), `p.value` = x$p.value)) tab <- data.frame(do.call(rbind, tab)) printCoefmat(tab, has.Pvalue = TRUE) } 

Then you can simply call it using the data frame sw.df (df)

And if you want to try the conversion: sw.df (log (df))

+4
Dec 06 '11 at 16:38
source share



All Articles