2011-10-26 7 views
6

Mi scuso se il titolo non è chiaro, ma non sono riuscito a spiegarlo in modo sintetico.per arrotondare al prossimo ordine di grandezza in R

Dato un vettore di concentrazioni, vorrei arrotondare il valore massimo al successivo ordine di grandezza (vale a dire, da 345 a 1000). Inoltre, vorrei arrotondare il valore minimo all'ordine di grandezza inferiore (ad esempio, da 3,2 a 1). Queste concentrazioni possono anche essere inferiori a 1, quindi ad esempio 0,034 dovrebbe essere arrotondato a 0,01.

Qualche idea?

+0

che non è arrotondamento, ma qualcos'altro. È possibile arrotondare 32 a 30 e di conseguenza 30 a 0, ma non a 10 o 1. –

risposta

12

Non sono sicuro di R, ma questo è un processo semplice da descrivere algoritmicamente.

Prendere il logaritmo di base 10 del numero e applicare un soffitto o un pavimento al risultato. Alza 10 a quel potere. Fatto.

Hai bisogno di un caso speciale per 0 perché non si può prendere un logaritmo di 0.

+0

Grazie Mark! Esattamente quello di cui avevo bisogno. – sinclairjesse

8

Ecco una semplice funzione che fa quello che stai dopo:

log10_ceiling <- function(x) { 
    10^(ceiling(log10(x))) 
} 

log10_ceiling(c(345, 3.2, 0.034)) 
# [1] 1000.0 10.0 0.1 
+0

Nice Josh. Grazie! – sinclairjesse

1

pacchetto di Hadley plyr ha un funzione estremamente flessibile chiamata round_any che fa questo elegantemente. Ecco come si potrebbe chiamare la funzione

round_any(x, accuracy, f = round) 

Nel tuo caso, x = 345, accuracy = 1000 e si vuole f = ceiling. Quindi chiamando

round_any(x = 345, accuracy = 1000, f = ceiling) 

avrebbe fatto il lavoro

EDIT. Ho appena visto che si desidera che lo maximum sia arrotondato a ceiling ei valori minimi arrotondati a floor. cambiare il f nella chiamata di funzione per ottenere questo.

+0

Grazie per le informazioni Ramnath! Lo guarderò. – sinclairjesse

1

La risposta accettata da Mark Ransom è per lo più corretta. Dopo aver implementato questo in Java ho trovato alcune altre aree che devono essere affrontate:

  • numeri negativi devono essere maneggiati specialmente se si vuole -375 a cedere -1000
  • soffitto per i valori di registro positivi, piano + 1 per i valori di log negativi (il più positivo è importante se si desidera che 0.456 restituisca 1).

Qui è la mia implementazione in Java con l'unità di far passare i test

static double roundUpToNearestMagnitude(double n) { 
    if (n == 0d) return 1d; 
    boolean negative = n < 0; 
    double log = Math.log10(Math.abs(n)); 
    double decimalPlaces = ((log > 0)) ? (Math.ceil(log)) : (Math.floor(log) + 1); 
    double rounded = Math.pow(10, decimalPlaces); 
    return negative ? -rounded : rounded; 
} 

@Test public void roundUpToNearestMagnitudeFifty() { 
    Assert.assertEquals(100d, roundUpToNearestMagnitude(50d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeFive() { 
    Assert.assertEquals(10d, roundUpToNearestMagnitude(5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZeroPointFive() { 
    Assert.assertEquals(1d, roundUpToNearestMagnitude(0.5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZeroPointZeroFive() { 
    Assert.assertEquals(.1d, roundUpToNearestMagnitude(0.05d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZeroPointZeroZeroFive() { 
    Assert.assertEquals(.01d, roundUpToNearestMagnitude(0.005d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeFifty() { 
    Assert.assertEquals(-100d, roundUpToNearestMagnitude(-50d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeFive() { 
    Assert.assertEquals(-10d, roundUpToNearestMagnitude(-5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeZeroPointFive() { 
    Assert.assertEquals(-1d, roundUpToNearestMagnitude(-0.5d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeZeroPointZeroFive() { 
    Assert.assertEquals(-.1d, roundUpToNearestMagnitude(-0.05d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeNegativeZeroPointZeroZeroFive() { 
    Assert.assertEquals(-.01d, roundUpToNearestMagnitude(-0.005d), 0.000001); 
} 

@Test public void roundUpToNearestMagnitudeZero() { 
    Assert.assertEquals(1, roundUpToNearestMagnitude(0d), 0.000001); 
} 
Problemi correlati