Saltar al contenido

Sumar valores en R según el valor de la columna con dplyr

Siéntete en la libertad de divulgar nuestro sitio y códigos en tus redes, necesitamos de tu ayuda para hacer crecer nuestra comunidad.

Solución:

No soy un fan/experto en tidyverse, pero intentaría esto usando un formato largo. Luego, simplemente filtre por índice de fila por grupo y luego ejecute las funciones que desee en una sola columna (mucho más fácil de esta manera).

library(tidyr)
library(dplyr)

Data %>% 
  gather(variable, value, -Subject, -UniqueNumber) %>% # long format
  group_by(Subject) %>% # group by Subject in order to get row counts
  filter(row_number() <= UniqueNumber) %>% # filter by row index
  summarise(Mean = mean(value), Total = sum(value)) %>% # do the calculations
  ungroup() 

## A tibble: 3 x 3
#  Subject  Mean Total
#       
# 1       1 0.667     2
# 2       2 0.5       1
# 3       3 1         1

Una forma muy similar de lograr esto podría ser filtrar por los números enteros en los nombres de las columnas. El paso del filtro viene antes del group_by por lo que potencialmente podría aumentar el rendimiento (¿o no?) pero es menos robusto ya que asumo que las columnas de interés se llaman "Value#"

Data %>% 
  gather(variable, value, -Subject, -UniqueNumber) %>% #long format
  filter(as.numeric(gsub("Value", "", variable, fixed = TRUE)) <= UniqueNumber) %>% #filter
  group_by(Subject) %>% # group by Subject
  summarise(Mean = mean(value), Total = sum(value)) %>% # do the calculations
  ungroup()

## A tibble: 3 x 3
#  Subject  Mean Total
#       
# 1       1 0.667     2
# 2       2 0.5       1
# 3       3 1         1

Solo por diversión, agregando una solución data.table

library(data.table)

data.table(Data) %>% 
  melt(id = c("Subject", "UniqueNumber")) %>%
  .[as.numeric(gsub("Value", "", variable, fixed = TRUE)) <= UniqueNumber,
    .(Mean = round(mean(value), 3), Total = sum(value)),
    by = Subject]

#    Subject  Mean Total
# 1:       1 0.667     2
# 2:       2 0.500     1
# 3:       3 1.000     1

Aquí hay otro método que usa tidyr::nest para recoger el Values columnas en una lista para que podamos iterar a través de la tabla con map2. En cada fila, seleccionamos los valores correctos de la Values list-col y toma la suma o la media respectivamente.

library(tidyverse)
tbl <- read_table2(
"Subject    Value1    Value2    Value3      UniqueNumber
001        1         0         1           3
002        0         1         1           2
003        1         1         1           1"
)
tbl %>%
  filter(UniqueNumber > 0) %>%
  nest(starts_with("Value"), .key = "Values") %>%
  mutate(
    sum = map2_dbl(UniqueNumber, Values, ~ sum(.y[1:.x], na.rm = TRUE)),
    mean = map2_dbl(UniqueNumber, Values, ~ mean(as.numeric(.y[1:.x], na.rm = TRUE))),
  )
#> # A tibble: 3 x 5
#>   Subject UniqueNumber Values             sum  mean
#>                          
#> 1 001                3      2 0.667
#> 2 002                2      1 0.5  
#> 3 003                1      1 1

Creado el 2019-02-14 por el paquete reprex (v0.2.1)

Compruebe esta solución:

df %>%
  gather(key, val, Value1:Value3) %>%
  group_by(Subject) %>%
  mutate(
    Sum = sum(val[c(1:(UniqueNumber[1]))]),
    Mean = mean(val[c(1:(UniqueNumber[1]))]),
  ) %>%
  spread(key, val)

Producción:

 Subject UniqueNumber   Sum  Mean Value1 Value2 Value3
                    
1 001                3     2 0.667      1      0      1
2 002                2     1 0.5        0      1      1
3 003                1     1 1          1      1      1

Te mostramos las reseñas y valoraciones de los usuarios

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *