Transpose関数の実行速度が気になったので検証してみました。
同じ処理をFor文で全要素代入して再現した方法との速度比較で検証します。
一応経緯を説明しますと、Transpose関数には要素数65,536という上限が存在します。
この上限を超えた際に自作関数で対応する必要があるのですが、
「その関数を使うと遅くなってしまわないか?」
という検証を行ったものです。
Transpose関数の上限仕様についてはこちらの記事をご覧ください。
www.limecode.jp
さて検証結果ですが、お忙しい方向けに結論を先に書いておくと、
- 愚直に配列に代入した方が高速
- ただしどちらも十分高速なため誤差の範囲と捉えて良い
というのが結論でした。
検証内容を読みたい方は、以下読み進めてみてください。
一次元配列を二次元配列にする用途で使用する場合
一次元配列を縦方向にセル出力する際に↓のようなコードを使います。
始点セル.Resize(要素数, 1).Value = WorksheetFunction.Transpose(配列)
これをTransposeの上限65,536行以降で行う必要が出た際に、
自作関数にすることでTransposeより遅くなってしまわないかを検証します。
Sub Transpose関数vs愚直に配列代入_一次元配列→二次元配列() ' 50000連番の配列でテスト Dim Arr(1 To 50000) Dim i As Long For i = LBound(Arr) To UBound(Arr) Arr(i) = i Next Dim 開始時刻 As Double, 終了時刻 As Double 開始時刻 = Timer Dim tmp For i = 1 To 500 ' どちらかのコメントアウトを解いて実行 'tmp = WorksheetFunction.Transpose(Arr) tmp = GetArray一次元配列→n行1列の二次元配列(Arr) Next 終了時刻 = Timer Debug.Print "このマクロの実行時間:" & (終了時刻 - 開始時刻) & "秒" End Sub Function GetArray一次元配列→n行1列の二次元配列(Arr As Variant) As Variant Dim 生成配列() ReDim 生成配列(LBound(Arr) To UBound(Arr), 1 To 1) Dim i As Long For i = LBound(Arr) To UBound(Arr) 生成配列(i, 1) = Arr(i) Next GetArray一次元配列→n行1列の二次元配列 = 生成配列 End Function
◆ 検証結果
| Transpose関数 | 2.20703125秒 |
|---|---|
| 愚直な配列代入 | 1.208984375秒 |
実行時間を見ると、愚直に配列に代入した方が早いという結果になりました。
といっても50,000要素の変換処理を500回やってこの処理時間です。
よほどの規模のデータを相手にしない限りは、
「どちらも十分高速で差は誤差の範囲」と捉えて良さそうですね。
一次元配列→二次元配列の変換コードにおいては、
- Transpose上限対応関数を作ったら常にそれを使ってOK
- 自作関数の無い状況下であればTranspose関数で十分高速
と結論しておきます。
二次元配列の行列入れ替えを実行する場合
続いて本来のTranspose関数の使い方になります。
こちらの速度比較は以下の通りでした。
Sub Transpose関数vs愚直に配列代入_二次元配列行列変換() ' 1000×1000の配列でテスト Dim Arr As Variant Arr = Worksheets("データ").Range("A1").Resize(10000, 20) Dim 開始時刻 As Double, 終了時刻 As Double 開始時刻 = Timer Dim i As Long, tmp For i = 1 To 100 'tmp = WorksheetFunction.Transpose(Arr) tmp = 愚直に代入するTranspose(Arr) Next 終了時刻 = Timer Debug.Print "このマクロの実行時間:" & (終了時刻 - 開始時刻) & "秒" End Sub Function 愚直に代入するTranspose(Arr As Variant) As Variant Dim 生成配列() ReDim 生成配列(LBound(Arr, 2) To UBound(Arr, 2), LBound(Arr, 1) To UBound(Arr, 1)) Dim i As Long Dim j As Long For i = LBound(Arr, 2) To UBound(Arr, 2) For j = LBound(Arr, 1) To UBound(Arr, 1) 生成配列(i, j) = Arr(j, i) Next Next 愚直に代入するTranspose = 生成配列 End Function
◆ 検証結果
| Transpose関数 | 1.6199951171875秒 |
|---|---|
| 愚直な配列代入 | 1.0469970703125秒 |
こちらも愚直に配列に代入した方が早いという結果でしたね。
といっても10000×20の配列を100回変換してこれなので、
一次元配列変換と同じく「どちらも十分高速で差は誤差の範囲」です。
- Transpose上限対応関数を作ったら常にそれを使ってOK
- 自作関数の無い状況下であればTranspose関数で十分高速
という結論で変更ありません。
以上がTranspose関数 vs 愚直な配列代入の速度比較結果でした。
どちらも十分高速ですので、速度は気にする必要はなさそうです。
- Transpose関数の要素数上限65,536への対応
- その他データ型(Transposeは数値がDouble型限定)への対応
あたりに対応する場合は自作関数を用意し、
それ以外の場合はTranspose関数をそのまま使ってOKですね。