web-dev-qa-db-ja.com

最も近い10(または100またはX)に切り上げる方法は?

データをプロットする関数を書いています。データセットの最大値より大きいY軸maxにNiceラウンド数を指定したいと思います。

具体的には、次を実行する関数fooが必要です。

foo(4) == 5
foo(6.1) == 10 #maybe 7 would be better
foo(30.1) == 40
foo(100.1) == 110 

私は

foo <- function(x) ceiling(max(x)/10)*10

最も近い10に丸めますが、これは任意の丸め間隔では機能しません。

Rでこれを行うより良い方法はありますか?

78
Abe

最も近い10のべき乗に切り上げたい場合は、次のように定義します。

_roundUp <- function(x) 10^ceiling(log10(x))
_

これは、xがベクトルの場合にも実際に機能します。

_> roundUp(c(0.0023, 3.99, 10, 1003))
[1] 1e-02 1e+01 1e+01 1e+04
_

..「Nice」の数値に丸める場合は、まず「Nice」の数値を定義する必要があります。以下では、 "Nice"を1〜10のNiceベース値を持つベクトルとして定義できます。デフォルトは、偶数に5を加えた値に設定されます。

_roundUpNice <- function(x, Nice=c(1,2,4,5,6,8,10)) {
    if(length(x) != 1) stop("'x' must be of length 1")
    10^floor(log10(x)) * Nice[[which(x <= 10^floor(log10(x)) * Nice)[[1]]]]
}
_

Xがベクトルの場合、上記は機能しません-今夜は遅すぎます:)

_> roundUpNice(0.0322)
[1] 0.04
> roundUpNice(3.22)
[1] 4
> roundUpNice(32.2)
[1] 40
> roundUpNice(42.2)
[1] 50
> roundUpNice(422.2)
[1] 500
_

[[編集]]

質問が指定された最も近い値(10または100など)に丸める方法である場合、James answer が最も適切であると思われます。私のバージョンでは、任意の値を取得して、適切な「ナイス」値に自動的に丸めることができます。上記の「ナイス」ベクトルの他の適切な選択肢は次のとおりです。1:10, c(1,5,10), seq(1, 10, 0.1)

プロットに値の範囲がある場合、たとえば_[3996.225, 40001.893]_の場合、自動方法では範囲のサイズと数値の大きさの両方を考慮する必要があります。そして Hadleyで表記 のように、pretty()関数はあなたが望むものかもしれません。

59
Tommy

plyrライブラリーには関数round_anyこれは、あらゆる種類の丸めを行うための非常に一般的なものです。例えば

library(plyr)
round_any(132.1, 10)               # returns 130
round_any(132.1, 10, f = ceiling)  # returns 140
round_any(132.1, 5, f = ceiling)   # returns 135
119
Ramnath

Rのラウンド関数は、digitsパラメーターが負の場合、特別な意味を割り当てます。

round(x、数字= 0)

負の桁数に丸めることは、10の累乗に丸めることを意味するため、たとえばround(x、digits = -2)は最も近い100に丸められます。

これは、次のような関数がpretty closeを求めているものに取得することを意味します。

foo <- function(x)
{
    round(x+5,-1)
}

出力は次のようになります

foo(4)
[1] 10
foo(6.1)
[1] 10
foo(30.1)
[1] 40
foo(100.1)
[1] 110
34
Zero

どうですか:

roundUp <- function(x,to=10)
{
  to*(x%/%to + as.logical(x%%to))
}

与えるもの:

> roundUp(c(4,6.1,30.1,100.1))
[1]  10  10  40 110
> roundUp(4,5)
[1] 5
> roundUp(12,7)
[1] 14
23
James

Round()のdigits-argumentに負の数を追加すると、Rは10、100などの倍数に丸めます。

    round(9, digits = -1) 
    [1] 10    
    round(89, digits = -1) 
    [1] 90
    round(89, digits = -2) 
    [1] 100
17

任意の数値を任意の間隔に切り上げ/切り捨て

モジュロ演算子%%を使用して、数値を特定の間隔に簡単に丸めることができます。

関数:

round.choose <- function(x, roundTo, dir = 1) {
  if(dir == 1) {  ##ROUND UP
    x + (roundTo - x %% roundTo)
  } else {
    if(dir == 0) {  ##ROUND DOWN
      x - (x %% roundTo)
    }
  }
}

例:

> round.choose(17,5,1)   #round 17 UP to the next 5th
[1] 20
> round.choose(17,5,0)   #round 17 DOWN to the next 5th
[1] 15
> round.choose(17,2,1)   #round 17 UP to the next even number
[1] 18
> round.choose(17,2,0)   #round 17 DOWN to the next even number
[1] 16

仕組み:

モジュロ演算子%%は、最初の数を2番目の数で割った余りを決定します。興味のある番号にこの間隔を加算または減算すると、基本的に選択した間隔に数値を「丸める」ことができます。

> 7 + (5 - 7 %% 5)       #round UP to the nearest 5
[1] 10
> 7 + (10 - 7 %% 10)     #round UP to the nearest 10
[1] 10
> 7 + (2 - 7 %% 2)       #round UP to the nearest even number
[1] 8
> 7 + (100 - 7 %% 100)   #round UP to the nearest 100
[1] 100
> 7 + (4 - 7 %% 4)       #round UP to the nearest interval of 4
[1] 8
> 7 + (4.5 - 7 %% 4.5)   #round UP to the nearest interval of 4.5
[1] 9

> 7 - (7 %% 5)           #round DOWN to the nearest 5
[1] 5
> 7 - (7 %% 10)          #round DOWN to the nearest 10
[1] 0
> 7 - (7 %% 2)           #round DOWN to the nearest even number
[1] 6

更新:

便利な2-argument version:

rounder <- function(x,y) {
  if(y >= 0) { x + (y - x %% y)}
  else { x - (x %% abs(y))}
}

正のyroundUp、負のyroundDown

 # rounder(7, -4.5) = 4.5, while rounder(7, 4.5) = 9.

または...

自動的に切り上げる関数またはDOWN標準の丸め規則に基づいて:

Round <- function(x,y) {
  if((y - x %% y) <= x %% y) { x + (y - x %% y)}
  else { x - (x %% y)}
}

x値が>である場合、丸め値yの後続のインスタンスの中間に自動的に切り上げられます。

# Round(1.3,1) = 1 while Round(1.6,1) = 2
# Round(1.024,0.05) = 1 while Round(1.03,0.05) = 1.05
10

任意の数の多重度に切り上げ、例えば10、これはジェームズの答えに対する単純な代替案です。

real切り上げられた数値(from)およびreal positive切り上げられた数値(to)に対して機能します。

> RoundUp <- function(from,to) ceiling(from/to)*to

例:

> RoundUp(-11,10)
[1] -10
> RoundUp(-0.1,10)
[1] 0
> RoundUp(0,10)
[1] 0
> RoundUp(8.9,10)
[1] 10
> RoundUp(135,10)
[1] 140

> RoundUp(from=c(1.3,2.4,5.6),to=1.1)  
[1] 2.2 3.3 6.6
7
hanna.lacka

あなたのコードは少し修正するだけでうまくいくと思います:

_foo <- function(x, round=10) ceiling(max(x+10^-9)/round + 1/round)*round
_

そして、例を実行します:

_> foo(4, round=1) == 5
[1] TRUE
> foo(6.1) == 10            #maybe 7 would be better
[1] TRUE
> foo(6.1, round=1) == 7    # you got 7
[1] TRUE
> foo(30.1) == 40
[1] TRUE
> foo(100.1) == 110
[1] TRUE
> # ALL in one:
> foo(c(4, 6.1, 30.1, 100))
[1] 110
> foo(c(4, 6.1, 30.1, 100), round=10)
[1] 110
> foo(c(4, 6.1, 30.1, 100), round=2.3)
[1] 101.2
_

次の2つの方法で機能を変更しました。

  • 2番目の引数を追加(指定した[〜#〜] x [〜#〜]
  • 大きな値が必要な場合は、max(x)に小さな値(_=1e-09_、自由に変更してください!)を追加しました
1
daroczig

常に数値を丸めたい場合 アップ 最も近いXには、ceiling関数を使用できます。

#Round 354 up to the nearest 100:
> X=100
> ceiling(354/X)*X
[1] 400

#Round 47 up to the nearest 30:
> Y=30
> ceiling(47/Y)*Y
[1] 60

同様に、常に丸めたい場合 ダウンfloor関数を使用します。単純に最も近いZに切り上げまたは切り捨てる場合は、代わりにroundを使用します。

> Z=5
> round(367.8/Z)*Z
[1] 370
> round(367.2/Z)*Z
[1] 365
1
Steve Walsh

外部ライブラリや暗号機能を使用せずにこれを試しましたが、動作します!

それが誰かを助けることを願っています。

ceil <- function(val, multiple){
  div = val/multiple
  int_div = as.integer(div)
  return (int_div * multiple + ceiling(div - int_div) * multiple)
}

> ceil(2.1, 2.2)
[1] 2.2
> ceil(3, 2.2)
[1] 4.4
> ceil(5, 10)
[1] 10
> ceil(0, 10)
[1] 0
0
Rahul Chawla

Tommy's answer のアップグレードバージョンがあります。これは、いくつかのケースを考慮しています。

  • 下限または上限の選択
  • 負の値とゼロの値を考慮する
  • 関数で小さい数値と大きい数値を別々に丸める場合に使用する2つの異なるNiceスケール。例:4は0で丸められ、400は400で丸められます。

コードの下:

round.up.Nice <- function(x, lower_bound = TRUE, Nice_small=c(0,5,10), Nice_big=c(1,2,3,4,5,6,7,8,9,10)) {
  if (abs(x) > 100) {
    Nice = Nice_big
  } else {
    Nice = Nice_small
  }
  if (lower_bound == TRUE) {
    if (x > 0) {
      return(10^floor(log10(x)) * Nice[[max(which(x >= 10^floor(log10(x)) * Nice))[[1]]]])
    } else if (x < 0) {
      return(- 10^floor(log10(-x)) * Nice[[min(which(-x <= 10^floor(log10(-x)) * Nice))[[1]]]])
    } else {
      return(0)
    }
  } else {
    if (x > 0) {
      return(10^floor(log10(x)) * Nice[[min(which(x <= 10^floor(log10(x)) * Nice))[[1]]]])
    } else if (x < 0) {
      return(- 10^floor(log10(-x)) * Nice[[max(which(-x >= 10^floor(log10(-x)) * Nice))[[1]]]])
    } else {
      return(0)
    }
  }
}
0
Yohan Obadia