Rには、数値が整数であるかどうかをチェックする便利な機能が備わっていないことを知って驚いた。
_is.integer(66) # FALSE
_
is.integer(x)
は、x
に整数が含まれているかどうかをテストしません!そのためには、例の関数is.wholenumber(x)
のように、round
を使用します。
例には、このカスタム関数が「回避策」として含まれています
_is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
is.wholenumber(1) # is TRUE
_
上記のコメントを読んでいなかったと仮定して、整数をチェックする関数を作成する必要がある場合は、
_check.integer <- function(x) {
x == round(x)
}
_
私のアプローチはどこで失敗しますか?あなたが私の仮説の靴を履いていたなら、あなたの周りの仕事は何でしょうか?
別の方法は、小数部分をチェックすることです:
x%%1==0
または、特定の許容範囲内で確認する場合:
min(abs(c(x%%1, x%%1-1))) < tol
以下に、単純な関数を使用し、ハックを使用しないソリューションを示します。
all.equal(a, as.integer(a))
さらに、必要に応じて、ベクター全体を一度にテストできます。関数は次のとおりです。
testInteger <- function(x){
test <- all.equal(x, as.integer(x), check.attributes = FALSE)
if(test == TRUE){ return(TRUE) }
else { return(FALSE) }
}
ベクトル、行列などの場合に*apply
を使用するように変更できます。
以下は、明らかに信頼できる方法の1つです。
check.integer <- function(N){
!grepl("[^[:digit:]]", format(N, digits = 20, scientific = FALSE))
}
check.integer(3243)
#TRUE
check.integer(3243.34)
#FALSE
check.integer("sdfds")
#FALSE
このソリューションでは、科学表記法の整数も使用できます。
> check.integer(222e3)
[1] TRUE
R言語のドキュメントを読むと、_as.integer
_は、実際に整数と同等である場合よりも、数値の格納方法に関係しています。 _is.integer
_は、数値が整数として宣言されているかどうかをテストします。整数を宣言するには、その後にL
を追加します。
_> is.integer(66L)
[1] TRUE
> is.integer(66)
[1] FALSE
_
また、round
などの関数は、宣言された整数を返します。これは、x==round(x)
で実行していることです。このアプローチの問題は、実際には整数であると考えるものです。この例では、同等性のテストの精度が低くなります。
_> is.wholenumber(1+2^-50)
[1] TRUE
> check.integer(1+2^-50)
[1] FALSE
_
そのため、アプリケーションによっては、その方法で問題が発生する可能性があります。
何らかのエラー耐性を組み込む必要はないと思われます。すべての整数が整数として入力された場合は必要ありませんが、精度を失う算術演算の結果として来る場合があります。例えば:
> 2/49*49
[1] 2
> check.integer(2/49*49)
[1] FALSE
> is.wholenumber(2/49*49)
[1] TRUE
これはRの弱点ではなく、すべてのコンピューターソフトウェアには精度の限界があることに注意してください。
_Hmisc::spss.get
_から:
_all(floor(x) == x, na.rm = TRUE)
_
マシンの精度の問題を「バイパス」するため、はるかに安全なオプション、IMHO。 is.integer(floor(1))
を試すと、FALSE
が得られます。ところで、整数は_.Machine$integer.max
_値(デフォルトでは2147483647)よりも大きい場合、整数として保存されないため、_integer.max
_値を変更するか、代替チェックを行います...
次のような単純なif条件を使用できます。
if(round(var) != var)
Rでは、数値が数値であるか整数であるかは、クラス関数によって決定できます。通常、すべての数値は数値として保存され、数値を整数として明示的に定義するには、数値の後に「L」を指定する必要があります。
例:
x <-1
クラス(x)
[1]「数値」
x <-1L
クラス(x)
[1]「整数」
これが必要だったことを願っています。ありがとう:)
[更新] =============================================== ===============
以下の[古い]回答を参照して、すべての数値を単一の原子ベクトルに入れたために機能することを発見しました。それらの1つはキャラクターだったので、すべてがキャラクターになります。
リストを使用する場合(したがって、強制は発生しません)、テストはすべてパスしますが、1つは1/(1 - 0.98)
で、numeric
のままです。これは、tol
パラメーターがデフォルトで_100 * .Machine$double.eps
_であり、その数が_50
_から遠く、その2倍より少し小さいためです。したがって、基本的に、この種の数値については、許容範囲を決定するためにhaveを持っています!
すべてのテストをTRUE
にしたい場合は、assertive::is_whole_number(x, tol = 200 * .Machine$double.eps)
できます
とにかく、IMOの断定的が最善の解決策であることを確認します。
以下は、この[更新]の前提です。
_expect_trues_c <- c(
cl = sqrt(2)^2,
pp = 9.0,
t = 1 / (1 - 0.98),
ar0 = 66L,
ar1 = 66,
ar2 = 1 + 2^-50,
v = 222e3,
w1 = 1e4,
w2 = 1e5,
v2 = "1000000000000000000000000000000000001",
an = 2 / 49 * 49,
ju1 = 1e22,
ju2 = 1e24,
al = floor(1),
v5 = 1.0000000000000001 # this is under machine precision!
)
str(expect_trues_c)
#> Named chr [1:15] "2" "9" "50" "66" "66" "1" "222000" "10000" "1e+05" ...
#> - attr(*, "names")= chr [1:15] "cl" "pp" "t" "ar0" ...
assertive::is_whole_number(expect_trues_c)
#> Warning: Coercing expect_trues_c to class 'numeric'.
#> 2 9 50
#> TRUE TRUE TRUE
#> 66 66 1
#> TRUE TRUE TRUE
#> 222000 10000 100000
#> TRUE TRUE TRUE
#> 1e+36 2 1e+22
#> TRUE TRUE TRUE
#> 9.9999999999999998e+23 1 1
#> TRUE TRUE TRUE
expect_trues_l <- list(
cl = sqrt(2)^2,
pp = 9.0,
t = 1 / (1 - 0.98),
ar0 = 66L,
ar1 = 66,
ar2 = 1 + 2^-50,
v = 222e3,
w1 = 1e4,
w2 = 1e5,
v2 = "1000000000000000000000000000000000001",
an = 2 / 49 * 49,
ju1 = 1e22,
ju2 = 1e24,
al = floor(1),
v5 = 1.0000000000000001 # this is under machine precision!
)
str(expect_trues_l)
#> List of 15
#> $ cl : num 2
#> $ pp : num 9
#> $ t : num 50
#> $ ar0: int 66
#> $ ar1: num 66
#> $ ar2: num 1
#> $ v : num 222000
#> $ w1 : num 10000
#> $ w2 : num 1e+05
#> $ v2 : chr "1000000000000000000000000000000000001"
#> $ an : num 2
#> $ ju1: num 1e+22
#> $ ju2: num 1e+24
#> $ al : num 1
#> $ v5 : num 1
assertive::is_whole_number(expect_trues_l)
#> Warning: Coercing expect_trues_l to class 'numeric'.
#> There was 1 failure:
#> Position Value Cause
#> 1 3 49.999999999999957 fractional
assertive::is_whole_number(expect_trues_l, tol = 200 * .Machine$double.eps)
#> Warning: Coercing expect_trues_l to class 'numeric'.
#> 2.0000000000000004 9 49.999999999999957
#> TRUE TRUE TRUE
#> 66 66 1.0000000000000009
#> TRUE TRUE TRUE
#> 222000 10000 100000
#> TRUE TRUE TRUE
#> 1e+36 1.9999999999999998 1e+22
#> TRUE TRUE TRUE
#> 9.9999999999999998e+23 1 1
#> TRUE TRUE TRUE
expect_falses <- list(
bb = 5 - 1e-8,
pt1 = 1.0000001,
pt2 = 1.00000001,
v3 = 3243.34,
v4 = "sdfds"
)
str(expect_falses)
#> List of 5
#> $ bb : num 5
#> $ pt1: num 1
#> $ pt2: num 1
#> $ v3 : num 3243
#> $ v4 : chr "sdfds"
assertive::is_whole_number(expect_falses)
#> Warning: Coercing expect_falses to class 'numeric'.
#> Warning in as.this_class(x): NAs introduced by coercion
#> There were 5 failures:
#> Position Value Cause
#> 1 1 4.9999999900000001 fractional
#> 2 2 1.0000001000000001 fractional
#> 3 3 1.0000000099999999 fractional
#> 4 4 3243.3400000000001 fractional
#> 5 5 <NA> missing
assertive::is_whole_number(expect_falses, tol = 200 * .Machine$double.eps)
#> Warning: Coercing expect_falses to class 'numeric'.
#> Warning: NAs introduced by coercion
#> There were 5 failures:
#> Position Value Cause
#> 1 1 4.9999999900000001 fractional
#> 2 2 1.0000001000000001 fractional
#> 3 3 1.0000000099999999 fractional
#> 4 4 3243.3400000000001 fractional
#> 5 5 <NA> missing
_
reprexパッケージ (v0.3.0)によって2019-07-23に作成
[OLD] ============================================== ==================
IMOの最良の解決策は、assertive
パッケージ(現時点では、このスレッドのすべての正と負の例を解決する)から得られます。
_are_all_whole_numbers <- function(x) {
all(assertive::is_whole_number(x), na.rm = TRUE)
}
are_all_whole_numbers(c(
cl = sqrt(2)^2,
pp = 9.0,
t = 1 / (1 - 0.98),
ar0 = 66L,
ar1 = 66,
ar2 = 1 + 2^-50,
v = 222e3,
w1 = 1e4,
w2 = 1e5,
v2 = "1000000000000000000000000000000000001",
an = 2 / 49 * 49,
ju1 = 1e22,
ju2 = 1e24,
al = floor(1),
v5 = 1.0000000000000001 # difference is under machine precision!
))
#> Warning: Coercing x to class 'numeric'.
#> [1] TRUE
are_all_not_whole_numbers <- function(x) {
all(!assertive::is_whole_number(x), na.rm = TRUE)
}
are_all_not_whole_numbers(c(
bb = 5 - 1e-8,
pt1 = 1.0000001,
pt2 = 1.00000001,
v3 = 3243.34,
v4 = "sdfds"
))
#> Warning: Coercing x to class 'numeric'.
#> Warning in as.this_class(x): NAs introduced by coercion
#> [1] TRUE
_
reprexパッケージ (v0.3.0)によって2019-07-23に作成
独自の関数を作成したくない場合は、 _check.integer
_ from packageinstallrを試してください。現在、 使用 VitoshKaの答え。
また、パッケージからの check.numeric(v, only.integer=TRUE)
varhandleを試してみてください。これにはベクトル化の利点があります。