Cómo utilizar la función 'barrer'

100

Cuando miro la fuente de los paquetes R, veo la función que se sweepusa con bastante frecuencia. A veces se usa cuando una función más simple hubiera sido suficiente (por ejemplo, apply), otras veces, es imposible saber exactamente lo que está haciendo sin dedicar una buena cantidad de tiempo a recorrer el bloque de código en el que se encuentra.

El hecho de que pueda reproducir sweepel efecto usando una función más simple sugiere que no entiendo sweeplos casos de uso principales, y el hecho de que esta función se use con tanta frecuencia sugiere que es bastante útil.

El contexto:

sweepes una función en la biblioteca estándar de R; sus argumentos son:

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 se puede ver, los argumentos son similares a applypesar de que sweeprequiere un parámetro más, STATS.

Otra diferencia clave es que sweepdevuelve una matriz de la misma forma que la matriz de entrada, mientras que el resultado devuelto por applydepende de la función pasada.

sweep en acción:

# 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

Entonces, en resumen, lo que estoy buscando es un caso de uso ejemplar o dos sweep.

Por favor, no recite ni enlace a la Documentación de R, las listas de correo ni ninguna de las fuentes de R "primarias", suponga que las he leído. Lo que me interesa es cómo los programadores / analistas experimentados de R utilizan sweepen su propio código.

doug
fuente
2
M-dx no replica su resultado. Ha respondido a su propia pregunta.
Juan
El único uso de applyeso que puedo averiguar para este resultado es algo así t(apply(t(M), 2, "-", dx)), pero eso es bastante desagradable.
Ken Williams

Respuestas:

84

sweep()se utiliza normalmente cuando se opera una matriz por fila o por columna, y la otra entrada de la operación es un valor diferente para cada fila / columna. Si opera por fila o columna está definido por MARGIN, como para apply(). Los valores usados ​​para lo que llamé "la otra entrada" están definidos por STATS. Entonces, para cada fila (o columna), tomará un valor de STATS y lo usará en la operación definida por FUN.

Por ejemplo, si desea agregar 1 a la 1ra fila, 2 a la 2da, etc. de la matriz que definió, hará:

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

Francamente, tampoco entendí la definición en la documentación de R, solo aprendí buscando ejemplos.

Daniele Merico
fuente
2
parafraseando un poco: STATSparece ser una mala etiqueta para esta variable. Es una entrada FUNque se usa para modificar el valor de cada elemento en la matriz ( M, en este ejemplo). STATSpuede ser una constante o una lista / vector / etc. de un tamaño que coincida con el tamaño elegido MARGIN. Yo creo que.
Roland
16

sweep () puede ser excelente para manipular sistemáticamente una matriz grande, ya sea columna por columna o fila por fila, como se muestra a continuación:

> 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

Por supuesto, este ejemplo es simple, pero cambiando el argumento STATS y FUN, son posibles otras manipulaciones.

Brad Horn
fuente
6

Esta pregunta es un poco antigua, pero como recientemente me enfrenté a este problema, se puede encontrar un uso típico de barrido en el código fuente de la función de estadísticas cov.wt, que se utiliza para calcular matrices de covarianza ponderadas. Estoy mirando el código en R 3.0.1. Aquí sweepse utiliza para restar las medias de las columnas antes de calcular la covarianza. En la línea 19 del código se deriva el vector de centrado:

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

y en la línea 54 se elimina de la matriz

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

El autor del código está usando el valor predeterminado FUN = "-", lo que me confundió por un tiempo.

James King
fuente
3

Un uso es cuando se calculan sumas ponderadas para una matriz. Donde rowSumso colSumsse puede suponer que significa 'pesos = 1', sweepse puede usar antes de esto para dar un resultado ponderado. Esto es particularmente útil para matrices con> = 3 dimensiones.

Esto surge, por ejemplo, al calcular una matriz de covarianza ponderada según el ejemplo de @James King.

Aquí hay otro basado en un proyecto actual:

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
fuente
0

Puede usar la sweepfunción para escalar y centrar datos como el siguiente código. Tenga en cuenta que meansy sdsson arbitrarios aquí (es posible que tenga algunos valores de referencia que desee estandarizar los datos en función de ellos):

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 convierte las puntuaciones brutas en puntuaciones T (con media = 50 y 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
Ehsan88
fuente
1
@BenBolker como mencioné en la respuesta, porque es posible que desee escalar los elementos de acuerdo con una media de referencia y sd, no la media y sd de la muestra actual en sí. Ocurre cuando se trata de pruebas que se administran y estandarizan en muestras grandes, y desea estandarizar la puntuación de la muestra pequeña de acuerdo con sus estadísticas.
Ehsan88