3
votes

Sélection avec un filtre sur le numéro de ligne et la valeur

J'ai le simple "test" de data.table suivant. Je voudrais sélectionner toutes les lignes de la ligne 3 à 8 avec X égal à "A":

library(data.table)
set.seed(1)
test <- data.table(X=c(rep("A",5),rep("B",5)),Y=rnorm(10),Z=rnorm(10))

test[3:8 & X == "A"] # gives the not desired output:

1: A -0.6264538  1.5117812
2: A  0.1836433  0.3898432
3: A -0.8356286 -0.6212406
4: A  1.5952808 -2.2146999
5: A  0.3295078  1.1249309
Warning message:
  In 3:8 & X == "A" :
  longer object length is not a multiple of shorter object length

# desired outcome:

3: A -0.8356286 -0.62124058
4: A  1.5952808 -2.21469989
5: A  0.3295078  1.12493092

Entre la ligne 3: 8, je voudrais sélectionner uniquement celles avec X == " UNE". Comment est-ce possible? Veuillez noter que l'utilisation de test [3: 8] [X == "A"] ne semble pas être une option, car je souhaite effectuer des calculs sur ces lignes qui sont enregistrées dans la table de données d'origine.


2 commentaires

test [3: 8,] [X == "A",]


@ M-M Je pensais à la même chose, mais je veux effectuer des calculs sur les autres colonnes (par exemple Y et Z), qui sont enregistrées dans le test. Cette approche crée un nouveau DT, de sorte que les calculs ne sont pas enregistrés. Essayez par exemple test [3: 8,] [X == "A", Z: = Z + 3]


3 Réponses :


5
votes

Ici 3: 8 n'est certainement pas de la même longueur que la deuxième expression ( X == "A" ) et plus encore, nous comparons un index logique avec un index numérique. Au lieu de cela, convertissez la première expression en logique en utilisant % in% sur la séquence de lignes, puis deux choses se produisent - 1) les longueurs deviennent identiques, 2) Même type

test[(seq_len(.N) %in% 3:8) & X == "A"]
#    X          Y          Z
#1: A -0.8356286 -0.6212406
#2: A  1.5952808 -2.2146999
#3: A  0.3295078  1.1249309


2 commentaires

merci je m'attendais à ce que ce soit une seule ligne. Une manière intéressante de travailler avec .N !


@IceCreamToucan Pas de problème. J'étais à propos de l'édition, mais il y a une autre solution publiée



4
votes
library(data.table)
set.seed(1)
test <- data.table(X=c(rep("A",5),rep("B",5)),Y=rnorm(10),Z=rnorm(10))

test[test[, .I %in% 3:8 & X == "A"], Z := Z+3][]
#>     X          Y           Z
#>  1: A -0.6264538  1.51178117
#>  2: A  0.1836433  0.38984324
#>  3: A -0.8356286  2.37875942
#>  4: A  1.5952808  0.78530011
#>  5: A  0.3295078  4.12493092
#>  6: B -0.8204684 -0.04493361
#>  7: B  0.4874291 -0.01619026
#>  8: B  0.7383247  0.94383621
#>  9: B  0.5757814  0.82122120
#> 10: B -0.3053884  0.59390132
Created on 2019-06-21 by the reprex package (v0.3.0)

2 commentaires

Merci @ M-M. J'ai accepté la réponse d'Akrun qui était un peu plus rapide


@ Talik3233 pas de soucis, c'était juste hier qu'akrun et moi parlions d'eux comme étant un adversaire pour moi;)



0
votes

Si vous devez sélectionner des lignes à partir d'un certain index (3: 8) puis filtrer une variable avec une certaine valeur (ici X == 'A'), vous pouvez essayer avec `dplyr package ':

library(data.table)
library(dplyr)
set.seed(1)
test <- data.table(X=c(rep("A",5),rep("B",5)),Y=rnorm(10),Z=rnorm(10))

test %>% slice(3:8) %>% filter(X == 'A')


1 commentaires

Pour info, OP a noté dans un commentaire qu'il souhaitait mettre à jour / muter ces lignes. (Votre message reste cependant une réponse valide à la question posée.)