はい、2つの数値の真ん中にある場合(つまり、2.5が2になる場合)、常に最も近い偶数に丸める理由を知っています。しかし、私が一部の人々のデータを評価したいとき、彼らはこの振る舞いを望んでいません。これを取得する最も簡単な方法は何ですか:
x <- seq(0.5,9.5,by=1)
round(x)
0,2,2,4,4、...、10ではなく1,2,3、...、10になります。
編集:明確にするために:丸め後、1.4999は1になるはずです。(これは明らかだと思いました)
これは私自身の機能ではありません。残念ながら、現時点ではどこで入手したかはわかりません(元々は統計的に有意なブログで匿名のコメントとして見つかりました)が、必要なものには役立つはずです。
round2 = function(x, n) {
posneg = sign(x)
z = abs(x)*10^n
z = z + 0.5 + sqrt(.Machine$double.eps)
z = trunc(z)
z = z/10^n
z*posneg
}
x
は丸めるオブジェクトであり、n
は丸める桁数です。
例
x = c(1.85, 1.54, 1.65, 1.85, 1.84)
round(x, 1)
# [1] 1.8 1.5 1.6 1.8 1.8
round2(x, 1)
# [1] 1.9 1.5 1.7 1.9 1.8
(@Gregorを追加してくれてありがとう+ sqrt(.Machine$double.eps)
。)
round
これらのxxx.5値を除いて、まったく同じように動作するものが必要な場合は、次のことを試してください。
x <- seq(0, 1, 0.1)
x
# [1] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
floor(0.5 + x)
# [1] 0 0 0 0 0 1 1 1 1 1 1
@CarlWitthoftがコメントで述べたように、これは以下で言及されているIEC60559規格です?round
。
5を四捨五入する場合は、IEC60559標準が使用されることが予想されることに注意してください。「偶数桁に移動」します。したがって、round(0.5)は0で、round(-1.5)は-2です。ただし、これはOSサービスと表現エラーに依存します(たとえば、0.15は正確に表現されていないため、丸め規則は印刷された数値ではなく、表現された数値に適用されます。したがって、round(0.15、1)は0.1または0.2のいずれかになります。 )。
グレッグスノーによる追加の説明:
丸めから偶数へのルールの背後にある論理は、基礎となる連続値を表現しようとしていることです。xが真に連続分布からのものである場合、x == 2.5は0であり、2.5はおそらく任意の値から1回丸められています。 2.45〜2.54999999999999 ...、小学校で学んだ0.5のルールの切り上げを使用する場合、二重の丸めは、2.45〜2.50の値がすべて3に丸められることを意味します(最初に2.5に丸められます)。これは、見積もりを上向きにバイアスする傾向があります。バイアスを取り除くには、2.5に丸める前に戻るか(多くの場合、非現実的ではありません)、半分の時間を切り上げて半分の時間を切り下げます(または、可能性に比例して丸める方がよいでしょう)。 2.5より下または上の値を2.5に丸めて表示します。しかし、それはほとんどの基礎となるディストリビューションで50/50に近くなります)。確率論的アプローチは、ラウンド関数にラウンドする方法をランダムに選択させることですが、決定論的タイプはそれに快適ではないため、ラウンドする一貫したルールとして「ラウンドから偶数」が選択されました(ラウンドから奇数はほぼ同じように機能するはずです)。上下約50/50。
2.5が正確な値を表す可能性が高いデータ(たとえば、お金)を扱っている場合は、すべての値に10または100を掛けて整数で処理し、最終的な印刷のためだけに変換して戻すと、より良い結果が得られます。2.50000001は3に丸められることに注意してください。したがって、最終印刷までより多くの桁の精度を維持すると、丸めは期待される方向に進むか、丸めの直前に値に0.000000001(またはその他の小さな数値)を追加できますが、それは可能です。見積もりを上向きにバイアスします。
これは機能しているようです。
rnd <- function(x) trunc(x+sign(x)*0.5)
Ananda Mahtoの応答は、これ以上のことを行っているようです。彼の応答の余分なコードが何を説明しているのかわかりません。つまり、上記で定義したrnd()関数を壊す方法がわかりません。
例:
seq(-2, 2, by=0.5)
# [1] -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0
round(x)
# [1] -2 -2 -1 0 0 0 1 2 2
rnd(x)
# [1] -2 -2 -1 -1 0 1 1 2 2
データの揺れにどれだけ慣れているかに応じて、これは機能します。
round(x+10*.Machine$double.eps)
# [1] 1 2 3 4 5 6 7 8 9 10
この方法:
round2 = function(x, n) {
posneg = sign(x)
z = abs(x)*10^n
z = z + 0.5
z = trunc(z)
z = z/10^n
z*posneg
}
数字が多い場合はうまく機能しないようです。たとえば、実行round2(2436.845, 2)
すると2436.84が得られます。関数で問題が発生しているtrunc(z)
ようです。
全体として、Rが数値を格納する方法と関係があると思います。したがって、trunc
andfloat
関数が常に機能するとは限りません。私はそれを最もエレガントな方法ではなく回避することができました:
round2 = function(x, n) {
posneg = sign(x)
z = abs(x)*10^n
z = z + 0.5
z = trunc(as.numeric(as.character(z)))
z = z/10^n
(z)*posneg
}
これは、.5でのゼロからの丸めを模倣しています。
round_2 <- function(x, digits = 0) {
x = x + abs(x) * sign(x) * .Machine$double.eps
round(x, digits = digits)
}
round_2(.5 + -2:4)
-2 -1 1 2 3 4 5