24

我创建了一个生成矩阵的函数,但我不知道如何使该函数的输出在函数环境之外可用,以便例如将其保存在 csv 文件中。

我的函数代码如下:

创建的函数从特定站点获取 url 并返回页面标题:

getTitle <- function(url) {
  webpage <- readLines(url)
  first.row <- webpage[1]
  start <- regexpr("<title>", first.row)
  end <- regexpr("</title>", first.row)
  title <- substr(first.row,start+7,end-1)
  return(title)
}

创建的函数采用 url 向量并返回 n*2 矩阵,其中包含 url 和页面标题:

getTitles <- function(pages) {
  my.matrix <- matrix(NA, ncol=2, nrow=nrow(pages))
  for (i in seq_along(1:nrow(pages))) {
    my.matrix[i,1] <- as.character(pages[i,])
    my.matrix[i,2] <- getTitle(as.character(pages[i,])) }
  return(my.matrix)
  print(my.matrix)}

在从这里http://goo.gl/D9lLZ我用 read.csv 函数导入并命名为“mypages”的示例文件上运行此函数后,我得到以下输出:

getTitles(mypages)
     [,1]                                               [,2]                                                
[1,] "http://support.google.com/adwords/answer/1704395" "Create your first ad campaign - AdWords Help"      
[2,] "http://support.google.com/adwords/answer/1704424" "How costs are calculated in AdWords - AdWords Help"
[3,] "http://support.google.com/adwords/answer/2375470" "Organizing your account for success - AdWords Help"

这正是我所需要的,但我希望能够将此输出导出到 csv 文件或重复使用以进行进一步的操作。但是,当我尝试打印(my.matrix)时,我收到一条错误消息“错误:找不到对象'my.matrix'”

我觉得这是我知识上的一个非常基本的差距,但是有一段时间没有使用 R 并且无法解决这个问题。

谢谢!谢尔盖

4

4 回答 4

31

这很简单:<<-用于分配给全局。

但话又说回来,全局分配是邪恶的,没有功能。也许您宁愿从您的函数返回一个包含多个结果的列表?查看您的代码,似乎您的第二个函数可能会混淆returnand print。确保返回正确的数据结构。

于 2013-04-14T00:21:16.080 回答
21

一点关于函数式编程的知识。首先,当你定义你的函数时:

getTitles <- function(pages) {
  [...]
  return(my.matrix)
  print(my.matrix)
}

知道当函数被调用时,它永远不会到达print语句。相反,它将在之前退出,带有return. 所以你可以删除那个print语句,它是没用的。

现在更重要的东西。在您的函数内部,您定义并返回my.matrix. 该对象只存在于函数的范围内:函数退出时,返回的是一个未命名的对象(并且my.matrix丢失了。)

在你的会话中,当你打电话时

getTitles(mypages)

结果被打印,因为您没有分配它。相反,您应该这样做:

out.matrix <- getTitles(mypages)

现在将不会打印结果,但您绝对可以通过键入print(out.matrix)或仅out.matrix在一行上打印。并且因为您已将结果存储在一个对象中,您现在可以重用它以进行进一步的操作

如果它可以帮助您掌握概念,这c()与从命令行调用函数完全一样:

c(1, 5, 2)      # will return and print a vector 
x <- c(1, 5, 2) # will return and assign a vector (not printed.)

奖励:真的,我认为您不需要定义getTitles,但您可以使用其中一个*apply功能。我会试试这个:

url    <- as.character(mypages)
title  <- sapply(url, getTitle)
report <- data.frame(url, title)
write.csv(report, file = "report.csv", row.names = FALSE)
于 2013-04-14T00:28:37.593 回答
7

您不能只使用<<-将对象分配给工作区吗?以下代码适用于我并保存amort_value对象。

amortization <- function(cost, downpayment, interest, term) {
  amort_value <<- (cost)*(1-downpayment/100)*(interest/1200)*((1+interest/1200)^(term*12))/((1+interest/1200)^(term*12)-1)
  sprintf("$%.2f", amort_value)         

}
amortization(445000,20,3,15)
amort_value
于 2015-04-20T14:13:38.330 回答
6

在函数结束时,您可以return得到结果。

首先定义函数:

getRangeOf <- function (v) {
    numRange <- max(v) - min(v)
    return(numRange)
}

然后调用它并将输出分配给一个变量:

scores <- c(60, 65, 70, 92, 99)
scoreRange <- getRangeOf(scores)

从这里开始scoreRange在环境中使用。外部无法访问您定义的函数中的任何变量或嵌套函数,当然,除非您使用<<-分配全局变量。所以在这个例子中,你不能numRange从外部看到什么,除非你把它变成全局的。

通常,在早期尽量避免使用全局变量。变量是“封装的”,因此我们知道在当前上下文(“环境”)中使用了哪个变量。全局变量更难驯服。

于 2017-07-13T21:18:03.727 回答