2
votes

Extraire des lignes d'un bloc de données sous certaines conditions

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


0 commentaires

4 Réponses :


1
votes

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.)]

données

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


2 commentaires

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



1
votes

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


0 commentaires

1
votes

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)

 entrez la description de l'image ici

Démo

a >

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.


0 commentaires

1
votes

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))")


2 commentaires

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.