Mi pregunta implica sumar valores en múltiples columnas de un marco de datos y crear una nueva columna correspondiente a esta suma usando dplyr
. Las entradas de datos en las columnas son binarias (0,1). Estoy pensando en un análogo de fila de la función summarise_each
o mutate_each
de dplyr
. A continuación se muestra un ejemplo mínimo del marco de datos:
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
Podría usar algo como:
df <- df %>% mutate(sumrow= x1 + x2 + x3 + x4 + x5)
pero esto implicaría escribir los nombres de cada una de las columnas. Tengo como 50 columnas. Además, los nombres de las columnas cambian en diferentes iteraciones del ciclo en el que quiero implementar esta operación, así que me gustaría intentar evitar tener que dar nombres de columna.
¿Cómo puedo hacer eso de la manera más eficiente? Cualquier ayuda será muy apreciada.
dplyr
? ¿Por qué no simplemente un simpledf$sumrow <- rowSums(df, na.rm = TRUE)
de base R? Odf$sumrow <- Reduce(`+`, df)
si quieres replicar exactamente lo que hicistedplyr
.dplyr
también como endf %>% mutate(sumrow = Reduce(`+`, .))
odf %>% mutate(sumrow = rowSums(.))
dplyr
versión y funcionará.Respuestas:
Qué tal si
suma cada columna
df %>% replace(is.na(.), 0) %>% summarise_all(funs(sum))
resumir cada fila
df %>% replace(is.na(.), 0) %>% mutate(sum = rowSums(.[1:5]))
fuente
summarise_each
suma a lo largo de cada columna, mientras que lo que se requiere es la suma a lo largo de cada fila(.[1:5])
parte, pero desafortunadamente no estoy familiarizado con la sintaxis ni sé cómo buscar ayuda al respecto. Lo intentémutate(sum = rowSums(is.numeric(.)))
pero no funcionó.df %>% replace(is.na(.), 0) %>% select_if(is.numeric) %>% summarise_each(funs(sum))
intentarlo?summarise_all
lugar desummarise_each
ya que ha quedado obsoleto.mutate(sum = rowSums(.[,-1]))
puede resultar útil si no sabe con cuántas columnas debe tratar.Si desea sumar solo ciertas columnas, usaría algo como esto:
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 esta forma puede utilizar
dplyr::select
la sintaxis de.fuente
Usaría la coincidencia de expresiones regulares para sumar variables con ciertos nombres de patrones. Por ejemplo:
df <- df %>% mutate(sum1 = rowSums(.[grep("x[3-5]", names(.))], na.rm = TRUE), sum_all = rowSums(.[grep("x", names(.))], na.rm = TRUE))
De esta manera, puede crear más de una variable como una suma de cierto grupo de variables de su marco de datos.
fuente
-
cartel:rowSums(.[-grep("x[3-5]", names(.))], na.rm = TRUE)
Me encuentro con este problema a menudo y la forma más sencilla de hacerlo es utilizar la
apply()
función dentro de unmutate
comando.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))
Aquí puede usar lo que quiera para seleccionar las columnas usando los
dplyr
trucos estándar (por ejemplo,starts_with()
ocontains()
). Al hacer todo el trabajo con un solomutate
comando, esta acción puede ocurrir en cualquier lugar dentro de undplyr
flujo de pasos de procesamiento. Finalmente, al usar laapply()
función, tiene la flexibilidad de usar cualquier resumen que necesite, incluida su propia función de resumen diseñada específicamente.Alternativamente, si la idea de usar una función no tidyverse no es atractiva, entonces puede reunir las columnas, resumirlas y finalmente unir el resultado al marco de datos original.
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, . )
Aquí usé la
starts_with()
función para seleccionar las columnas y calculé la suma y puedes hacer lo que quieras con losNA
valores. La desventaja de este enfoque es que, si bien es bastante flexible, realmente no encaja en undplyr
flujo de pasos de limpieza de datos.fuente
apply
cuando esto es para lo querowSums
fue diseñado.rowSums
funciona muy bien como lo hacerowMeans
, pero siempre me sentí un poco extraño al preguntarme "¿Qué pasa si lo que necesito calcular no es una suma o una media?" Sin embargo, el 99% de las veces tengo que hacer algo como esto, es una suma o una media, por lo que tal vezapply
no se justifique un poco de flexibilidad adicional para usar la función general .Usar
reduce()
frompurrr
es un poco más rápidorowSums
y definitivamente más rápido queapply
, ya que evita iterar sobre todas las filas y simplemente aprovecha las operaciones vectorizadas:library(purrr) library(dplyr) iris %>% mutate(Petal = reduce(select(., starts_with("Petal")), `+`))
Vea esto para los tiempos
fuente
na.rm = TRUE
rowSums(select(., matches("myregex")) , na.rm = TRUE))
porque eso es lo que necesitaba en términos de ignorar las NA. Entonces, si los números son,sum(NA, 5)
el resultado es 5. Pero usted dijo que reducir es mejor querowSums
eso. Me preguntaba si hay una manera de usarlo en esta situación.rowSums
versión es probablemente la mejor. La principal desventaja es que solorowSums
yrowMeans
están disponibles (es un poco más lento que reducir, pero no mucho). Si necesita realizar otra operación (no la suma),reduce
probablemente la versión sea la única opción. Simplemente evite usarapply
en este caso.En las versiones más recientes
dplyr
, puede usarrowwise()
junto conc_across
para realizar agregaciones por filas para funciones que no tienen variantes específicas por filas, pero si existe la variante por filas, debería ser más rápido.Dado que
rowwise()
es solo una forma especial de agrupación y cambia la forma en que funcionan los verbos, es probable que desee canalizarlosungroup()
después de realizar la operación de filas.Para seleccionar un rango de filas:
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()
Para seleccionar filas por tipo:
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()
En su caso específico, existe una variante por filas para que pueda hacer lo siguiente (tenga en cuenta el uso de en su
across
lugar):df %>% dplyr::mutate(sumrow = rowSums(dplyr::across(x1:x5), na.rm = T)) # %>% dplyr::ungroup() # you'll likely want to ungroup after using rowwise()
Para obtener más información, consulte la página sobre filas .
fuente