2010-08-09 90 views
68

當我看R軟件包的來源時,我看到功能掃描經常使用。 有些時候,如果一個簡單的函數在其他時候已經足夠(例如「應用」), 就可以使用它,但不可能確切知道它在做什麼,而不需要花費相當多的時間來遍歷它所在的代碼塊。如何使用R功能'掃描'

我可以使用更簡單的函數重現掃描效果的事實表明我不明白掃描的核心用例,而且這個函數經常使用的事實表明它非常有用。

上下文:

是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 

正如你所看到的,方法簽名類似於「應用」雖然「掃」需要 一個參數,「STATS」。

另一個關鍵的區別是,「掃描」返回相同的形狀作爲輸入數組的數組,而由「應用」返回的結果取決於傳入的功能。

在動作掃

# 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 

所以總之,我要找的是一個典型的用例或兩個

請不要背誦或鏈接到R文檔,郵件列表或任何「主要」R來源 - 假設我已經閱讀過它們。我感興趣的是經驗豐富的R程序員/分析師在自己的代碼中使用掃描

+2

M-DX不復制您的結果。你是在自問自答。 – John 2010-08-10 00:59:59

+0

我可以計算出這個結果的'apply'的唯一用法就像't(apply(t(M),2, - - ,,dx))',但這很糟糕。 – 2011-05-04 14:32:48

回答

56

sweep通常用於按行或按列操作矩陣,並且操作的另一個輸入對於每個行/列是不同的值。無論您是按行還是按列操作,均由MARGIN定義,適用。用於我稱爲「其他輸入」的值由STATS定義。 因此,對於每一行(或列),您將從STATS中獲取一個值並將其用於由FUN定義的操作。

舉例來說,如果你想加1,第1行,2〜2次,等等......你所定義的矩陣,你會做什麼:

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

坦白說,我不明白在R文檔中定義,我只是通過查找示例來了解。

+0

稍微解釋一下:'STATS'似乎是這個變量的一個不好的標籤。這是「FUN」的輸入,用於修改矩陣中每個元素的值(在本例中爲「M」)。 STATS可以是一個常量,也可以是一個大小與所選MARGIN大小相匹配的列表/矢量等。我認爲。 – Roland 2017-12-28 03:54:24

14

掃描()可以是大的用於系統性操縱由行通過柱大矩陣任一列或行,如下所示:

> 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論點,其他操作是可能的。

6

這個問題有點舊,但由於我最近遇到過這個問題,典型的掃描使用可以在用於計算加權協方差矩陣的統計函數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

您可以使用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

如果你要擴展和居中,你爲什麼不使用'scale()'......? – 2014-09-22 22:25:11

+1

@BenBolker正如我在答案中提到的那樣,因爲我可能想根據參考均值和sd來縮放項目,而不是當前樣本本身的均值和sd。當您處理在大樣本中進行管理和標準化的測試時,會出現這種情況,並且您希望根據統計信息將小樣本分數標準化。 – ehsan88 2014-09-23 14:57:53

1

的一個用途是,當你計算加權資金用於數組。其中rowSumscolSums可以假定爲'權重= 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)