J'ai un bloc de données avec 4 colonnes (dont une partie est illustrée ci-dessous).
La première colonne montre les groupes classés par nombres: 1, 2, ....
Je veux générer une nouvelle colonne "valeur4". Pour chaque groupe, si la taille du groupe est supérieure à 2 (> = 3) et que toutes les valeurs de la colonne «valeur1» sont supérieures à 2 (> 2) ou inférieures à -2 (
g value1 value2 value3 value4 1 1.1 8 1 8 # for group "1", all the values in "value1" are <2, so the values from column "value2" are taken 1 1.2 8 1 8 1 1.3 9 1 9 2 3 10 5 5 # for group "2", all the values in "value1" are >2, median of numbers 5,5,4,6 from column "value3" is calculated 2 4 11 5 5 2 5 0 4 5 2 6 1 6 5 3 -3 2 5 5 # for group "3", all the values in "value1" are < -2, median of numbers 5,10,0 from column "value3" is calculated 3 -4 3 10 5 3 -5 4 0 5 4 -3 1 0 1 # group size less than 3, so the values from column "value2" are taken 4 -4 1 0 1
Le résultat sera:
g value1 value2 value3 1 1.1 8 1 1 1.2 8 1 1 1.3 9 1 2 3 10 5 2 4 11 5 2 5 0 4 2 6 1 6 3 -3 2 5 3 -4 3 10 3 -5 4 0 4 -3 1 0 4 -4 1 0
Je pense que je peux utiliser aggregate (), mais je ne sais pas comment intégrer les conditions. J'apprécie votre temps et votre aide.
3 Réponses :
En fonction de la condition, nous pouvons utiliser une condition if / else en utilisant la taille du groupe ( n () ) et if all value1 moins supérieur à -2 ou supérieur à 2, puis obtenir la médiane de "valeur3" ou autre renvoyer "valeur2"
df1 <- structure(list(g = c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L), value1 = c(1.1, 1.2, 1.3, 3, 4, 5, 6, -3, -4, -5, -3, -4), value2 = c(8L, 8L, 9L, 10L, 11L, 0L, 1L, 2L, 3L, 4L, 1L, 1L), value3 = c(1L, 1L, 1L, 5L, 5L, 4L, 6L, 5L, 10L, 0L, 0L, 0L)), class = "data.frame", row.names = c(NA, -12L))
library(dplyr)
df1 %>%
group_by(g) %>%
mutate(value4 = if(n() > 2 & (all(value1 > 2)| all(value1 < -2))) median(value3)
else value2)
# A tibble: 12 x 5
# Groups: g [4]
# g value1 value2 value3 value4
# <int> <dbl> <int> <int> <dbl>
# 1 1 1.1 8 1 8
# 2 1 1.2 8 1 8
# 3 1 1.3 9 1 9
# 4 2 3 10 5 5
# 5 2 4 11 5 5
# 6 2 5 0 4 5
# 7 2 6 1 6 5
# 8 3 -3 2 5 5
# 9 3 -4 3 10 5
#10 3 -5 4 0 5
#11 4 -3 1 0 1
#12 4 -4 1 0 1
Je ne pense pas que ce soit correct. g (et g1 ) semblent être des ID de groupe dans l'exemple mais vous l'évaluez comme une valeur.
@MokeEire Je pense que vous avez raison. Je mettrai à jour. Je pensais que c'était une valeur au lieu de n ()
Vous pouvez utiliser le package data.table comme suit:
library(data.table) setDT(df)[, value4 := if(.N > 2 & (all(value1 > 2) | all(value1 < -2))) median(value3) else value2, g]
C'est une situation idéale pour case_when () . *
Vous souhaite que la valeur4 soit calculée en fonction de la condition suivante:
Si la taille du groupe> 2 et la valeur absolue de toute valeur1 code> dans un groupe> 2 => prendre la médiane de valeur3 . Sinon utilisez value2
library(dplyr)
df %>%
group_by(g) %>%
mutate(value4 = case_when( (n() > 2) & (all(abs(value1) > 2)) ~ median(value3),
T ~ value2)
* On pourrait penser que nous pourrions utiliser if_else () ici car il n'y a qu'une seule condition mais pour une raison quelconque, il échouait lors de l'utilisation de all () dans la condition. Je pense qu'il renvoyait plusieurs valeurs? Pas clair, mais peut-être que quelqu'un d'autre pourrait expliquer.