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.