1
votes

sous-ensemble data.frame pour chaque niveau d'un facteur

Étant donné les vecteurs suivants pour construire un dataframe:

level A  y >30 | y <20
level B  y >21 | y <12
level C  y >42 | y <21
level D  y >58 | y <13

Je voudrais avoir si possible, un code propre avec une boucle ou apply ou toute autre méthode pour sous-définir le data.frame par différentes conditions pour chaque niveau de facteur x . Par exemple:

set.seed(1)
x <- sample( LETTERS[1:4], 100, replace=TRUE)
y <- runif(100,0,100)
df <- data.frame(x,y)

r

4 commentaires

Voulez-vous dire | (OR) au lieu de & (AND) par hasard?


Ouais. désolé je voulais dire |


Cela peut être implémenté comme une combinaison de cut () , pour changer y en catégoriel, puis un split-apply-combine en utilisant dplyr / tidyr ou data.table.


La nuance ici est que certains niveaux ont deux bacs non contigus, et l'ordre dans lequel vous classez les choses fait une différence.


3 Réponses :


0
votes

Et quelque chose comme ça

df[df$x == 'A' & (df$y > 30 | df$y < 20),]
#    x         y
# 2  A 71.117606
# 3  A 44.438057
# 6  A 63.244699
# 7  A 54.185802
# 11 A 39.577617
# 13 A  8.681545
# 29 A 94.437431
# ...
# or depending on what you mean by '&'
df[df$x == 'A' & df$y > 30,]
#    x        y
# 2  A 71.11761
# 3  A 44.43806
# 6  A 63.24470
# 7  A 54.18580
# 11 A 39.57762
# 29 A 94.43743
# 31 A 54.17604
# ...

# and then accordingly for the other cases


0 commentaires

1
votes

Une approche de combinaison d'application fractionnée où nous utilisons Map pour parcourir les sous-ensembles et les conditions en parallèle.

do.call(rbind,
        Map(function(data, left, right) {
          subset(x = data, subset = y > left | y < right) 
          },
          data = split(df, df$x),
          left = c(30, 21, 42, 58),
          right = c(20, 12, 21, 13)
        ))
#      x         y
#A.5   A 63.349326
#A.10  A 59.876097
#A.11  A 97.617069
#A.12  A 73.179251
#A.22  A 49.559358
#A.24  A 17.344233
# ...

Nous divisons vos données par x , sous-ensemble chacun en fonction de vos conditions et combinons la liste en une seule trame de données.


1 commentaires

C'est sympa ! merci pour le partage, j'apprendrai beaucoup de ce code



0
votes

en utilisant bibliothèque (data.table) nous pouvons faire

lower = c(20, 12, 21, 13)
upper = c(30, 21, 42, 58)
setDT(df)[!between(y, lower[x], upper[x]), .SD, keyby=x]

#    x         y
# 1: A 63.349326
# 2: A 59.876097
# 3: A 97.617069
# 4: A 73.179251
# 5: A 49.559358
# 6: A 17.344233
# 7: A 51.116978
# ...


0 commentaires