Rパッケージのソースを見ると、sweep
という関数が頻繁に使用されていることがわかります。より簡単な関数で十分な場合に使用されることもあります(例:apply
)、他の場合は、コードブロックをステップスルーするためにかなりの時間を費やさずに、それが何をしているかを正確に知ることは不可能です。
単純な関数を使用してsweep
の効果を再現できるという事実は、sweep
のコアユースケースを理解していないことを示唆しており、この関数が頻繁に使用されるという事実は、非常に有用であることを示唆しています。
コンテキスト:
sweep
はRの標準ライブラリの関数です。引数は次のとおりです。
sweep(x, MARGIN, STATS, FUN="-", check.margin=T, ...)
# x is the data
# STATS refers to the summary statistics which you wish to 'sweep out'
# FUN is the function used to carry out the sweep, "-" is the default
ご覧のとおり、apply
にはもう1つのパラメーターsweep
が必要ですが、引数はSTATS
に似ています。
もう1つの重要な違いは、sweep
が入力配列として同じ形状の配列を返すのに対し、apply
によって返される結果は渡される関数に依存することです。
sweep
アクション:
# e.g., use 'sweep' to express a given matrix in terms of distance from
# the respective column mean
# create some data:
M = matrix( 1:12, ncol=3)
# calculate column-wise mean for M
dx = colMeans(M)
# now 'sweep' that summary statistic from M
sweep(M, 2, dx, FUN="-")
[,1] [,2] [,3]
[1,] -1.5 -1.5 -1.5
[2,] -0.5 -0.5 -0.5
[3,] 0.5 0.5 0.5
[4,] 1.5 1.5 1.5
要するに、私が探しているのは、sweep
の典型的なユースケースまたは2つです。
Rドキュメンテーション、メーリングリスト、または「主要な」Rソースのいずれかを暗記またはリンクしないでください。私がそれらを読んだと仮定します。私が興味を持っているのは、経験豊富なRプログラマー/分析者が自分のコードでsweep
をどのように使用するかです。
sweep()
は通常、行列を行または列で操作するときに使用され、操作の他の入力は行/列ごとに異なる値です。行または列のどちらで操作するかは、apply()
のようにMARGINによって定義されます。 「他の入力」と呼ばれるものに使用される値は、STATSによって定義されます。したがって、各行(または列)に対して、STATSから値を取得し、FUNによって定義された操作で使用します。
たとえば、定義したマトリックスの1行目に1、2行目に2などを追加する場合、次のようにします。
sweep (M, 1, c(1: 4), "+")
私は率直に言ってRのドキュメントの定義も理解していませんでした。私はちょうど例を調べて学びました。
以下に示すように、sweep()は、列ごと、または行ごとに大きなマトリックスを体系的に操作するのに最適です。
> print(size)
Weight Waist Height
[1,] 130 26 140
[2,] 110 24 155
[3,] 118 25 142
[4,] 112 25 175
[5,] 128 26 170
> sweep(size, 2, c(10, 20, 30), "+")
Weight Waist Height
[1,] 140 46 170
[2,] 120 44 185
[3,] 128 45 172
[4,] 122 45 205
[5,] 138 46 200
確かに、この例は単純ですが、STATSおよびFUN引数を変更すると、他の操作が可能になります。
この質問は少し古いですが、最近この問題に直面したため、スイープの典型的な使用法は、重み付き共分散行列の計算に使用される統計関数cov.wt
のソースコードにあります。 R 3.0.1のコードを見ています。ここで、sweep
は、共分散を計算する前に列平均を減算するために使用されます。コードの19行目で、センタリングベクトルが導出されます。
center <- if (center)
colSums(wt * x)
else 0
そして、54行目では、マトリックスから掃き出されます
x <- sqrt(wt) * sweep(x, 2, center, check.margin = FALSE)
コードの作成者はデフォルト値FUN = "-"
を使用していますが、しばらく混乱していました。
用途の1つは、配列のweighted sumsを計算する場合です。 rowSums
またはcolSums
が 'weights = 1'を意味すると想定できる場合、sweep
をこれの前に使用して重み付き結果を得ることができます。これは、3次元以上の配列で特に役立ちます。
これは、例えば@James Kingの例に従って加重共分散行列を計算するとき。
現在のプロジェクトに基づいた別の例を次に示します。
set.seed(1)
## 2x2x2 array
a1 <- array(as.integer(rnorm(8, 10, 5)), dim=c(2, 2, 2))
## 'element-wise' sum of matrices
## weights = 1
rowSums(a1, dims=2)
## weights
w1 <- c(3, 4)
## a1[, , 1] * 3; a1[, , 2] * 4
a1 <- sweep(a1, MARGIN=3, STATS=w1, FUN="*")
rowSums(a1, dims=2)
sweep
関数を使用して、次のコードのようにデータをスケーリングおよびセンタリングできます。 means
とsds
はここでは任意です(それらに基づいてデータを標準化する参照値がある場合があります)。
df=matrix(sample.int(150, size = 100, replace = FALSE),5,5)
df_means=t(apply(df,2,mean))
df_sds=t(apply(df,2,sd))
df_T=sweep(sweep(df,2,df_means,"-"),2,df_sds,"/")*10+50
このコードは、未加工のスコアをTスコアに変換します(平均= 50およびsd = 10):
> df
[,1] [,2] [,3] [,4] [,5]
[1,] 109 8 89 69 15
[2,] 85 13 25 150 26
[3,] 30 79 48 1 125
[4,] 56 74 23 140 100
[5,] 136 110 112 12 43
> df_T
[,1] [,2] [,3] [,4] [,5]
[1,] 56.15561 39.03218 57.46965 49.22319 40.28305
[2,] 50.42946 40.15594 41.31905 60.87539 42.56695
[3,] 37.30704 54.98946 47.12317 39.44109 63.12203
[4,] 43.51037 53.86571 40.81435 59.43685 57.93136
[5,] 62.59752 61.95672 63.27377 41.02349 46.09661