2016-01-17 13 views
27

Von R-Hilfe-Funktion: Beachten Sie, dass zum Abrunden einer 5 der IEC 60559-Standard erwartet wird, "gehe zur geraden Ziffer". Daher ist round(0.5) 0 und round(-1.5) ist -2.rund, aber .5 sollte leer sein

> round(0.5) 
[1] 0 
> round(1.5) 
[1] 2 
> round(2.5) 
[1] 2 
> round(3.5) 
[1] 4 
> round(4.5) 
[1] 4 

Aber ich brauche alle Werte mit Endung .5 abgerundet werden. Alle anderen Werte sollten so gerundet werden, wie sie von der Funktion round() ausgeführt werden. Beispiel:

round(3.5) = 3 
round(8.6) = 9 
round(8.1) = 8 
round(4.5) = 4 

Gibt es eine schnelle Möglichkeit, es zu tun?

+15

Warum nicht nur 'ceil (x - 0.5)'? –

+1

@DietrichEpp Ich kam, um die gleiche Frage zu stellen: Ich glaube, dass Ihre Frage wahrscheinlich eine Antwort sein sollte :) –

+4

Können wir einen Moment sichern und fragen ** warum ** Sie dies tun möchten. Sie führen eine Verzerrung in Ihrem gerundeten Datensatz ein. Was ist ein Problem, und warum glauben Sie, dass es diese besondere Behandlung erfordert? –

Antwort

28

Per Dietrich Epp Kommentar, können Sie die ceiling() Funktion mit einem Offset verwenden, um eine schnelle, vektorisiert, richtige Lösung zu erreichen:

round_down <- function(x) ceiling(x - 0.5) 
round_down(seq(-2, 3, by = 0.5)) 
## [1] -2 -2 -1 -1 0 0 1 1 2 2 3 

Ich denke, das ist schneller und viel einfacher als viele der anderen hier gezeigten Lösungen.

Wie von Carl Witthoft angemerkt, fügt dies Ihren Daten viel mehr Neigung als einfache Rundung. Vergleich:

mean(round_down(seq(-2, 3, by = 0.5))) 
## [1] 0.2727273 
mean(round(seq(-2, 3, by = 0.5))) 
## [1] 0.4545455 
mean(seq(-2, 3, by = 0.5)) 
## [1] 0.5 

Was ist die Anwendung für ein solches Rundungsverfahren?

+2

Dies ist bei weitem der beste Weg, dies zu tun. –

20

überprüfen Sie, ob der Rest der x %% 1-.5 gleich ist und dann Boden oder um die Zahlen:

x <- seq(1, 3, 0.1) 
ifelse(x %% 1 == 0.5, floor(x), round(x)) 
> 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 
10

Diese Funktion ist durch die Elemente zu finden, die Dezimalteil gleich 0.5 haben, und das Hinzufügen eine kleine negative Zahl zu zu ihnen vor dem Runden, um sicherzustellen, dass sie nach unten abgerundet werden. (Es stützt sich -. Harmlos, aber in einer Weise, leicht verschleierte --- auf der Tatsache, dass ein boolescher Vektor in R wird auf einen Vektor von 0 ‚s und 1‘ s umgewandelt werden, wenn durch einen numerischen Vektor multipliziert)

f <- function(x) { 
    round(x - .1*(x%%1 == .5)) 
} 

x <- c(0.5,1,1.5,2,2.5,2.01,2.99) 
f(x) 
[1] 0 1 1 2 2 2 3 
8

Die Funktion (nicht golfed) ist sehr einfach und überprüft, ob die verbleibenden Dezimalstellen .5 oder weniger sind. In der Tat könnte man leicht macht es nützlichen und nehme 0.5 als Argument:

nice.round <- function(x, myLimit = 0.5) { 
    bX <- x 
    intX <- as.integer(x) 
    decimals <- x%%intX 
    if(is.na(decimals)) { 
    decimals <- 0 
    } 
    if(decimals <= myLimit) { 
    x <- floor(x) 
    } else { 
    x <- round(x) 
    } 
    if (bX > 0.5 & bX < 1) { 
    x <- 1 
    } 
    return(x) 
} 

Tests

Derzeit ist diese Funktion nicht richtig mit Werten zwischen 0,5 und 1,0 arbeitet.

> nice.round(1.5) 
[1] 1 
> nice.round(1.6) 
[1] 2 
> nice.round(10000.624541) 
[1] 10001 
> nice.round(0.4) 
[1] 0 
> nice.round(0.6) 
[1] 1 
+1

"nicht golfed" -ist das soll ein * schlecht * Ding sein ?? – wchargin

+0

@WChargin Absolut nicht, ich habe nur angezeigt, dass die Funktion einfach kürzer gemacht werden könnte. – Konrad

+0

Hier ist eine Anmerkung von @Kreupf, die sich darum kümmern, diesen Beitrag zu bearbeiten: "Momentan funktioniert diese Funktion nicht korrekt mit Werten zwischen 0.5 und 1.0.' Nice.round (0.6) 'gibt 0 zurück." – vard

14

Ich werde den Zirkus kommen zu:

rndflr <- function(x) { 
    sel <- vapply(x - floor(x), function(y) isTRUE(all.equal(y, 0.5)), FUN.VALUE=logical(1)) 
    x[sel] <- floor(x[sel]) 
    x[!sel] <- round(x[!sel]) 
    x 
} 

rndflr(c(3.5,8.6,8.1,4.5)) 
#[1] 3 9 8 4 
+1

+1 von mir. Die einzige Antwort mit 'all.equal()', die IMHO ist der richtige Weg, um solche Situationen zu behandeln. – RHertel

Verwandte Themen