J'ai une donnée:
Source: local data frame [30 x 5] Groups: <by row> # A tibble: 30 x 5 x.1 x.2 x.3 x.4 var <dbl> <dbl> <dbl> <dbl> <dbl> 1 32.7 42.7 50.1 20.8 7091. 2 75.9 71.3 83.6 77.6 7091. 3 49.6 28.7 97.0 59.7 7091. 4 47.4 96.1 31.9 79.7 7091. 5 54.2 47.1 81.7 41.6 7091. 6 27.9 58.1 97.4 25.9 7091. 7 61.8 78.3 52.6 67.7 7091. 8 85.4 51.3 38.8 82.0 7091. 9 27.9 72.6 68.9 25.2 7091. 10 87.2 42.1 27.6 73.9 7091. # ... with 20 more rows
La fonction suivante fonctionne:
df_1 %>% select(-y) %>% rowwise() %>% mutate(var = sum(select_if(., is.numeric)))
Mais, les fonctions suivantes (pour toutes les variables) ne fonctionnent pas ne fonctionne pas:
avec .
:
df_1 %>% select(-y) %>% rowwise() %>% mutate(var = sum(.))
avec select_if
:
library(tidyverse) df_1 %>% select(-y) %>% rowwise() %>% mutate(var = sum(c(x.1, x.3)))
Les deux méthodes renvoient:
df_1 <- data.frame( x = replicate(4, runif(30, 20, 100)), y = sample(1:3, 30, replace = TRUE) )
Où 7091
est une somme incorrecte.
Comment l'ajustement fonctionne-t-il?
4 Réponses :
Je pense que c'est délicat parce que les variantes de portée de mutate ( mutate_at
, mutate_all
, mutate_if
) visent généralement à exécuter une fonction sur une colonne spécifique, au lieu de créer une opération qui utilise toutes les colonnes.
La solution la plus simple que je puisse trouver consiste essentiellement à créer un vecteur ( cols
) qui est ensuite utilisé pour exécuter l'opération récapitulative :
library(dplyr) library(purrr) df_1 <- data.frame( x = replicate(4, runif(30, 20, 100)), y = sample(1:3, 30, replace = TRUE) ) # create vector of columns to operate on cols <- names(df_1) cols <- cols[map_lgl(df_1, is.numeric)] cols <- cols[! cols %in% c("y")] cols #> [1] "x.1" "x.2" "x.3" "x.4" df_1 %>% select(-y) %>% rowwise() %>% mutate( var = sum(!!!map(cols, as.name), na.rm = TRUE) ) #> Source: local data frame [30 x 5] #> Groups: <by row> #> #> # A tibble: 30 x 5 #> x.1 x.2 x.3 x.4 var #> <dbl> <dbl> <dbl> <dbl> <dbl> #> 1 46.1 28.9 28.9 50.7 155. #> 2 26.8 68.0 67.1 26.5 188. #> 3 35.2 63.8 62.5 28.5 190. #> 4 31.3 44.9 67.3 68.2 212. #> 5 52.6 23.9 83.2 43.4 203. #> 6 55.7 92.8 86.3 57.2 292. #> 7 56.9 50.0 77.6 25.6 210. #> 8 95.0 82.6 86.1 22.7 286. #> 9 62.7 26.5 61.0 88.9 239. #> 10 65.2 23.1 25.5 51.0 165. #> # ⦠with 20 more rows
Créé le 30/04/2019 par package reprex (v0.2.1)
REMARQUE: si vous n'êtes pas familier avec purrr
, vous pouvez également utiliser quelque chose comme lapply code>, etc.
Vous pouvez en savoir plus sur ces types d'opérations dplyr
plus délicates ( !!
, !!! code>, etc.) ici:
https: //dplyr.tidyverse .org / articles / programmation.html
Quelques approches que j'ai adoptées dans le passé:
rowSums
) réduire
(qui ne s'applique pas à toutes les fonctions) pmap
my_var <- function(...){ vec <- c(...) var(vec) } df_1 %>% mutate(var = select(., -y) %>% pmap(my_var)) %>% head() #> x.1 x.2 x.3 x.4 y var #> 1 41.24069 58.56641 93.03007 39.17035 3 620.9523 #> 2 49.76991 67.96527 43.48827 24.71475 2 318.3722 #> 3 65.82827 59.48330 56.72526 71.38306 2 43.17011 #> 4 92.65662 34.89741 46.59157 90.10154 1 878.5009 #> 5 36.13455 86.18987 72.06964 82.31317 3 520.7224 #> 6 91.87117 73.47734 40.64134 83.78471 2 506.1679
df_1 %>% mutate(var = select(., -y) %>% as.matrix %>% t %>% as.data.frame %>% map_dbl(var)) %>% head() #> x.1 x.2 x.3 x.4 y var #> 1 41.24069 58.56641 93.03007 39.17035 3 620.95228 #> 2 49.76991 67.96527 43.48827 24.71475 2 318.37221 #> 3 65.82827 59.48330 56.72526 71.38306 2 43.17011 #> 4 92.65662 34.89741 46.59157 90.10154 1 878.50087 #> 5 36.13455 86.18987 72.06964 82.31317 3 520.72241 #> 6 91.87117 73.47734 40.64134 83.78471 2 506.16785
df_1 %>% mutate(var = reduce(select(., -y),`+`)) %>% head() #> x.1 x.2 x.3 x.4 y var #> 1 41.24069 58.56641 93.03007 39.17035 3 232.0075 #> 2 49.76991 67.96527 43.48827 24.71475 2 185.9382 #> 3 65.82827 59.48330 56.72526 71.38306 2 253.4199 #> 4 92.65662 34.89741 46.59157 90.10154 1 264.2471 #> 5 36.13455 86.18987 72.06964 82.31317 3 276.7072 #> 6 91.87117 73.47734 40.64134 83.78471 2 289.7746
pmap
set.seed(1) df_1 <- data.frame( x = replicate(4, runif(30, 20, 100)), y = sample(1:3, 30, replace = TRUE) ) library(tidyverse) # rowSums df_1 %>% mutate(var = rowSums(select(., -y))) %>% head() #> x.1 x.2 x.3 x.4 y var #> 1 41.24069 58.56641 93.03007 39.17035 3 232.0075 #> 2 49.76991 67.96527 43.48827 24.71475 2 185.9382 #> 3 65.82827 59.48330 56.72526 71.38306 2 253.4199 #> 4 92.65662 34.89741 46.59157 90.10154 1 264.2471 #> 5 36.13455 86.18987 72.06964 82.31317 3 276.7072 #> 6 91.87117 73.47734 40.64134 83.78471 2 289.7746
Créé le 2019-04-30 par le package reprex (v0.2.1)
Au lieu de +
, je peux mettre mean
, var
(répondre avec réduire
)? Comment puis-je faire ceci?
Je l'ai mis à jour avec var
, en utilisant une stratégie différente. Ce n'est pas particulièrement élégant (je suppose qu'il y a des fonctions personnalisées par ligne pour beaucoup de choses), mais cette approche fonctionnerait généralement tant que toutes les colonnes -y
sont du même type.
Cela peut être fait en utilisant purrr :: pmap
a >, qui passe une liste d'arguments à une fonction qui accepte les "points". Étant donné que la plupart des fonctions telles que mean
, sd
, etc. fonctionnent avec des vecteurs, vous devez associer l'appel avec un domain lifter :
df_1 %>% select(-y) %>% mutate( v1 = pmap(., lift_vd(mean)), v2 = pmap(., lift_vd(sd)), v3 = pmap(., sum) ) # x.1 x.2 x.3 x.4 v1 v2 v3 # 1 70.12072 62.99024 54.00672 86.81358 68.48282 13.88555 273.9313 # 2 49.40462 47.00752 21.99248 78.87789 49.32063 23.27958 197.2825
La fonction sum
accepte directement les points, donc vous ne t besoin de lever son domaine:
df_1 %>% select(-y) %>% mutate( var = pmap(., sum) ) # x.1 x.2 x.3 x.4 var # 1 70.12072 62.99024 54.00672 86.81358 273.9313 # 2 49.40462 47.00752 21.99248 78.87789 197.2825
Tout est conforme au traitement de données standard dplyr
, donc les trois peuvent être combinés comme arguments séparés pour muter
:
df_1 %>% select(-y) %>% mutate( var = pmap(., lift_vd(mean)) ) # x.1 x.2 x.3 x.4 var # 1 70.12072 62.99024 54.00672 86.81358 68.48282 # 2 49.40462 47.00752 21.99248 78.87789 49.32063 df_1 %>% select(-y) %>% mutate( var = pmap(., lift_vd(sd)) ) # x.1 x.2 x.3 x.4 var # 1 70.12072 62.99024 54.00672 86.81358 13.88555 # 2 49.40462 47.00752 21.99248 78.87789 23.27958
Merci. Mais, et pour plus que la fonction? Exemple, pour mean
, sd
et var
(3 nouvelles colonnes)? Voir: mutate (var = pmap (., Lift_vd (mean, sd, var)))
ne fonctionne pas.
@GiovaniNeves: Combinez simplement ceux à l'intérieur de mutate
comme vous le feriez normalement. Voir la modification ci-dessus.
Excellente solution! Merci, @Artem Sokolov!
C'est un problème délicat car dplyr opère par colonne pour de nombreuses opérations. J'ai utilisé à l'origine apply
à partir de la base R pour appliquer sur les lignes, mais apply
est problématique lors de la gestion des caractères et des types numériques .
Au lieu de cela, nous pouvons utiliser (le vieillissement) plyr strong> et adply
a > pour faire cela simplement, puisque plyr nous permet de traiter un bloc de données à une ligne comme un vecteur:
df_1 %>% select(-y) %>% adply(1, function(df) c(v1 = sd(df[1, ])))
Notez certaines fonctions comme var
won ' t travailler sur une trame de données à une ligne, nous devons donc convertir en vecteur en utilisant as.numeric
.
Vous pouvez utiliser
rowSums
:df_1%>% mutate (var = rowSums (select (., Starts_with ('x.'))))
@IceCreamToucan, j'ai besoin d'utiliser
rowwise
.cette répond à votre question?
Ça ne marche pas. J'ai besoin d'une somme pour chaque cas (ligne) pour toutes les variables.
Peut être fait en utilisant le package
purrr
:df_1%>% select (-y)%>% mutate (var = pmap (., Lift (sum)))
Et
signifie
ousd
?@GiovaniNeves: C'est la même chose pour
mean
etsd
. Utilisez simplement un autre lifter de domaine:df_1%>% select (-y)%>% mutate (var = pmap (., Lift_vd (mean)))