ベクトルとして、一連の数列が与えられfoo
ます。タスクは、単調に増加していることを見つけることですfoo
-すべてのアイテムが次のアイテム以下である-または単調に減少している-すべてのアイテムが次のアイテム以上である。
確かにこれはループを通して見つけることができますが、もっと創造的なアイデアはありますか?
もう1つ:確認してください
all(x == cummax(x))
また
all(x == cummin(x))
それぞれ単調に増加または減少します。cummax
よりもはるかdiff
に高速であり、メモリの使用量も少ないようです。
> x <- seq_len(1e7)
> system.time(all(x == cummax(x)))
user system elapsed
0.11 0.00 0.11
> system.time(all(diff(x) >= 0))
user system elapsed
0.47 0.13 0.59
> x <- seq_len(1e8)
> system.time(all(x == cummax(x)))
user system elapsed
1.06 0.09 1.16
> system.time(all(diff(x) >= 0))
Error: cannot allocate vector of size 381.5 Mb
In addition: Warning messages:
1: Reached total allocation of 1535Mb: see help(memory.size)
2: Reached total allocation of 1535Mb: see help(memory.size)
3: Reached total allocation of 1535Mb: see help(memory.size)
4: Reached total allocation of 1535Mb: see help(memory.size)
Timing stopped at: 1.96 0.38 2.33
違いを計算するよりも高速な数値を比較するだけでよいため、なぜcummax
よりも高速であるかについての私の賭けです。diff
編集:あなたの(アリの)要求に応じて、あなたの答えを含む追加のテスト(私は現在別のマシンから実行しているため、次の結果を上記の結果と比較しないでください)
> x <- seq_len(1e7)
> system.time(x == cummax(x))
user system elapsed
0.316 0.096 0.416
> system.time(all(diff(x) >= 0))
user system elapsed
4.364 0.240 4.632
> system.time(x[-1] - x[-length(x)] >= 0)
user system elapsed
3.828 0.380 4.227
> system.time(all(x[-1] >= x[-length(x)]))
user system elapsed
2.572 0.288 2.865
1 つのオプションは、diff()
関数を使用して、ベクトル内の隣接する要素間の差を与えることです。
単調に増加する関数は、diff(x)
すべてが 0 以上になります。
f1 <- 1:10
f2 <- 10:1
> all(diff(f1) >= 0)
[1] TRUE
> all(diff(f2) >= 0)
[1] FALSE
等しいかどうかのテストは0
嫌われるかもしれませんが。< 0
を使用して比較を否定する方が良いかもしれません!
:
> all(!diff(f1) < 0)
[1] TRUE
> all(!diff(f2) < 0)
[1] FALSE
これは、すべての数値を正確に表現できるとは限らないコンピューターを使用しているためです。計算中の数値を正確に表すことができなかった (つまり、浮動小数点数) ため、実際にはゼロであるが完全にゼロではない結果を計算する場合があります。したがって、foo
が計算の結果である場合、それが 0 に等しいかどうかをテストすると、0 が 0 よりも少し大きいか小さいかという結果になる可能性があり、増加/減少関数の結果が間違っている可能性があります。
増加するバージョンの場合、次を使用できますis.unsorted()
。
x <- seq_len(1e7)
!is.unsorted(x)
> !is.unsorted(x)
[1] TRUE
これもかなり速いです:
> system.time(!is.unsorted(x))
user system elapsed
0.099 0.000 0.099
> system.time(all(x == cummax(x)))
user system elapsed
0.320 0.039 0.360
残念ながらis.unsorted()
、明示的に昇順です。これを減少状況に変換するのは少し手間がかかりますが、それでも私のシステムの他のオプションと競合します。
xx <- 1e7:1
!is.unsorted(-xx)
system.time(!is.unsorted(-xx))
> system.time(!is.unsorted(-xx))
user system elapsed
0.205 0.020 0.226
> system.time(all(xx == cummin(xx)))
user system elapsed
0.356 0.088 0.444
そしてさらに大きな問題に…
x <- 1:1e8
xx <- 1e8:1
system.time(!is.unsorted(x))
system.time(all(x == cummax(x)))
system.time(!is.unsorted(-xx))
system.time(all(xx == cummin(xx)))
> system.time(!is.unsorted(x))
user system elapsed
1.019 0.000 1.019
> system.time(all(x == cummax(x)))
user system elapsed
3.255 0.354 3.608
> system.time(!is.unsorted(-xx))
user system elapsed
2.089 0.561 2.650
> system.time(all(xx == cummin(xx)))
user system elapsed
3.318 0.395 3.713
厳密に増加するシーケンスを強制する場合は、 を参照strictly
してください?is.unsorted
。
all(diff(x)<0)
>
(必要に応じて、、、に<=
置き換えます>=
)
興味深い答えは次のとおりです。
foo = c(1, 3, 7, 10, 15)
all(foo[-1] - foo[-length(foo)] >= 0) # TRUE
foo[3] = 20
all(foo[-1] - foo[-length(foo)] >= 0) # FALSE