将函数的输出放入R中的数据框或列表或向量中

时间:2014-02-11 00:50:58

标签: r list dataframe data-manipulation

我试图测试欧拉素性测试的准确性。我写了一个函数euler(),它接受一个数字并测试所有数字的primality直到输入,并将它们输出到控制台,包括nonprimes。以下是它的外观:

euler(10)
[1] 1
[1] 2
[1] 3
[1] "Not prime:" "4"         
[1] 5
[1] "Not prime:" "6"         
[1] 7
[1] "Not prime:" "8"         
[1] "Not prime:" "9"         
[1] "Not prime:" "10"        
> 

我正在尝试将此输出放入数据框或因子或列表中。我试过了x<-euler(10),但它没有用。我只是得到一个NULL向量。这是我的euler函数的代码:

## Euler's primality test

euler <- function(k) {
  for(i in 1:k) {
    a  <- 2;
    if((a^i-a) %% i == 0) {
      print(i)
    } else{print(c("Not prime:",i))}
  }   
}

我尝试在“for”循环之外定义一个数据框,然后使用rbind(),但是当有if语句时我不知道该怎么做。任何帮助赞赏。如果我不清楚,请告诉我,我会进行必要的编辑。

3 个答案:

答案 0 :(得分:3)

建议函数返回一些内容而不是打印它。 (如果你想要的话,你可以在调用函数后自由打印输出。)

还建议函数的输出是一致的,例如不要在一个案例中返回一个数字,或者一个字符串&#34; Not prime&#34;在另一个。在这里,返回一个布尔值(对于素数是否为TRUE或FALSE)是最有意义的。

在可能的情况下,也建议(有益)矢量化函数。所以你可以使用像1:10之类的向量来调用函数,它会很快返回10个布尔值的向量。

考虑到所有这些因素,我将按如下方式定义函数:

is.euler.prime <- function(k) (2^k-2) %% k == 0

然后你可以做以下事情:

is.euler.prime(10)
is.euler.prime(1:10)
which(is.euler.prime(1:10))
data.frame(x = 1:10, euler.prime = is.euler.prime(1:10))

答案 1 :(得分:2)

euler <- function(k) {
  L <- c()
  for(i in 1:k) {
    a  <- 2;
    if((a^i-a) %% i == 0) {
      L <- c(L,i)
    } 
    else{
      L <- c(L,paste("Not prime:",i))
    }
  }
  return(L)
}

答案 2 :(得分:1)

考虑到您的功能的“正确性”,您可以使用capture.output捕获函数的打印输出。

在你的情况下:

data<-capture.output(euler(10))

这会给你:

 [1] "[1] 1"                             "[1] 2"                             "[1] 3"                             "[1] \"Not prime:\" \"4\"         "
 [5] "[1] 5"                             "[1] \"Not prime:\" \"6\"         " "[1] 7"                             "[1] \"Not prime:\" \"8\"         "
 [9] "[1] \"Not prime:\" \"9\"         " "[1] \"Not prime:\" \"10\"        "

如果你愿意,你可以用cat:

以漂亮的方式打印它
cat(data,sep="\n")

这会让你回到结果:

[1] 1
[1] 2
[1] 3
[1] "Not prime:" "4"         
[1] 5
[1] "Not prime:" "6"         
[1] 7
[1] "Not prime:" "8"         
[1] "Not prime:" "9"         
[1] "Not prime:" "10" 

如果您想在没有换行符和[1]的情况下保存结果,可以使用gsub来清理数据:

data<- gsub("\\[1\\]\\s|[[:punct:]]|\\s*$", "", capture.output(euler(10)))

这将为您提供一个带有“干净”字符串的向量,如下所示:

data
[1] "1"            "2"            "3"            "Not prime 4"  "5"            "Not prime 6"  "7"            "Not prime 8"  "Not prime 9"  "Not prime 10"

但我的回答是假设你想要学习如何捕获打印输出,而且这个euler函数是一个测试它的玩具函数。

如果这不是你的意图(现在我已经再次阅读你的评论,我认为不是这样),你应该重新考虑你的功能并仔细阅读@ flodel的回答。