J'ai des données comme celle-ci, où certains "nom" se produisent plus de trois fois:
df <- data.frame(name = c("a", "a", "a", "b", "b", "c", "c", "c", "c"), x = 1:9)
name x
1 a 1
2 a 2
3 a 3
4 b 4
5 b 5
6 c 6
7 c 7
8 c 8
9 c 9
Je souhaite sous-ensemble (filtrer) les données en fonction du nombre de lignes (observations) à l'intérieur de chaque niveau de la variable name
. Si un certain niveau de name
se produit plus que disons 3 fois, je veux supprimer toutes les lignes appartenant à ce niveau. Donc, dans cet exemple, nous supprimerions des observations où name == c
, car il y a > 3
lignes dans ce groupe:
name x
1 a 1
2 a 2
3 a 3
4 b 4
5 b 5
J'ai écrit ce code, mais je ne peux pas le faire fonctionner.
as.data.frame(table(unique(df)$name))
subset(df, name > 3)
D'abord, deux base
alternatives. L'un s'appuie sur table
, et l'autre sur ave
et length
. Ensuite, deux data.table
façons.
table
tt <- table(df$name)
df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]
Si vous voulez le parcourir étape par étape:
# count each 'name', assign result to an object 'tt'
tt <- table(df$name)
# which 'name' in 'tt' occur more than three times?
# Result is a logical vector that can be used to subset the table 'tt'
tt < 3
# from the table, select 'name' that occur < 3 times
tt[tt < 3]
# ...their names
names(tt[tt < 3])
# rows of 'name' in the data frame that matches "the < 3 names"
# the result is a logical vector that can be used to subset the data frame 'df'
df$name %in% names(tt[tt < 3])
# subset data frame by a logical vector
# 'TRUE' rows are kept, 'FALSE' rows are removed.
# assign the result to a data frame with a new name
df2 <- subset(df, name %in% names(tt[tt < 3]))
# or
df2 <- df[df$name %in% names(tt[tt < 3]), ]
ave
et length
Comme suggéré par @flodel:
df[ave(df$x, df$name, FUN = length) < 3, ]
data.table
: .N
et .SD
:library(data.table)
setDT(df)[, if (.N < 3) .SD, by = name]
data.table
: .N
et .I
:setDT(df)
df[df[, .I[.N < 3], name]$V1]
Voir aussi les questions et réponses connexes Compter le nombre d'observations/lignes par groupe et ajouter le résultat au bloc de données .
Utilisation du package dplyr
:
df %>%
group_by(name) %>%
filter(n() < 4)
# A tibble: 5 x 2
# Groups: name [2]
name x
<fct> <int>
1 a 1
2 a 2
3 a 3
4 b 4
5 b 5
n()
renvoie le nombre d'observations dans le groupe actuel, afin que nous puissions group_by
nommer, puis conserver uniquement les lignes qui font partie d'un groupe où le nombre de lignes dans ce groupe est inférieur de 4.
Encore une autre façon d'utiliser le package dpylr
consiste à utiliser la fonction count
puis à effectuer une semi-jointure sur le bloc de données d'origine:
library(dplyr)
df %>%
count(name) %>%
filter(n <= 3) %>%
semi_join(df, ., by = "name")