1
votes

Moyennes de différentes longueurs en R

J'essaie de calculer les scores moyens des réponses à différents événements. Mes données sont au format long avec une ligne pour chaque événement, exemple de jeu de données data ici:

data$average <- data%>%filter(Event == "A") %>% with(data, (R1 + R2 + R3)/4) 

Donc, pour obtenir la moyenne de l'événement A, ce serait (R1 + R2 + R3) / 3 en ignorant le N / A, alors que l'événement B a 4 réponses. J'ai calculé la moyenne de l'événement A dans dplyr comme suit:

Subject  Event   R1  R2 R3 R4   Average
1        A       1   2  2  N/A   2.5
1        B       1   1  1  1     1

J'ai rencontré des problèmes lorsque j'ai essayé de faire de même pour le prochain événement. .Merci pour votre aide!


0 commentaires

4 Réponses :


2
votes

Vous n'avez pas besoin de filtrer pour chaque événement à la fois. dplyr est capable de traiter toutes les lignes à la fois, une par une. De plus, lorsque vous utilisez dplyr , vous n'avez pas besoin d'assigner à une variable en dehors de son contexte, comme data $ average . Vous pouvez utiliser mutate () . La syntaxe intuitive de dplyr serait donc:

data <-
  data %>%
  mutate(average = mean(c(R1, R2, R3, R4), na.rm = TRUE))


1 commentaires

Je pense que votre na.rm = TRUE doit vivre en dehors du vecteur.



3
votes

Ce qui suit n'inclut pas la valeur NA dans le cadre du calcul de la moyenne ( na.rm = TRUE ). De plus, je pense que le regroupement par événement est important. Lorsqu'ils sont exécutés sans group_by, les calculs combinent tous les événements et la valeur résultante est 1.285714 (= 9/7 obs).

Subject Event    R1    R2    R3    R4 Average
    <dbl> <fct> <dbl> <dbl> <dbl> <dbl>   <dbl>
1       1 A         1     2     2    NA    1.67
2       1 B         1     1     1     1    1   

Sortie:

data <- data.frame(
  Subject=c(1,1),
  Event=c('A', 'B'),
  R1=c(1,1),
  R2=c(2,1),
  R3=c(2,1),
  R4=c(NA,1)
)

df <- data %>%
  group_by(Event) %>%
  mutate(Average = mean(c(R1,R2,R3,R4), na.rm=TRUE))


0 commentaires

1
votes

Vous pouvez utiliser rowMeans pour calculer les moyennes pour chaque ligne d'un dataframe. Spécifiez dans l'entrée les colonnes que vous souhaitez inclure. Pour ignorer le NA , définissez na.rm=TRUE.

data$Average <- rowMeans(data[,grep("R",names(data))], na.rm=TRUE)

Si vous aviez beaucoup de colonnes à faire la moyenne et que vous ne vouliez pas saisissez-les tous, vous pouvez utiliser grep pour faire correspondre les noms des données à n'importe quel modèle. Disons par exemple que vous voulez faire la moyenne de toutes les lignes contenant un "R" dans leur nom:

data$Average <- rowMeans(data[,c("R1", "R2", "R3", "R4")], na.rm=TRUE)


0 commentaires

0
votes

Juste pour compléter toutes les réponses précédentes, si vous avez plusieurs valeurs nommées R1 , R2 , .... R100 , au lieu d'écrire tous dans la fonction mean , vous pourriez être intéressé en remodelant votre dataframe dans un format plus long en utilisant la fonction pivot_longer , puis en les groupant par événement et en calculant la moyenne. Enfin, en utilisant pivot_wider , vous pourriez obtenir votre dataframe dans le format initial plus large.

structure(list(Subject = c(1L, 1L), Event = c("A", "B"), R1 = c(1L, 
1L), R2 = 2:1, R3 = 2:1, R4 = c("N/A", "1"), Average = c(2.5, 
1)), row.names = c(NA, -2L), class = c("data.table", "data.frame"
), .internal.selfref = <pointer: 0x5555743c1310>)

Comme mentionné par @TTS, il y a quelque chose qui ne va pas dans votre calcul de la moyenne de l'événement A.

Exemple reproductible

library(dplyr)
library(tidyr)
df %>% mutate_at(vars(contains("R")), as.numeric) %>%
    pivot_longer(cols = starts_with("R"), names_to = "R", values_to = "Values") %>%
    group_by(Event) %>%
    mutate(average = mean(Values, na.rm = TRUE)) %>%
    pivot_wider(names_from = R, values_from = Values)

# A tibble: 2 x 8
# Groups:   Event [2]
  Subject Event Average average    R1    R2    R3    R4
    <int> <chr>   <dbl>   <dbl> <dbl> <dbl> <dbl> <dbl>
1       1 A         2.5    1.67     1     2     2    NA
2       1 B         1      1        1     1     1     1


0 commentaires