Je dois filtrer ma trame de données par rapport à une condition particulière. Mieux vaut si la solution envisage l'utilisation de dplyr.
J'ai une structure de dataframe comme celle-ci
sentId. B. label. partner. code 1. 2. 3. 4. 123 1. 2. 2. 4. 124 4. 2. 3. 8. 125
Si la colonne label contient une valeur particulière (par exemple, 3.), collectez non seulement cette ligne , mais également toutes les lignes qui ont les mêmes sentID et valeur de partenaire de la précédente un.
Les résultats attendus sont les suivants:
sentId. B. label. partner. code 1. 2. 3. 4. 123 1. 2. 2. 4. 124 4. 2. 3. 8. 125 7. 3. 2. 7. 126
4 Réponses :
Nous pouvons utiliser % in%
pour filtrer
les lignes après le regroupement par "sentId." et "partenaire".
df1 <- structure(list(sentId. = c(1, 1, 4, 7), B. = c(2, 2, 2, 3), label. = c(3, 2, 3, 2), partner. = c(4, 4, 8, 7), code = 123:126), class = "data.frame", row.names = c(NA, -4L))
Ou de façon compacte avec data.table
df1[with(df1, ave(label.==3, sentId., partner., FUN = any)),]
Ou avec base R
p>
library(data.table) setDT(df1)[, .SD[3 %in% label.], .(sentId., partner.)]
library(dplyr) df1 %>% group_by(sentId., partner.) %>% filter(3 %in% label.) # A tibble: 3 x 5 # Groups: sentId. [2] # sentId. B. label. partner. code # <dbl> <dbl> <dbl> <dbl> <int> #1 1 2 3 4 123 #2 1 2 2 4 124 #3 4 2 3 8 125
Il est nécessaire d'étendre le groupBy également à la valeur "partenaire". Cela fonctionne de cette façon. Je vous remercie
@Silvia J'ai également ajouté partenaire
Nous pouvons d'abord trouver les index de ligne où nous avons notre valeur label
intéressée, puis utiliser ces indices pour sous-définir les valeurs sentId
et partner
à partir de la totalité du dataframe.
library(dplyr) df %>% filter(sentId %in% sentId[label == label_value] & partner %in% partner[label == label_value])
La même logique dans dplyr
serait
label_value <- 3 inds <- df$label == label_value df[with(df, sentId %in% sentId[inds] & partner %in% partner[inds]), ] # sentId B label partner code #1 1 2 3 4 123 #2 1 2 2 4 124 #3 4 2 3 8 125
Ce problème peut être facilement formulé en utilisant SQL, donc une option serait d'utiliser la bibliothèque sqldf
:
library(sqldf) # your data frame df sql <- "SELECT t1.\"sentId.\", t1.\"B.\", t1.\"label.\", t1.\"partner.\", t1.code FROM yourTable t1 WHERE t1.\"label.\" = '3.' OR EXISTS (SELECT 1 FROM yourTable t2 WHERE t1.\"sentId.\" = t2.\"sentId.\" AND t1.\"partner.\" = t2.\"partner.\" AND t2.\"label.\" = '3.')" result <- sqldf(sql)
Remarque: La démo ci-dessus utilise en fait MariaDB, car SQLite ne fonctionnait pas avec l'outil de démonstration. Mais cela montre toujours que la logique de la requête est correcte.
En utilisant sqldf
:
Il extrait sentID
et partner
avec l'étiquette 3 en tant que deux requêtes internes et en extrait le résultat.
sentId B label partner code 1 1 2 3 4 123 2 1 2 2 4 124 3 4 2 3 8 125
Sortie :
names(df) <- gsub("\\.", "", names(df)) # to remove . from column name sqldf("select * from df where (sentID IN (select sentID from df where label IS 3) OR partner IN (select partner from df where label IS 3))")
Remarque: les noms de colonnes réels contiennent des points, vous devrez donc les échapper, en utilisant la syntaxe particulière de votre moteur de base de données sous-jacent.
@TimBiegeleisen: Merci de m'avoir corrigé. Suppression du premier .
du nom de la colonne pour faciliter les choses.