如何使用“扫描”功能


100

当我查看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取决于传入的函数。

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在自己的代码中使用。


2
M-dx不复制您的结果。你是在自问自答。
约翰

apply我可以得出此结果的唯一用法是类似的东西t(apply(t(M), 2, "-", dx)),但这很讨厌。
肯·威廉姆斯

Answers:


84

sweep()通常在按行或按列操作矩阵时使用,并且该操作的其他输入对于每个行/列都是不同的值。与一样,是按行还是按列由MARGIN定义apply()。我所谓的“另一个输入”所使用的值由STATS定义。因此,对于每一行(或每一列),您将从STATS中获取一个值并用于FUN定义的操作中。

例如,如果要在定义的矩阵的第一行中添加1,在第二行中添加2,依此类推,则可以执行以下操作:

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

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


2
稍微解释一下:STATS这个变量似乎是一个不好的标签。它是输入的输入FUN,用于修改矩阵中每个元素的值(M在本示例中为)。STATS可以是常量,也可以是大小与所选的大小匹配的列表/向量/等MARGIN。我认为。
罗兰

16

scan()对于系统地逐列或逐行处理大型矩阵非常有用,如下所示:

> 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

这个问题有点老了,但是由于我最近遇到了这个问题,通常可以在stats函数的源代码中找到sweep的典型用法,该函数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

一种用途是在计算数组的加权和时。在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)

0

您可以使用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,标准差= 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

1
我在答案中提到了@BenBolker,因为我可能想根据参考均值和sd(而不是当前样本本身的均值和sd)来缩放项目。当您处理在大样本中进行管理和标准化的测试,并且要根据小样本的统计信息对它们进行标准化时,就会发生这种情况。
Ehsan88
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.