Ma question consiste à additionner les valeurs sur plusieurs colonnes d'un bloc de données et à créer une nouvelle colonne correspondant à cette somme à l'aide de dplyr
. Les entrées de données dans les colonnes sont binaires (0,1). Je pense à un analogue en ligne de la fonction summarise_each
ou mutate_each
de dplyr
. Voici un exemple minimal de la trame de données:
library(dplyr)
df=data.frame(
x1=c(1,0,0,NA,0,1,1,NA,0,1),
x2=c(1,1,NA,1,1,0,NA,NA,0,1),
x3=c(0,1,0,1,1,0,NA,NA,0,1),
x4=c(1,0,NA,1,0,0,NA,0,0,1),
x5=c(1,1,NA,1,1,1,NA,1,0,1))
> df
x1 x2 x3 x4 x5
1 1 1 0 1 1
2 0 1 1 0 1
3 0 NA 0 NA NA
4 NA 1 1 1 1
5 0 1 1 0 1
6 1 0 0 0 1
7 1 NA NA NA NA
8 NA NA NA 0 1
9 0 0 0 0 0
10 1 1 1 1 1
Je pourrais utiliser quelque chose comme:
df <- df %>% mutate(sumrow= x1 + x2 + x3 + x4 + x5)
mais cela impliquerait d'écrire les noms de chacune des colonnes. J'ai environ 50 colonnes. De plus, les noms de colonnes changent à différentes itérations de la boucle dans laquelle je veux implémenter cette opération, je voudrais donc essayer d'éviter d'avoir à donner des noms de colonne.
Comment puis-je le faire le plus efficacement possible? Toute assistance sera grandement appréciée.
dplyr
? Pourquoi pas juste un simple àdf$sumrow <- rowSums(df, na.rm = TRUE)
partir de la base R? Oudf$sumrow <- Reduce(`+`, df)
si vous souhaitez reproduire exactement ce que vous avez faitdplyr
.dplyr
trop comme dansdf %>% mutate(sumrow = Reduce(`+`, .))
oudf %>% mutate(sumrow = rowSums(.))
dplyr
version et cela fonctionnera.Réponses:
Que diriez-vous
résumer chaque colonne
df %>% replace(is.na(.), 0) %>% summarise_all(funs(sum))
résumer chaque ligne
df %>% replace(is.na(.), 0) %>% mutate(sum = rowSums(.[1:5]))
la source
summarise_each
sommes vers le bas le long de chaque colonne tout ce qui est nécessaire est somme le long de chaque rangée(.[1:5])
partie, mais malheureusement, je ne suis pas familier avec la syntaxe et je ne sais pas comment chercher de l'aide. J'ai essayémutate(sum = rowSums(is.numeric(.)))
mais n'a pas fonctionné.df %>% replace(is.na(.), 0) %>% select_if(is.numeric) %>% summarise_each(funs(sum))
essayer?summarise_all
plutôtsummarise_each
que car il est obsolète.mutate(sum = rowSums(.[,-1]))
peut être utile si vous ne savez pas combien de colonnes vous devez traiter.Si vous souhaitez additionner uniquement certaines colonnes, j'utiliserais quelque chose comme ceci:
library(dplyr) df=data.frame( x1=c(1,0,0,NA,0,1,1,NA,0,1), x2=c(1,1,NA,1,1,0,NA,NA,0,1), x3=c(0,1,0,1,1,0,NA,NA,0,1), x4=c(1,0,NA,1,0,0,NA,0,0,1), x5=c(1,1,NA,1,1,1,NA,1,0,1)) df %>% select(x3:x5) %>% rowSums(na.rm=TRUE) -> df$x3x5.total head(df)
De cette façon, vous pouvez utiliser
dplyr::select
la syntaxe de.la source
J'utiliserais la correspondance d'expressions régulières pour additionner des variables avec certains noms de modèle. Par exemple:
df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE), sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE))
De cette façon, vous pouvez créer plusieurs variables en tant que somme de certains groupes de variables de votre bloc de données.
la source
-
signe:rowSums(.[-grep("x[3-5]", names(.))], na.rm = TRUE)
Je rencontre souvent ce problème et le moyen le plus simple de le faire est d'utiliser la
apply()
fonction dans unemutate
commande.library(tidyverse) df=data.frame( x1=c(1,0,0,NA,0,1,1,NA,0,1), x2=c(1,1,NA,1,1,0,NA,NA,0,1), x3=c(0,1,0,1,1,0,NA,NA,0,1), x4=c(1,0,NA,1,0,0,NA,0,0,1), x5=c(1,1,NA,1,1,1,NA,1,0,1)) df %>% mutate(sum = select(., x1:x5) %>% apply(1, sum, na.rm=TRUE))
Ici, vous pouvez utiliser ce que vous voulez pour sélectionner les colonnes en utilisant les
dplyr
astuces standard (par exemplestarts_with()
oucontains()
). En effectuant tout le travail dans une seulemutate
commande, cette action peut se produire n'importe où dans undplyr
flux d'étapes de traitement. Enfin, en utilisant laapply()
fonction, vous avez la possibilité d'utiliser le résumé dont vous avez besoin, y compris votre propre fonction de résumé spécialement conçue.Sinon, si l'idée d'utiliser une fonction non-tidyverse n'est pas attrayante, vous pouvez rassembler les colonnes, les résumer et enfin joindre le résultat à la trame de données d'origine.
df <- df %>% mutate( id = 1:n() ) # Need some ID column for this to work df <- df %>% group_by(id) %>% gather('Key', 'value', starts_with('x')) %>% summarise( Key.Sum = sum(value) ) %>% left_join( df, . )
Ici, j'ai utilisé la
starts_with()
fonction pour sélectionner les colonnes et calculé la somme et vous pouvez faire ce que vous voulez avec desNA
valeurs. L'inconvénient de cette approche est que, bien qu'elle soit assez flexible, elle ne s'intègre pas vraiment dans undplyr
flux d'étapes de nettoyage des données.la source
apply
Cela semble idiot à utiliser quand c'est cerowSums
pour quoi il a été conçu.rowSums
fonctionne très bienrowMeans
, mais je me suis toujours senti un peu étrange en me demandant "Et si ce que je dois calculer n'est pas une somme ou une moyenne?" Cependant, 99% du temps que je dois faire quelque chose comme ça, c'est soit une somme, soit une moyenne, alors peut-être que le peu de flexibilité supplémentaire dans l'utilisation de laapply
fonction générale n'est pas garanti.L'utilisation de
reduce()
frompurrr
est légèrement plus rapiderowSums
et certainement plus rapide queapply
, puisque vous évitez d'itérer sur toutes les lignes et profitez simplement des opérations vectorisées:library(purrr) library(dplyr) iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), `+`))
Voir ceci pour les horaires
la source
na.rm = TRUE
rowSums(select(., matches("myregex")) , na.rm = TRUE))
parce que c'est ce dont j'avais besoin pour ignorer les NA. Donc, si les chiffres sontsum(NA, 5)
les résultats est 5. Mais vous avez dit que réduire est mieux querowSums
donc je me demandais s'il y avait un moyen de l'utiliser dans cette situation?rowSums
version est probablement la meilleure. Le principal inconvénient est que seulsrowSums
etrowMeans
sont disponibles (il est légèrement plus lent que de réduire, mais pas de beaucoup). Si vous devez effectuer une autre opération (pas la somme), lareduce
version est probablement la seule option. Évitez simplement d'utiliserapply
dans ce cas.Dans les versions plus récentes de,
dplyr
vous pouvez utiliserrowwise()
avecc_across
pour effectuer une agrégation par ligne pour les fonctions qui n'ont pas de variantes spécifiques par ligne, mais si la variante par ligne existe, elle devrait être plus rapide.Puisqu'il
rowwise()
s'agit simplement d'une forme spéciale de regroupement et qu'il change la façon dont les verbes fonctionnent, vous voudrez probablement le dirigerungroup()
après avoir effectué votre opération par ligne.Pour sélectionner une plage de lignes:
df %>% dplyr::rowwise() %>% dplyr::mutate(sumrange = sum(dplyr::c_across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Pour sélectionner des lignes par type:
df %>% dplyr::rowwise() %>% dplyr::mutate(sumnumeric = sum(c_across(where(is.numeric)), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Dans votre cas spécifique, une variante par ligne existe, vous pouvez donc faire ce qui suit (notez l'utilisation de à la
across
place):df %>% dplyr::mutate(sumrow = rowSums(dplyr::across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Pour plus d'informations, consultez la page sur rowwise .
la source