为什么R对象不能在函数或“for”循环中打印?

时间:2011-01-17 17:49:31

标签: r for-loop printing r-faq

我有一个名为ddd的R矩阵。当我输入此内容时,一切正常:

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

对Shapiro Wilk,Anderson Darling的调用,以及所有工作,并提取相同的列。

如果我把这段代码放在“for”循环中,那么对Shapiro Wilk和Anderson Darling的调用将停止工作,而词干&amp;叶子呼叫和打印呼叫继续工作。

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

如果我尝试写一个函数,也会发生同样的事情。 SW&amp; AD不起作用。其他的电话呢。

> 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

为什么所有的通话都不一样?

3 个答案:

答案 0 :(得分:55)

在循环中,自动打印关闭,因为它在函数内部。如果要查看输出,则需要在两种情况下明确print。您获得的[1] 9项内容是因为您明确打印了y

的值

以下是您可能想要考虑如何执行此操作的示例。

> 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

所以我们有自动打印。在循环中,我们必须这样做:

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

如果你想打印更多的测试,那么只需将它们作为额外的行添加到循环中:

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]))
}

但是,除非你喜欢阅读大量的输出,否则这不是很吸引人。相反,为什么不保存拟合的测试对象然后你可以打印它们并调查它们,甚至可以处理它们以将测试统计和p值聚合到表中?你可以使用循环来做到这一点:

## 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])
}

然后我们可以使用

查看模型
> obj[[1]]

    Shapiro-Wilk normality test

data:  DF[, y] 
W = 0.9891, p-value = 0.5895

例如,或者使用lapply,它负责设置我们用来存储结果的对象:

> obj2 <- lapply(DF, shapiro.test)
> obj2[[1]]

    Shapiro-Wilk normality test

data:  X[[1L]] 
W = 0.9891, p-value = 0.5895

现在说我想提取Wp-value数据,我们可以处理存储所有结果的对象以提取我们想要的位,例如:

> 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

对那些喜欢重要明星的人来说:

> 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

这比将屏幕输出发送到屏幕更好,然后才能通过?

答案 1 :(得分:37)

不是新答案,但除了上述内容之外:“flush.console()”是强制打印在循环期间而不是之后进行的必要条件。我在循环期间使用print()的唯一原因是显示进度,例如读取许多文件。

for (i in 1:10) {
  print(i)
  flush.console()
  for(j in 1:100000)
    k <- 0
}

答案 2 :(得分:5)

Gavin Simpson的精彩回答。我拿了最后一点魔法并把它变成了一个函数。

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)
}

然后你可以用你的数据框来调用它     sw.df(df)

如果你想尝试转型:     sw.df(log(df))