4 votes

La méthode efficace de filtrage des données à basse fréquence dans un cadre de données en R

J'ai un data.frame avec plusieurs colonnes et je veux filtrer les données à basse fréquence en fonction de la combinaison des variables. Par exemple, j'ai la variable Sexe (Male/Female) et la variable Cholestérol (High/Low). Mon cadre de données serait alors le suivant :

set.seed(123)
Sex = sample(c('Male','Female'),size = 20,replace = TRUE)
Age = sample(c('Low','High'),size = 20,replace = TRUE)
Index = 1:20
df = data.frame(index = Index,Sex=Sex,Age=Age)
df

  index    Sex  Age
1      1   Male High
2      2 Female High
3      3   Male High
4      4 Female High
5      5 Female High
6      6   Male High
7      7 Female High
8      8 Female High
9      9 Female  Low
10    10   Male  Low
11    11 Female High
12    12   Male High
13    13 Female High
14    14 Female High
15    15   Male  Low
16    16 Female  Low
17    17   Male High
18    18   Male  Low
19    19   Male  Low
20    20 Female  Low

Je veux maintenant filtrer la combinaison Sexe/Age dont la fréquence est supérieure à 3.

table(df[,2:3])
        Age
Sex      High Low
  Female    8   3
  Male      5   4

En d'autres termes, je veux garder les indices pour femme-haute, homme-basse et homme-haute.

Avis que 1) mon cadre de données comporte plusieurs variables (pas comme dans l'exemple ci-dessus) et 2) que je fais ne pas vouloir d'utiliser un troisième paquet R et 3) je veux qu'il soit rapide.

7voto

beginneR Points 7179

Voici une approche simple en base R :

lvls <- interaction(df$Sex, df$Age)
counts <- table(lvls)
df[lvls %in% names(counts)[counts > 3], ]

#   index    Sex  Age
#1      1   Male High
#2      2 Female High
#3      3   Male High
#4      4 Female High
#5      5 Female High
#6      6   Male High
#7      7 Female High
#8      8 Female High
#10    10   Male  Low
#11    11 Female High
#12    12   Male High
#13    13 Female High
#14    14 Female High
#15    15   Male  Low
#17    17   Male High
#18    18   Male  Low
#19    19   Male  Low

Si vous avez un plus grand nombre de variables, vous pouvez les stocker dans un vecteur :

vars <- c("Age", "Sex") # add more
lvls <- interaction(df[, vars])
counts <- table(lvls)
df[lvls %in% names(counts)[counts > 3], ]

Et voici une deuxième approche R de base utilisant ave :

subset(df, ave(as.integer(factor(Sex)), Sex, Age, FUN = "length") > 3)

4voto

Georgery Points 408

OK, voici une option de base-R

set.seed(123)
Sex = sample(c('Male','Female'),size = 20,replace = TRUE)
Age = sample(c('Low','High'),size = 20,replace = TRUE)
Index = 1:20
df = data.frame(index = Index,Sex=Sex,Age=Age)
df

merge(
    df
    , aggregate(rep(1, nrow(df)), by = df[,c("Sex", "Age")], sum)
    , by = c("Sex", "Age")
)

La fonction agrégée sum s sur tous les 1 pour toutes les combinaisons.

4voto

akrun Points 148302

Nous pouvons le faire avec data.table et il devrait aussi être efficace

library(data.table)
setDT(df)[, .SD[.N > 3], .(Sex, Age)]

Ou avec .I

setDT(df)[df[, .I[.N >3], .(Sex, Age)]$V1]

1voto

loki Points 4669

A dplyr la réponse serait

library(dplyr)
df %>% 
  group_by(Sex, Age) %>% 
  filter(n() > 3) 

Même si cela est indiqué dans l'OP il ne s'agit pas d'une solution de base R. J'ai pensé que cela pourrait être utile pour les futurs utilisateurs qui n'ont pas de telles restrictions.

1voto

Moody_Mudskipper Points 18115
vars     <- c("Sex","Age")
max_freq <- 3
new_df   <- merge(df, subset(as.data.frame(table(df[,vars])),Freq>max_freq)[1:2])

new_df
#       Sex  Age index
# 1  Female High     2
# 2  Female High     7
# 3  Female High    14
# 4  Female High    11
# 5  Female High     5
# 6  Female High     4
# 7  Female High    13
# 8  Female High     8
# 9    Male High     6
# 10   Male High     3
# 11   Male High     1
# 12   Male High    17
# 13   Male High    12
# 14   Male  Low    10
# 15   Male  Low    15
# 16   Male  Low    18
# 17   Male  Low    19

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X