【问题标题】:How to use the 'sweep' function如何使用“扫一扫”功能
【发布时间】:2011-03-27 13:42:22
【问题描述】:

当我查看 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

【问题讨论】:

  • M-dx 不会复制您的结果。您回答了自己的问题。
  • apply 的唯一用法是我可以计算出的结果,类似于 t(apply(t(M), 2, "-", dx)),但这很讨厌。

标签: r statistics


【解决方案1】:

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

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

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

坦白说我也没有理解 R 文档中的定义,我只是通过查找示例了解到的。

【讨论】:

  • 稍微解释一下:STATS 似乎是这个变量的错误标签。它是FUN 的输入,用于修改矩阵中每个元素的值(在此示例中为M)。 STATS 可以是一个常量,也可以是一个大小与所选MARGIN 大小匹配的列表/向量/等。我想。
  • 我怀疑他们使用了参数STATS,因为该函数被设计为一种缩放工具,您减去colMeans并除以列的标准偏差(scale()函数在“见也”文档的一部分)。但事实上,它不必是任何类型的统计数据。我猜这就是 R 文档具有误导性的原因。
【解决方案2】:

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'在sweep函数调用中代表什么?
  • 第二个参数是被操作的边距,类似于apply。在这里,2 表示每行评估 STAT。在应用中,它是相反的(2 适用于列)。例如。 sweep(matrix(1:50, nrow = 5), 2, 1:10, "-")
  • 我不知道他们为什么这样做,但这是真的,column=1 row=2
【解决方案3】:

这个问题有点老了,但由于我最近遇到了这个问题,所以可以在统计函数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 = "-",这让我困惑了一阵子。

【讨论】:

    【解决方案4】:

    您可以使用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 分数(mean=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
    

    【讨论】:

    • @BenBolker 正如我在答案中提到的那样,因为我可能想根据参考平均值和 sd 来缩放项目,而不是当前样本本身的平均值和 sd。当您处理在大样本中进行管理和标准化的测试时,就会发生这种情况,并且您希望根据它们的统计数据来标准化您的小样本分数。
    【解决方案5】:

    一种用途是计算数组的加权总和。其中rowSumscolSums 可以假定为'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)
    

    【讨论】:

      猜你喜欢
      • 2018-12-16
      • 1970-01-01
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 2012-02-07
      • 2022-10-25
      • 2021-10-29
      • 1970-01-01
      相关资源
      最近更新 更多