1
votes

R: générer une nouvelle colonne basée sur des groupes et des conditions

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.

r

0 commentaires

3 Réponses :


0
votes

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))

données h3>
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


2 commentaires

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 ()



0
votes

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]


0 commentaires

0
votes

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.


0 commentaires