0
votes

calcul des minima des morceaux d'un vecteur: valeur manquante là où TRUE / FALSE est nécessaire

Je souhaite rassembler toutes les valeurs minimales non nulles des exécutions d'un vecteur séparées par des zéros. Ainsi, les résultats de l'application de mon code au vecteur x ci-dessous doivent être -1, -9 : -1 à partir de -1, 5 et -9 de -4, -9 .

J'exécute le code ci-dessous et j'obtiens le message suivant:

Erreur dans if ((temp [i] == 0) && (temp [i + 1]! = 0)) {: valeur manquante où TRUE / FALSE est nécessaire

x <- c(0, 0, -1, 5, 0, 0, -4, -9, 0)
temp = c()
minV = c()
for (i in 1:length(x)-1){
    temp[i] <- x[i]
    if((temp[i] == 0) && (temp[i+1] != 0)){
        minV <- c(minV,min(temp))
        temp <- c()
    }
}
minV

Que puis-je faire pour atteindre mon objectif?

r

1 commentaires

ressemble à l'un des résultats des contrôles logiques dans NA . voyez sur quelle valeur de i il s'arrête, puis vérifiez ce que l'instruction if résout pour cette valeur de i . Ensuite, découvrez pourquoi il se résout à NA


3 Réponses :


4
votes

L'opérateur : a une priorité inférieure à - . Cela signifie que 1: n - 1 est identique à seq (0, n-1) plutôt que seq (1, n-1) .


1 commentaires

Je pense que la principale raison pour laquelle ne pas utiliser automatiquement min (x) est qu'il / elle veut traiter chaque section du vecteur séparée par zéro individuellement et obtenir le minimum de chacune.



3
votes

Il y a donc plusieurs problèmes dans le code comme suit;

  1. Vous essayez d'évaluer la température [i + 1] alors qu'elle n'a pas encore été créée, cela donnera NA.
  2. Parce que vous indexez en utilisant i, après avoir libéré temp au milieu de la boucle quand il rencontre un zéro, il n'ajoutera pas de valeur au début de temp au lieu de cela il s'ajoutera au milieu.
  3. Lorsque vous bouclez, vous bouclez sur 1: length (x) -1 ce qui donnera 0 à 8 au lieu de cela, vous voulez le rendre 1: (length (x) - 1)

Voici un correctif du code;

# Creating data
x <- c(0, 0, -1, 5, 0, 0, -4, -9, 0)

# Split string at occurances of zeros
ll <- with(rle(x == 0),{
  ifelse(x == 0 & (seq_along(x) != cumsum(lengths)[lengths <= 3 & values]), NA, x)
})
x_split <- split(x, with(rle(is.na(ll)), rep(1:length(lengths), lengths) + ll * 0))

# Get minimum of each vector as list of minimum(s)
lapply(x_split, min)
# $`2`
# [1] -1
# 
# $`4`
# [1] -9

# Or get it in form of vector
unlist(lapply(x_split, min), use.names = FALSE)
# [1] -1 -9

# Or use sapply automatically [credit to Ben Bolker]
sapply(x_split, min)
# [1] -1 -9

Cependant, un meilleur moyen est de couper le vecteur chaque fois qu'il rencontre un zéro puis d'obtenir le minimum de chacun des les scissions comme suit;

# Creating data
x <- c(0, 0, -1, 5, 0, 0, -4, -9, 0)

# Create temp place holders
temp = c()
minV = c()

# Loop on x vector
for (i in 1:(length(x)-1)){
  # If x[i] is not zero
  if(x[i] != 0){
    # Append to temp
    temp <- c(temp, x[i])

    # If next value is zero then get minimum
    if(x[i+1] == 0){
      # Get minimum
      minV <- c(minV, min(temp))
      # Free temp
      temp <- c()
    }
  }
}
minV
# -1 -9


3 commentaires

J'aime ta solution. (1) c'est dommage qu'il n'y ait pas de moyen plus compact de faire le fractionnement; (2) pourquoi ne pas utiliser sapply () pour la dernière étape?


Bon point concernant Sapply, je l'ai ajouté à la solution. En ce qui concerne le fractionnement bien, j'ai pensé à une autre façon où je le convertit dans une chaîne puis couper la corde, puis reconvertit-le en vecteur, mais je pense que les deux nécessitent plusieurs étapes. Si vous connaissez une meilleure solution, merci de le partager.


Une version plus simple de la même idée générale: minV <- tapply (x, with (rle (x == 0), rep (seq_along (longueurs), longueurs)), FUN = min); minV [minV! = 0]



1
votes

Voici une autre alternative si cela vous aide?

x <- c(0, 0, -1, 5, 0, 0, -4, -9, 0)

accumulated.values <- NULL
min.values <- NULL

for (value in x) {

  # if we hit a 0
  if (value == 0) {

    # and we have some values accumulated 
    if (!is.null(accumulated.values)) {

      # calculate the minimum value of the accumulated values
      min.values <- c(min.values, min(accumulated.values))

      # clear the accumulated values 
      accumulated.values <- NULL
    }

    # otherwise ignore
  }
  else {

    # add the value to the accumulated list
    accumulated.values <- c(accumulated.values, value)
  }
}

min.values
# [1] -1 -9


0 commentaires