Como usar a função 'varredura'

100

Quando eu olho para a origem dos Pacotes R, vejo a função sweepusada com bastante frequência. Às vezes, é usado quando uma função mais simples seria suficiente (por exemplo, apply), outras vezes, é impossível saber exatamente o que está fazendo sem gastar um bom tempo para percorrer o bloco de código em que está.

O fato de eu poder reproduzir sweepo efeito de usando uma função mais simples sugere que não entendo sweepos principais casos de uso de, e o fato de que essa função é usada com tanta frequência sugere que é bastante útil.

O contexto:

sweepé uma função na biblioteca padrão de R; seus argumentos são:

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

Como você pode ver, os argumentos são semelhantes a applyembora sweeprequer mais um parâmetro STATS,.

Outra diferença importante é que sweepretorna um array da mesma forma que o array de entrada, enquanto o resultado retornado por applydepende da função passada.

sweep em ação:

# 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

Resumindo, o que estou procurando é um ou dois casos de uso exemplares sweep.

Por favor, não recite ou crie links para a Documentação R, listas de discussão ou qualquer uma das fontes 'primárias' de R - suponha que eu as li. Estou interessado em como programadores / analistas experientes em R usam sweepem seu próprio código.

doug
fonte
2
M-dx não replica seu resultado. você respondeu sua própria pergunta.
John
O único uso applyque posso descobrir para este resultado é algo como t(apply(t(M), 2, "-", dx)), mas isso é muito desagradável.
Ken Williams

Respostas:

84

sweep()é normalmente usado quando você opera uma matriz por linha ou coluna, e a outra entrada da operação é um valor diferente para cada linha / coluna. Se você opera por linha ou coluna é definido por MARGIN, assim como por apply(). Os valores usados ​​para o que chamei de "a outra entrada" são definidos por STATS. Assim, para cada linha (ou coluna), você pegará um valor de STATS e usará na operação definida por FUN.

Por exemplo, se você quiser adicionar 1 à 1ª linha, 2 à 2ª, etc. da matriz que definiu, você fará:

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

Francamente, também não entendi a definição na documentação do R, apenas aprendi procurando exemplos.

Daniele Merico
fonte
2
parafraseando um pouco: STATSparece ser um rótulo ruim para essa variável. É uma entrada FUNque é usada para modificar o valor de cada elemento da matriz ( Mneste exemplo). STATSpode ser uma constante ou uma lista / vetor / etc de um tamanho correspondente ao tamanho do escolhido MARGIN. Eu acho que.
Roland
16

sweep () pode ser ótimo para manipular sistematicamente uma grande matriz coluna por coluna ou linha por linha, conforme mostrado abaixo:

> 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

Concedido, este exemplo é simples, mas alterando o argumento STATS e FUN, outras manipulações são possíveis.

Brad Horn
fonte
6

Esta questão é um pouco antiga, mas como recentemente enfrentei esse problema, um uso típico de varredura pode ser encontrado no código-fonte da função de estatísticas cov.wt, usada para calcular matrizes de covariância ponderada. Estou olhando o código em R 3.0.1. Aqui sweepé usado para subtrair as médias das colunas antes de calcular a covariância. Na linha 19 do código, o vetor de centralização é derivado:

 center <- if (center) 
        colSums(wt * x)
    else 0

e na linha 54 é varrido para fora da matriz

x <- sqrt(wt) * sweep(x, 2, center, check.margin = FALSE)

O autor do código está usando o valor padrão FUN = "-", o que me confundiu por um tempo.

James King
fonte
3

Um uso é quando você está computando somas ponderadas para um array. Onde rowSumsou colSumspode ser assumido como significando 'pesos = 1', sweeppode ser usado antes disso para fornecer um resultado ponderado. Isso é particularmente útil para arrays com> = 3 dimensões.

Isso surge, por exemplo, ao calcular uma matriz de covariância ponderada conforme o exemplo de @James King.

Aqui está outro baseado em um projeto atual:

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)
dardisco
fonte
0

Você pode usar a sweepfunção para dimensionar e centralizar dados como o código a seguir. Observe que meanse sdssão arbitrários aqui (você pode ter alguns valores de referência que deseja padronizar os dados com base neles):

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

Este código converte pontuações brutas em pontuações T (com média = 50 e dp = 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
Ehsan88
fonte
1
@BenBolker como mencionei na resposta, porque posso querer dimensionar os itens de acordo com uma média de referência e dp, não a média e dp da própria amostra atual. Isso ocorre quando você lida com testes que são administrados e padronizados em grandes amostras e deseja padronizar a pontuação de sua pequena amostra de acordo com suas estatísticas.
Ehsan88