J'essaie d'identifier les valeurs incompatibles en fonction d'une valeur d'élément avant ou après la valeur focale dans un vecteur. Avez-vous réfléchi à la façon de procéder?
Disons que j'ai un vecteur: x <-c (1,1,2,1,3,3) . Si élément [i] correspond à l'élément avant ou après l'élément i ( élément [i-1] et élément [i + 1] ). S'il y a une correspondance, l'élément [i] doit être égal à «oui», sinon il doit être égal à «non».
La sortie attendue pour x <-c (1,1,2,1,3,3) doit être c ("yes", "yes", "no", "non", "oui", "oui") .
4 Réponses :
Voici une approche de base R. Nous pouvons générer des vecteurs décalés, soit une position vers la gauche, soit une position vers la droite, à partir de votre vecteur d'entrée d'origine. Ensuite, nous pouvons affirmer si chaque position dans le vecteur d'origine correspond à l'une ou l'autre de la même position dans les vecteurs décalés. Pour donner un visuel:
x <- as.character(c(1,1,2,1,NA,NA))
x1 <- c('NA', x[1:length(x)-1])
x2 <- c(x[2:length(x)], 'NA')
result <- (x==x1 | is.na(x) & is.na(x1) | x==x2 | is.na(x) & is.na(x2))
output <- ifelse(is.na(result) | !result, "no", "yes")
output
[1] "yes" "yes" "no" "no" "yes" "yes"
Nous pouvons voir le résultat que vous attendez par inspection. Voici un extrait de code implémentant ceci:
x: [ 1, 1, 2, 1, 3, 3] ------------------------ x1: [NA, 1, 1, 2, 1, 3] x2: [ 1, 2, 1, 3, 3, NA]
Notez que j'ai délibérément converti votre vecteur numérique en vecteur de caractères, afin que je puisse utiliser 'NA' code >, une chaîne littérale, comme espace réservé pour une valeur manquante. Si nous avons utilisé la logique ci-dessus avec un vecteur numérique, NA pourrait entrer en conflit avec les valeurs manquantes réelles.
@Gregor Il y a en fait un plus gros problème, c'est que peut-être le vecteur de l'OP contient des valeurs NA . Ensuite, utiliser NA comme espace réservé pour une valeur manquante ne fonctionnera pas.
@Gregor J'ai un peu corrigé la réponse. Maintenant, il est même robuste de comparer les valeurs NA dans le vecteur numérique d'origine. Ma logique suppose que deux valeurs NA adjacentes se traduiraient par yes .
Je ne suis pas non plus fan de x [1: length (x) -1] , mais je ferais un pitch pour head (x, -1) comme une version plus propre
@dww mon problème avec cela est que je ne me souviens jamais si head (x, -1) ou tail (x, -1) est équivalent à x [- longueur (x)] . Je l'essaie à chaque fois. Mais je préfère définitivement la syntaxe head lorsque plusieurs valeurs doivent omettre la fin.
Voici une façon de le faire (en utilisant TRUE et FALSE à la place de "yes" et "no" code>). Explication dans les commentaires. pre_or_post_matches <- function(vec){
# get length of `vec`, create empty return vector `out` that we fill
len <- length(vec)
out <- rep(NA, len)
# first element: just check if it equals the second
out[1] <- vec[1]==vec[2]
# last element: just check if it equals the second to last
out[len] <- vec[len]==vec[len-1]
# the other elements: check if equal to at least one neighbor
for (idx in 2:(len-1)){
out[idx] <- (vec[idx]==vec[idx-1]) | (vec[idx]==vec[idx+1])
}
return(out)
}
# apply func to example data provided by OP
x <- c(1, 1, 2, 1, 3, 3)
pre_or_post_matches(x)
## [1] TRUE TRUE FALSE FALSE TRUE TRUE
Une seule ligne pour cela est d'utiliser diff
c(diff(x) == 0, F) | c(F, diff(x) == 0) [1] TRUE TRUE FALSE FALSE TRUE TRUE
c (diff (x) == 0, F) sera être vrai pour chaque index avec l'élément [i] == élément [i + 1] (non applicable pour le dernier élément) et c (F, diff (x) == 0) sera vrai pour chaque index avec élément [i] == élément [i-1] (non applicable pour le premier élément)
Utilisez rle () pour identifier les exécutions de valeurs égales. lengths == 1 signifie qu'il n'y a pas de valeurs égales avant ou après la valeur actuelle.
with(rle(x), rep(lengths != 1, lengths)) # [1] TRUE TRUE FALSE FALSE TRUE TRUE
Modifier: version plus concise (merci pour @ dww's comment)
with(rle(x), rep(ifelse(lengths == 1, "no", "yes"), lengths)) # [1] "yes" "yes" "no" "no" "yes" "yes"
ou de façon plus concise rep ((l <- rle (x) $ l) == 1, l)
très agréable! n'était pas familier avec rle ()