Почему объекты R не печатаются в функции или в цикле for? - PullRequest
52 голосов
/ 17 января 2011

У меня есть матрица R с именем ddd.Когда я вхожу в это, все работает нормально:

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

Звонки Шапиро Уилку, Андерсону Дарлингу, и все работают, и извлекают тот же столбец.

Если я вставлю этот код вцикл «for», вызовы Шапиро Уилку и Андерсону Дарлингу перестают работать, в то время как вызовы стебля и листа и вызов печати продолжают работать.

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 & 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 ]

55 голосов
/ 17 января 2011

В цикле автоматическая печать отключена, так как она находится внутри функции. Вам нужно явно 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

Скажем, теперь я хотел извлечь данные W и p-value, мы можем обработать объект, хранящий все результаты, чтобы извлечь нужные нам биты, например ::1010 *

> 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

Это должно быть лучше, чем запускать вывод на экран, через который вы затем должны пролить?

37 голосов
/ 17 января 2011

Не новый ответ, но в дополнение к вышесказанному: «flush.console ()» необходим для принудительной печати во время цикла, а не после. Единственная причина, по которой я использую print () во время цикла, состоит в том, чтобы показать прогресс, например, в чтении многих файлов.

for (i in 1:10) {
  print(i)
  flush.console()
  for(j in 1:100000)
    k <- 0
}
5 голосов
/ 06 декабря 2011

Фантастический ответ от Гэвина Симпсона.Я взял последнюю магию и превратил ее в функцию.

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

...