Come filtrare valori di un array

samurai.sette

Utente Attivo
17 Dic 2015
228
6
18
Ciao a tutti.
Come da titolo ho la necessità di filtrare un array eliminando da esso tutti quei valori che si discostano in maniera eccessiva dagli agli.
Faccio un esempio.
PHP:
array (0.13 , 0.12 , 0.15 , 7 , 0.11 , 5);
Come potete vedere nell'array che ho scritto i valori riportati sono tutti molto simili tra loro ad eccezione del quarto valore (7) e dell'ultimo valore (5).
Ciò che vorrei riuscire a fare è questo: se nell'array dovesse capitare un valore abnorme rispetto agli altri (in questo caso il 7 e il 5), questi devono essere eliminati dall'array.
Preciso che l'array viene creato e valorizzato da un Arduino che invia progressivamente i valori in maniera automatica; qualche volta può capitare che il valore inviato sia "sballato".
Qualcuno ha un'idea su come potrei procedere?
Ciao, grazie mille.
 

f107

Utente Attivo
7 Ago 2012
203
6
18
Roma
Ciao!

secondo me hai due possibilità, PHP ha la funzione array_filter che fa al caso tuo (qui maggiori info).
Se hai dei valori di soglia tipo minimo e massimo noti potresti fare così:
PHP:
$min = 0;
$max = 2;

$valueBetween = function($value) use($min, $max) {
    return $value && $min < $value && $value < $max;
};

$result = array_filter($array, $valueBetween);

var_dump($result);
Se invece vuoi una cosa più "dinamica" potresti decidere un valore massimo di differenza tra la media dei valori presenti nell'array, esempio:
PHP:
// max diff value
$delta_max = 2;

// remove null
$array = array_filter($array);

$avg = array_sum($array) / count($array);

$avgDiff = function($value) use($delta_max, $avg) {
    return abs($value - $avg) < $delta_max;
};

$result = array_filter($array, $avgDiff);
var_dump($avg, $result);
Nel secondo caso attenzione, che se i numeri che ritornano sono tanto più alti (ad esempio 100) non funziona più come logica, Vedi tu.

Sono solo dei piccoli spunti, spero ti siano utili
 
Ultima modifica:

samurai.sette

Utente Attivo
17 Dic 2015
228
6
18
Ciao f107, grazie per la risposta.
Per quanto riguarda la tua prima idea tenderei a escluderla perché non posso impostare un valore minimo e un valore massimo a priori.

La tua seconda idea è sicuramente più funzionale anche se anche qui non posso impostare un valore massimo di differenza tra la media dei valori.

Ti faccio un esempio reale di dati inviati da un arduino per circa un anno e mezzo (dati giusti). Inizialmente questi dati avevano un valore di circa 0.20 per poi aumentare progressivamente fino a circa 4.03
Capisci bene che prima di iniziare a inviare i dati con arduino non ho modo di sapere quali valori impostare nelle tue due idee.

Sono comunque due buone idee (soprattutto la seconda).
 
  • Like
Reactions: f107

f107

Utente Attivo
7 Ago 2012
203
6
18
Roma
Ok, ora mi è più chiara la situazione, dipende da molte cose, ad esempio l'incremento che andamento segue? Lineare? Solitamente quanti valori sballati hai?

Puoi pensare a varie strategie comunque:
https://it.wikipedia.org/wiki/Scarto_quadratico_medio oppure meglio questa https://it.wikipedia.org/wiki/Deviazione_mediana_assoluta
se vuoi farlo più semplice, e sei sicuro che avrai più valori corretti che fuori set, puoi modellare la seconda opzione che ti avevo dato e usare come delta_max una percentuale ragionevole

Spero siano spunti utili
 

macus_adi

Utente Attivo
5 Dic 2017
1.266
82
48
IT/SW
Simile a quanto suggerito da @f107 , una media della differenza assoluta tra gli elementi dell'array eliminando il massimo ed il minimo, in pratica il delta lo calcola lui...
La stesura non è bella volutamente!
PHP:
function calcolaMediaStep($data){
   $dati=[];
   for($i=1;$i<count($data);$i++){
      $dati[]=abs($data[$i-1]-$data[$i]);
   }
   return array_sum(array_diff($dati,[min($dati),max($dati)]))/count($data);
}
function createNewArray($data){
   $makeDiff=calcolaMediaStep($data);
   $local=[];
   foreach ($data as $items){
      ($items<=$makeDiff)?$local[]=$items:null;
   }
   return $local;
}

$demo=array (0.13 , 0.12 , 0.15 , 7 , 0.11 , 5);
$arr=createNewArray($demo);
dd($arr);
 
  • Like
Reactions: f107