web-dev-qa-db-fra.com

Comment rendre un objet créé dans une fonction utilisable à l'extérieur

J'ai créé une fonction qui produit une matrice à la suite, mais je ne peux pas comprendre comment rendre la sortie de cette fonction utilisable en dehors de l'environnement de fonction, afin que je puisse par exemple l'enregistrer dans un fichier csv.

Mon code de fonction est le suivant:

fonction créée qui prend les URL d'un site spécifique et renvoie le titre de la page:

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

fonction créée qui prend le vecteur des URL et retourne la matrice n * 2 avec les URL et les titres des pages:

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

Après avoir exécuté ces fonctions sur un exemple de fichier d'ici http://goo.gl/D9lLZ que j'importe avec la fonction read.csv et le nom "mypages" j'obtiens la sortie suivante:

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"

C'est exactement ce dont j'ai besoin, mais j'aimerais pouvoir exporter cette sortie vers un fichier csv ou la réutiliser pour d'autres manipulations. Cependant, lorsque j'essaie d'imprimer (my.matrix), j'obtiens une erreur disant "Erreur: objet 'my.matrix' introuvable"

J'ai l'impression que c'est une lacune assez basique dans mes connaissances, mais je n'ai pas travaillé avec R depuis un moment et je n'ai pas pu résoudre cela.

Merci! Sergey

20
Sergey Samusev

C'est simple: utilisez <<- pour l'affectation à un global.

Mais là encore, l'affectation globale est mauvaise et non fonctionnelle. Vous préférez peut-être renvoyer une liste avec plusieurs résultats de votre fonction? En regardant votre code, il semble que votre deuxième fonction puisse confondre return et print. Assurez-vous de renvoyer la structure de données correcte.

27
Dirk Eddelbuettel

Un peu sur la programmation fonctionnelle. Tout d'abord, lorsque vous définissez votre fonction:

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

sachez que lorsque la fonction est appelée, elle n'atteindra jamais l'instruction print. Au lieu de cela, il sortira juste avant, avec return. Vous pouvez donc supprimer cette instruction print, elle est inutile.

Maintenant, les choses les plus importantes. Dans votre fonction, vous définissez et renvoyez my.matrix. L'objet existe uniquement dans le cadre de la fonction: à la sortie de la fonction, ce qui est retourné est un objet sans nom (et my.matrix Est perdu.)

Dans votre session, lorsque vous appelez

getTitles(mypages)

le résultat est imprimé car vous ne l'avez pas affecté. Au lieu de cela, vous devez faire:

out.matrix <- getTitles(mypages)

Maintenant, le résultat ne sera pas imprimé, mais vous pouvez certainement le faire en tapant print(out.matrix) ou simplement out.matrix Sur une seule ligne. Et parce que vous avez stocké le résultat dans un objet, vous pouvez maintenant le réutiliser pour d'autres manipulations.

Si cela vous aide à saisir le concept, cela revient à appeler la fonction c() depuis la ligne de commande:

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

Bonus: Vraiment, je ne pense pas que vous ayez besoin de définir getTitles, mais vous pouvez utiliser l'une des fonctions *apply. J'essaierais ceci:

url    <- as.character(mypages)
title  <- sapply(url, getTitle)
report <- data.frame(url, title)
write.csv(report, file = "report.csv", row.names = FALSE)
17
flodel

Ne pouvez-vous pas simplement utiliser <<- pour lui assigner l'objet à l'espace de travail? Le code suivant fonctionne pour moi et enregistre le amort_value objet.

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

À la fin de la fonction, vous pouvez return le résultat.

Définissez d'abord la fonction:

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

Appelez-le ensuite et affectez la sortie à une variable:

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

À partir de là, utilisez scoreRange dans l'environnement. Toutes les variables ou fonctions imbriquées à l'intérieur votre fonction définie n'est pas accessible à l'extérieur, à moins bien sûr que vous n'utilisiez <<- pour affecter une variable globale. Donc, dans cet exemple, vous ne pouvez pas voir ce que numRange de l'extérieur à moins que vous ne le rendiez global.

Habituellement, essayez d'éviter les variables globales à un stade précoce. Les variables sont "encapsulées" afin que nous sachions laquelle est utilisée dans le contexte actuel ("environnement"). Les variables globales sont plus difficiles à apprivoiser.

6
Teng L