J'ai un dataframe, et pour chaque ligne de ce dataframe, je dois faire des recherches compliquées et ajouter des données à un fichier.
Le dataFrame contient des résultats scientifiques pour des puits sélectionnés à partir de plaques de 96 puits utilisées dans la recherche biologique, je veux donc faire quelque chose comme:
for (well in dataFrame) {
wellName <- well$name # string like "H1"
plateName <- well$plate # string like "plate67"
wellID <- getWellID(wellName, plateName)
cat(paste(wellID, well$value1, well$value2, sep=","), file=outputFile)
}
Dans mon monde procédural, je ferais quelque chose comme:
for (row in dataFrame) {
#look up stuff using data from the row
#write stuff to the file
}
Quelle est la "manière R" de faire cela?
Réponses:
Vous pouvez essayer ceci, en utilisant la
apply()
fonctionla source
x
) est un vecteur. C'est pourquoi l'exemple ci-dessus doit utiliser des index numériques; l'approche by () vous donne un data.frame, ce qui rend votre code plus robuste.wellName <- x[1]
pourrait aussi êtrewellName <- x["name"]
.Vous pouvez utiliser la
by()
fonction:Mais itérer directement sur les lignes comme ceci est rarement ce que vous voulez; vous devriez essayer de vectoriser à la place. Puis-je demander ce que fait le travail réel de la boucle?
la source
1:0
n'est pas videseq_len(nrow(dataFrame))
à la place de1:nrow(dataFrame)
.dostuff
cette réponse enstr(row)
Vous verrez plusieurs lignes imprimées dans la console commençant par "'data.frame': 1 obs de x variables." Mais attention, changerdostuff
enrow
ne renvoie pas un objet data.frame pour la fonction externe dans son ensemble. Au lieu de cela, il renvoie une liste de blocs de données d'une ligne.Premièrement, l'argument de Jonathan concernant la vectorisation est correct. Si votre fonction getWellID () est vectorisée, vous pouvez ignorer la boucle et utiliser simplement cat ou write.csv:
Si getWellID () n'est pas vectorisé, la recommandation de Jonathan d'utiliser
by
ou la suggestion de knguyen deapply
devrait fonctionner.Sinon, si vous voulez vraiment utiliser
for
, vous pouvez faire quelque chose comme ceci:Vous pouvez également essayer d'utiliser le
foreach
package, bien qu'il vous oblige à vous familiariser avec cette syntaxe. Voici un exemple simple:Une dernière option consiste à utiliser une fonction hors du
plyr
package, auquel cas la convention sera très similaire à la fonction apply.la source
mapply(getWellId, well$name, well$plate)
.foreach
- Je vais utiliser l'enfer de celui-là.Je pense que la meilleure façon de faire cela avec le R de base est:
L'avantage par rapport à l'
for( i in 1:nrow(df))
approche-est que vous n'avez pas de problème sidf
est vide etnrow(df)=0
.la source
J'utilise cette fonction utilitaire simple:
Ou une forme plus rapide et moins claire:
Cette fonction divise simplement un data.frame en une liste de lignes. Ensuite, vous pouvez faire un "pour" normal sur cette liste:
Votre code de la question fonctionnera avec une modification minimale:
la source
lapply
itère sur les colonnes de l'ensemble de données entierx
, en donnant le nom à chaque colonnec
, puis en extrayant lai
e entrée de ce vecteur de colonne. Est-ce correct?wellName <- as.character(well$name)
.J'étais curieux de connaître les performances temporelles des options non vectorisées. Pour cela, j'ai utilisé la fonction f définie par knguyen
et un dataframe comme celui de son exemple:
J'ai inclus deux fonctions vectorisées (bien sûr plus rapides que les autres) afin de comparer l'approche cat () avec une approche write.table () ...
L'image résultante montre que apply donne les meilleures performances pour une version non vectorisée, alors que write.table () semble surpasser cat ().
la source
Vous pouvez utiliser la
by_row
fonction du packagepurrrlyr
pour cela:Par défaut, la valeur renvoyée par
myfn
est placée dans une nouvelle colonne de liste dans le df appelé.out
.Si c'est la seule sortie que vous désirez, vous pouvez écrire
purrrlyr::by_row(df, myfn)$.out
la source
Eh bien, puisque vous avez demandé un R équivalent à d'autres langues, j'ai essayé de le faire. Cela semble fonctionner même si je n'ai pas vraiment regardé quelle technique est la plus efficace dans R.
Pour les colonnes catégoriques cependant, cela vous chercherait un Data Frame que vous pourriez taper en utilisant as.character () si nécessaire.
la source