如何使用'扫描'功能

时间:2010-08-09 23:15:12

标签: r statistics

当我查看R Packages的源代码时,我看到函数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需要,但参数类似于sweep 还有一个参数STATS

另一个关键区别是sweep返回与输入数组相同的相同形状的数组,而apply返回的结果取决于传入的函数。< / p>

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的示范用例。

请不要背诵或链接到R文档,邮件列表或任何“主要”R源 - 假设我已阅读过它们。我感兴趣的是经验丰富的R程序员/分析师如何在他们自己的代码中使用sweep

5 个答案:

答案 0 :(得分:75)

sweep通常在按行或按列操作矩阵时使用,而操作的其他输入对于每个行/列都是不同的值。无论是按行还是列操作,都由MARGIN定义,如同申请。用于我称之为“其他输入”的值由STATS定义。 因此,对于每一行(或列),您将从STATS获取一个值并在FUN定义的操作中使用。

例如,如果你想在你定义的矩阵的第1行,第2行,第2行等中添加1,你将会这样做:

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

我坦率地不理解R文档中的定义,我只是通过查看示例来学习。

答案 1 :(得分:15)

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参数,其他操作也是可能的。

答案 2 :(得分:7)

这个问题有点陈旧,但由于我最近遇到了这个问题,因此可以在统计函数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 = "-",这让我困惑了一段时间。

答案 3 :(得分:2)

一种用途是在计算数组的加权总和时。如果colSumssweep可以假设为'权重= 1',则可以在此之前使用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) 来给出加权结果。这对于具有&gt; = 3维度的数组特别有用。

出现这种情况,例如根据@James King的例子计算加权协方差矩阵时。

这是基于当前项目的另一个:

{{1}}

答案 4 :(得分: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