34 votes

Pratique de codage en R: quels sont les avantages et inconvénients de différents styles?

Les dernières questions concernant l'utilisation d'exiger versus :: soulevé la question de savoir qui styles de programmation sont utilisés lors de la programmation en R, et quels sont leurs avantages et inconvénients. La navigation à travers le code source ou de la navigation sur le net, vous voyez beaucoup de styles différents affiche.

Les principales tendances dans mon code :

  • Je joue beaucoup avec les indices (et imbriqués les indices), ce qui entraîne plutôt obscur code parfois, mais est généralement beaucoup plus rapide que les autres solutions. par exemple: x[x < 5] <- 0 au lieu de x <- ifelse(x < 5, x, 0)

  • J'ai tendance à imbriquer des fonctions pour éviter de surcharger la mémoire temporaire des objets que j'ai besoin de nettoyer. Surtout avec les fonctions de manipulation d'ensembles de données volumineux, cela peut être un véritable fardeau. par exemple : y <- cbind(x,as.numeric(factor(x))) au lieu de y <- as.numeric(factor(x)) ; z <- cbind(x,y)

  • J'écris beaucoup de fonctions personnalisées, même si j'utilise le code qu'une seule fois dans eg. un sapply. Je crois qu'il le garde plus readible sans créer des objets qui peuvent rester traîner.

  • - Je éviter les boucles à tout prix, que je considère comme de la vectorisation à être beaucoup plus propre (et plus rapide)

Pourtant, j'ai remarqué que les opinions diffèrent, et certaines personnes ont tendance à s'éloigner de ce qu'ils appellent mon "Perl" mode de programmation (ou même "Lisp", avec toutes ces parenthèses qui volent autour dans mon code. Je n'irais pas si loin tout de même).

Que considérez-vous les bonnes pratiques de codage en R?

Quel est votre style de programmation, et comment voyez-vous ses avantages et ses inconvénients?

21voto

Gavin Simpson Points 72349

Ce que je ne dépendra pourquoi je suis en train d'écrire le code. Si je suis en train d'écrire une analyse des données de script pour mes travaux de recherche (travail de jour), je veux quelque chose qui fonctionne, mais c'est lisible et compréhensible, des mois ou même des années plus tard. Je ne m'inquiète pas trop de temps de calcul. La vectorisation avec lapply et coll. peut conduire à la dissimulation, que je voudrais éviter.

Dans de tels cas, je voudrais utiliser les boucles pour un processus répétitif si lapply m'a fait sauter à travers des cerceaux pour construire l'appropriées en fonction anonyme par exemple. Je voudrais utiliser l' ifelse() lors de votre première balle parce que, à mon avis, au moins, l' intention de cet appel est plus facile à comprendre que le sous-ensemble+remplacement de la version. Avec mon analyse de données, je suis plus préoccupé par obtenir les choses que nécessairement avec le temps de calcul. - - - il y a toujours les week-ends et les soirs où je ne suis pas dans le bureau quand je peux exécuter de gros travaux.

Pour vos autres balles; j'aurais tendance à ne pas incorporer/nid d'appels, sauf s'ils ont été très trivial. Si je sort les étapes explicitement, je trouve le code plus facile à lire et donc moins susceptibles de contenir des bugs.

J'écris des fonctions personnalisées tout le temps, surtout si je vais appeler le code équivalent de la fonction plusieurs fois dans une boucle ou similaire. De cette façon, j'en viens à la code de la principale analyse de données de script dans sa propre .R le fichier qui permet de garder l'intention de l'analyse séparée de la façon dont l'analyse est effectuée. Et si la fonction est utile je l'ai pour l'utiliser dans d'autres projets, etc.

Si je suis en train d'écrire le code pour un paquet, je pourrais commencer avec la même attitude que mon analyse de données (la connaissance) pour obtenir quelque chose que je sais œuvres, et seulement ensuite pour l'optimisation si je veux améliorer calculer les temps.

La seule chose que j'essaie d'éviter de le faire, c'est d'être trop intelligent quand je code, tout ce que je suis codant pour. En fin de compte, je ne suis jamais aussi intelligent que je pense, je suis à la fois et si j'ai garder les choses simples, j'ai tendance à ne pas tomber sur mon visage aussi souvent que je pourrais si je devais essayer d'être intelligent.

11voto

Roman Luštrik Points 19295

J'écris des fonctions (dans la version autonome d' .R fichiers) pour les différents morceaux de code que sur le plan conceptuel faire une chose. Cela permet de maintenir les choses à court et doux. J'ai trouvé le débogage est un peu plus facile, parce qu' traceback() vous donne la fonction qui produit une erreur.

J'ai trop tendance à éviter les boucles, sauf quand il est absolument nécessaire. Je me sens un peu sale si j'utilise un for() boucle. :) J'essaie vraiment difficile de tout faire en vectorisé ou à l'appliquer de la famille. Ce n'est pas toujours la meilleure solution, surtout si vous avez besoin d'expliquer le code à une autre personne qui n'est pas aussi à l'aise en applique ou à la vectorisation.

Concernant l'utilisation de l' require vs ::, j'ai tendance à utiliser les deux. Si j'ai seulement besoin d'une fonction à partir d'un certain paquet-je l'utiliser via ::, mais si j'ai besoin de plusieurs fonctions, je charge l'ensemble du paquet. Si il y a un conflit dans les noms de fonction entre les paquets, j'essaie de me souvenir et de l'utilisation ::.

J'essaie de trouver une fonction pour chaque tâche que je suis en train de réaliser. Je crois que quelqu'un avant moi a pensé et fait une fonction qui fonctionne mieux que tout ce que je peux trouver. Parfois, cela fonctionne, parfois pas tellement.

J'essaie d'écrire mon code pour que je puisse la comprendre. Cela signifie que je commente beaucoup et construire des morceaux de code, de sorte qu'ils en quelque sorte l'idée de ce que je suis en train de réaliser. J'ai souvent remplacer des objets comme la fonction progresse. Je pense que cela tient à la transparence de la tâche, surtout si vous faites référence à ces objets plus tard en la fonction. Je pense que sur la vitesse lors de temps de calcul dépasse de ma patience. Si une fonction prend autant de temps pour finir que j'ai commencer à naviguer de la SORTE, je vois si je peux l'améliorer.

J'ai découvert que la bonne syntaxe de l'éditeur de code de pliage et de coloration de la syntaxe (j'utilise Eclipse + StatET) m'a permis d'économiser beaucoup de maux de tête.

Basé sur VitoshKa post, j'ajoute que j'utilise capitalizedWords (sensu Java) pour les noms de fonction et de point.délimité pour les variables. Je vois que je pourrais avoir un autre style pour les arguments de la fonction.

8voto

VitoshKa Points 4689

Les conventions de nommage sont extrêmement important pour la lisibilité du code. Inspiré par R du S4 style interne, voici ce que j'utilise:

  • camelCase pour les fonctions globales et les objets (comme doSomething, getXyyy, upperLimit)
  • les fonctions commencent par un verbe
  • pas exportés et des fonctions d'assistance toujours commencer par un "."
  • les variables locales et fonctions sont toutes en lettres minuscules et en "_" la syntaxe (faire_quelque_chose, get_xyyy), Il permet de distinguer facilement le local vs global et, par conséquent, conduit à un produit de nettoyage de code.

4voto

Matt Bannert Points 6390

Pour les données de jonglerie j'essaie d'utiliser autant de SQL que possible, au moins pour les choses de base comme GROUPE PAR des moyennes. J'aime R beaucoup, mais parfois, il n'est pas seulement amusant à réaliser que votre stratégie de recherche n'était pas assez bon pour trouver encore une autre fonction cachée dans encore un autre paquet. Pour mon cas dialectes SQL ne diffèrent pas beaucoup, et le code est vraiment transparent. La plupart du temps, le seuil (quand commencer à utiliser R syntaxe) est plutôt intuitif à découvrir. par exemple

require(RMySQL)
# selection of variables alongside conditions in SQL is really transparent
# even if conditional variables are not part of the selection
statement = "SELECT id,v1,v2,v3,v4,v5 FROM mytable
             WHERE this=5
             AND that != 6" 
mydf <- dbGetQuery(con,statement)
# some simple things get really tricky (at least in MySQL), but simple in R
# standard deviation of table rows
dframe$rowsd <- sd(t(dframe))

Donc, je considère qu'il est de bonne pratique et vous recommande vraiment d'utiliser une base de données SQL pour vos données pour la plupart des cas d'utilisation. Je suis également à la recherche dans TSdbi et de gain de temps des séries en base de données relationnelle, mais ne peut pas vraiment juger encore.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X