Lorsque plyr
je travaille avec, j'ai souvent trouvé utile d'utiliser adply
pour les fonctions scalaires que je dois appliquer à chaque ligne.
par exemple
data(iris)
library(plyr)
head(
adply(iris, 1, transform , Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 5.1
2 4.9 3.0 1.4 0.2 setosa 4.9
3 4.7 3.2 1.3 0.2 setosa 4.7
4 4.6 3.1 1.5 0.2 setosa 4.6
5 5.0 3.6 1.4 0.2 setosa 5.0
6 5.4 3.9 1.7 0.4 setosa 5.4
Maintenant, j'utilise dplyr
plus, je me demande s'il existe un moyen ordonné / naturel de le faire? Comme ce n'est PAS ce que je veux:
library(dplyr)
head(
mutate(iris, Max.Len= max(Sepal.Length,Petal.Length))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Max.Len
1 5.1 3.5 1.4 0.2 setosa 7.9
2 4.9 3.0 1.4 0.2 setosa 7.9
3 4.7 3.2 1.3 0.2 setosa 7.9
4 4.6 3.1 1.5 0.2 setosa 7.9
5 5.0 3.6 1.4 0.2 setosa 7.9
6 5.4 3.9 1.7 0.4 setosa 7.9
mdply
in dplyr, et hadley a suggéré qu'ils pourraient préparer quelque chose basé surdo
. Je suppose que cela fonctionnerait également ici.rowwise()
qui regrouperait par chaque ligne individuelleadply
lorsque vous n'utilisez pas de regroupement? car sa fonction étroitement intégrée s'appellegroup_by
PASsplit_by
Réponses:
À partir de dplyr 0.2 (je pense)
rowwise()
est implémenté, la réponse à ce problème devient:Non
rowwise
alternativeCinq ans (!) Plus tard, cette réponse reçoit encore beaucoup de trafic. Depuis qu'il a été donné, il
rowwise
est de moins en moins recommandé, bien que beaucoup de gens semblent le trouver intuitif. Faites-vous une faveur et parcourez les flux de travail orientés Row de Jenny Bryan en R avec le matériel tidyverse pour bien comprendre ce sujet.Le moyen le plus simple que j'ai trouvé est basé sur l'un des exemples de Hadley utilisant
pmap
:En utilisant cette approche, vous pouvez donner un nombre arbitraire d'arguments à la fonction (
.f
) à l'intérieurpmap
.pmap
est une bonne approche conceptuelle car elle reflète le fait que lorsque vous effectuez des opérations par ligne, vous travaillez en fait avec des tuples à partir d'une liste de vecteurs (les colonnes d'un dataframe).la source
plyr
et desdplyr
packages, vous utilisez presque certainement le mauvais,mutate
sauf si vous fournissez explicitement la portéedplyr::mutate
.L'approche idiomatique sera de créer une fonction vectorisée de manière appropriée.
R
fournitpmax
ce qui convient ici, mais il fournit égalementVectorize
un wrapper pourmapply
vous permettre de créer une version arbitraire vectorisée d'une fonction arbitraire.Notez que l'implémentation de la vectorisation en C / C ++ sera plus rapide, mais il n'y a pas de
magicPony
package qui écrira la fonction pour vous.la source
dplyr
moyen ... car ce serait plus simple sans déplyr par exemplewith(df, Coalesce(a,b))
peut-être, c'est un genre de réponse cependant - ne pas utiliserdplyr
pour ça?magicPony
colis. DommageVous devez regrouper par ligne:
C'est ce que le
1
faitadply
.la source
dplyr
expert. J'espère que quelqu'un d'autre viendra avec quelque chose de mieux. Notez que je l'ai nettoyé un peu avec1:n()
.group_by(1:n())
comportement. Si personne n'a d'autres idées le matin, je coche les vôtres;)n
: "Cette fonction est implémentée spécialement pour chaque source de données et ne peut être utilisée qu'à partir de la synthèse.", Bien que cela semble fonctionner.Mise à jour 03/08/2017
Après avoir écrit ceci, Hadley a encore changé certaines choses. Les fonctions qui étaient auparavant dans purrr sont maintenant dans un nouveau package mixte appelé purrrlyr , décrit comme:
Vous devrez donc installer + charger ce package pour que le code ci-dessous fonctionne.
Message original
Hadley change fréquemment d'avis sur ce que nous devrions utiliser, mais je pense que nous sommes censés passer aux fonctions de purrr pour obtenir la fonctionnalité par ligne. Au moins, ils offrent les mêmes fonctionnalités et ont presque la même interface que
adply
de plyr .Il existe deux fonctions liées,
by_row
etinvoke_rows
. Je crois comprendre que vous utilisezby_row
lorsque vous souhaitez boucler sur des lignes et ajouter les résultats au data.frame.invoke_rows
est utilisé lorsque vous bouclez sur les lignes d'un data.frame et passez chaque col comme argument à une fonction. Nous n'utiliserons que le premier.Exemples
Cela nous permet de voir les éléments internes (afin que nous puissions voir ce que nous faisons), ce qui revient à le faire avec
adply
.Par défaut,
by_row
ajoute une colonne de liste basée sur la sortie:donne:
si à la place on retourne a
data.frame
, on obtient une liste avecdata.frame
s:donne:
La façon dont nous ajoutons la sortie de la fonction est contrôlée par le
.collate
paramètre. Il y a trois options: liste, lignes, cols. Lorsque notre sortie a la longueur 1, peu importe que nous utilisions des lignes ou des cols.les deux produisent:
Si nous sortons un data.frame avec 1 ligne, peu importe ce que nous utilisons:
les deux donnent:
sauf que le second a la colonne appelée
.row
et le premier pas.Enfin, si notre sortie est plus longue que la longueur 1 sous forme de a
vector
ou dedata.frame
avec des lignes, alors il importe que nous utilisions des lignes ou des cols pour.collate
:produit respectivement:
Donc, en bout de ligne. Si vous voulez la
adply(.margins = 1, ...)
fonctionnalité, vous pouvez utiliserby_row
.la source
by_row
est obsolète, l'appelant dit "utiliser une combinaison de: tidyr :: nest (); dplyr :: mutate (); purrr :: map ()" github.com/hadley/purrrlyr/blob/…Prolongeant la réponse de BrodieG,
Si la fonction renvoie plus d'une ligne, alors au lieu de
mutate()
,do()
doit être utilisée. Ensuite, pour le combiner à nouveau, utilisez-lerbind_all()
dans l'dplyr
emballage.Dans la
dplyr
versiondplyr_0.1.2
, utiliser1:n()
dans lagroup_by()
clause ne fonctionne pas pour moi. Espérons que Hadley serarowwise()
bientôt implémenté .Tester les performances,
il a les résultats suivants:
Cela montre que la nouvelle
purrr
version est la plus rapidela source
Quelque chose comme ça?
la source
dplyr
solution générale pour une fonction scalaire.wacky.function <- function(col.1, col.2){...}
, puisiris.wacky <- wacky.function(iris$Sepal.Length, iris$Petal.Length)
.dplyr
ouplyr
ou dites quedata.table
vous devriez essayer d'utiliser leurs expressions idiomatiques afin que votre code ne devienne pas un mélange de styles difficile à partager. D'où la question.plyr
documentation est "plyr est un ensemble d'outils qui résout un ensemble commun de problèmes: vous devez décomposer un gros problème en morceaux gérables, opérer sur chaque pièce et ensuite remonter toutes les pièces". Cela semble être un problème très différent pour lequel les opérations élémentaires sur les colonnes sont le meilleur outil. Cela pourrait aussi expliquer pourquoi il n'y a pas « naturel »plyr
/dplyr
commande pour ce faire.