web-dev-qa-db-ja.com

「スイープ」機能の使用方法

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をどのように使用するかです。

93
doug

sweep()は通常、行列を行または列で操作するときに使用され、操作の他の入力は行/列ごとに異なる値です。行または列のどちらで操作するかは、apply()のようにMARGINによって定義されます。 「他の入力」と呼ばれるものに使用される値は、STATSによって定義されます。したがって、各行(または列)に対して、STATSから値を取得し、FUNによって定義された操作で使用します。

たとえば、定義したマトリックスの1行目に1、2行目に2などを追加する場合、次のようにします。

sweep (M, 1, c(1: 4), "+")

私は率直に言ってRのドキュメントの定義も理解していませんでした。私はちょうど例を調べて学びました。

75
Daniele Merico

以下に示すように、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引数を変更すると、他の操作が可能になります。

15
Brad Horn

この質問は少し古いですが、最近この問題に直面したため、スイープの典型的な使用法は、重み付き共分散行列の計算に使用される統計関数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 = "-"を使用していますが、しばらく混乱していました。

6
James King

用途の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)
2
dardisco

sweep関数を使用して、次のコードのようにデータをスケーリングおよびセンタリングできます。 meanssdsはここでは任意です(それらに基づいてデータを標準化する参照値がある場合があります)。

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
0
Ehsan88