Considérez un df comme celui-ci:
df <- data.frame(colA = 1:10, colB = 50:59, colC = 100:109, colD = letters[1:10])
Je veux transformer la variable "colA" puis calculer une somme en ligne de variables que je choisis par select () code > à l'intérieur de
mutate ()
. Je fais ceci:
df %>% mutate(colA = colA * 60) %>% mutate(sum = rowSums(select(., colA, colB, colC))) colA colB colC colD sum 1 60 50 100 a 210 2 120 51 101 b 272 3 180 52 102 c 334 4 240 53 103 d 396 5 300 54 104 e 458 6 360 55 105 f 520 7 420 56 106 g 582 8 480 57 107 h 644 9 540 58 108 i 706 10 600 59 109 j 768
qui me donne un résultat incorrect:
df %>% mutate(colA_mod = colA * 60, sum = rowSums(select(., colA_mod, colB, colC)))
Si je crée une toute nouvelle variable :
colA colB colC colD sum 1 60 50 100 a 151 2 120 51 101 b 154 3 180 52 102 c 157 4 240 53 103 d 160 5 300 54 104 e 163 6 360 55 105 f 166 7 420 56 106 g 169 8 480 57 107 h 172 9 540 58 108 i 175 10 600 59 109 j 178
J'obtiens:
Erreur: erreur d'évaluation: la position doit être comprise entre 0 et n.
Cependant, lorsque j'utilise deux mutate ()
s séparés, j'obtiens les bons résultats:
df %>% mutate(colA = colA * 60, sum = rowSums(select(., colA, colB, colC)))
Donc la question est, comment puis-je transformer une variable / créer une nouvelle variable et la sélectionner dans un mutate ()
?
Exemple de données :
colA colB colC colD 1 1 50 100 a 2 2 51 101 b 3 3 52 102 c 4 4 53 103 d 5 5 54 104 e 6 6 55 105 f 7 7 56 106 g 8 8 57 107 h 9 9 58 108 i 10 10 59 109 j
3 Réponses :
Une option consiste à ajouter colA
séparément
rowSums(select(., colA_mod, colB, colC))
Lorsque vous utilisez select (., colA, colB, colC)
, .
est la trame de données d'origine et les colonnes sélectionnées proviennent également de la trame de données d'origine. Par conséquent, il ne dispose pas d'informations sur les valeurs mises à jour de colA
. C'est la même raison pour laquelle vous obtenez l'erreur lors de votre deuxième tentative
library(dplyr) df %>% mutate(colA = colA * 60, sum = rowSums(select(., colB, colC)) + colA) # colA colB colC colD sum #1 60 50 100 a 210 #2 120 51 101 b 272 #3 180 52 102 c 334 #4 240 53 103 d 396 #5 300 54 104 e 458 #6 360 55 105 f 520 #7 420 56 106 g 582 #8 480 57 107 h 644 #9 540 58 108 i 706 #10 600 59 109 j 768
car la colonne colA_mod
ne fait pas partie du dataframe d'origine ( df
).
Possibilité très élégante! Cependant, je suis toujours curieux de savoir s'il existe un moyen de mettre à jour le df original référencé par .
dans select ()
.
Le fait de changer rowSums
et select
fera le travail:
colA colB colC colD sum 1 1 50 100 a 210 2 2 NA 101 b 221 3 3 52 102 c 334 4 4 53 103 d 396 5 5 54 104 e 458 6 6 55 105 f 520 7 7 56 106 g 582 8 8 57 107 h 644 9 9 58 108 i 706 10 10 59 109 j 768
Si vous avez des NA, mettez-les d'abord à zéro. se comporte comme et na.rm:
df %>% mutate(sum = rowSums(select(., colA:colC) * matrix(rep(c(60,1,1), times = 10), byrow = T, ncol = 3), na.rm = T))
Sinon, voici une solution qui autorise rowSums
et une mutation:
df %>% replace(is.na(.), 0) %>% mutate(colA = colA * 60, sum = colA + colB + colC)
Cela pourrait être une possibilité, cependant, dans mes données réelles, j'ai aussi des NA. Il est beaucoup plus pratique d'ajouter na.rm = TRUE
dans rowSums ()
.
@tmfmnk a trouvé une solution qui permet aux rowSums
Le .
est un espace réservé pour ce qui a été envoyé dans le tube. Dans ce cas, votre mutation de colA
ne met pas à jour ce qui est dans le pipeline dans l'appel mutate
.
Vous pouvez ajouter un autre tube:
df %>% mutate(colA = colA * 60)%>% mutate(sum = rowSums(select(., colA, colB, colC)))
Merci, cependant, j'ai également inclus cette possibilité dans ma question :) De plus, je veux vraiment le faire en un seul mutate ()
.
Oops. En gros, cependant, vous ne pouvez pas faire ce que vous voulez. Le .
ne sera pas mis à jour avant le prochain tube avant %>%
.