5
votes

Comment faire correspondre une valeur dans un vecteur avec celle avant et après dans r?

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

r

0 commentaires

4 Réponses :


1
votes

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.


4 commentaires

@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.



0
votes

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


0 commentaires

5
votes

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)


0 commentaires

6
votes

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"


2 commentaires

ou de façon plus concise rep ((l <- rle (x) $ l) == 1, l)


très agréable! n'était pas familier avec rle ()