Come utilizzare la funzione "sweep"


100

Quando guardo l'origine di R Packages, vedo la funzione sweepusata abbastanza spesso. A volte viene utilizzato quando una funzione più semplice sarebbe bastata (ad esempio apply), altre volte, è impossibile sapere esattamente cosa sta facendo senza spendere una discreta quantità di tempo per passare attraverso il blocco di codice in cui si trova.

Il fatto che io possa riprodurre sweepl'effetto di usando una funzione più semplice suggerisce che non capisco sweepi casi d'uso principali, e il fatto che questa funzione sia usata così spesso suggerisce che sia abbastanza utile.

Il contesto:

sweepè una funzione nella libreria standard di R; i suoi argomenti sono:

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

Come si può vedere, gli argomenti sono simili a applyse sweeprichiede un altro parametro, STATS.

Un'altra differenza fondamentale è che sweeprestituisce un array della stessa forma dell'array di input, mentre il risultato restituito da applydipende dalla funzione passata.

sweep in azione:

# 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

Quindi, in sintesi, quello che sto cercando è un caso d'uso esemplare o due per sweep.

Per favore, non recitare o linkare alla documentazione di R, alle mailing list o ad alcuna delle fonti R "primarie" - presumi che le abbia lette. Quello che mi interessa è come i programmatori / analisti R esperti usano sweepnel proprio codice.


2
M-dx non replica il tuo risultato. Hai risposto alla tua stessa domanda.
John

L'unico utilizzo applyche posso capire per questo risultato è qualcosa del genere t(apply(t(M), 2, "-", dx)), ma è piuttosto sgradevole.
Ken Williams

Risposte:


84

sweep()viene tipicamente utilizzato quando si utilizza una matrice per riga o per colonna e l'altro input dell'operazione è un valore diverso per ogni riga / colonna. Sia che si operi per riga o colonna è definito da MARGIN, come per apply(). I valori usati per quello che ho chiamato "l'altro ingresso" sono definiti da STATS. Quindi, per ogni riga (o colonna), prenderai un valore da STATS e lo utilizzerai nell'operazione definita da FUN.

Ad esempio, se vuoi aggiungere 1 alla prima riga, 2 alla seconda, ecc. Della matrice che hai definito, farai:

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

Francamente non ho capito nemmeno la definizione nella documentazione di R, ho solo imparato cercando degli esempi.


2
parafrasando un po ': STATSsembra essere una cattiva etichetta per questa variabile. È un input FUNche viene utilizzato per modificare il valore di ogni elemento nella matrice ( M, in questo esempio). STATSpuò essere una costante o una lista / vettore / etc di una dimensione corrispondente alla dimensione del scelto MARGIN. Penso.
Roland

16

sweep () può essere ottimo per manipolare sistematicamente una grande matrice colonna per colonna o riga per riga, come mostrato di seguito:

> 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

Certo, questo esempio è semplice, ma cambiando gli argomenti STATS e FUN, sono possibili altre manipolazioni.


6

Questa domanda è un po 'vecchia, ma poiché ho recentemente affrontato questo problema, un uso tipico di sweep può essere trovato nel codice sorgente della funzione stats cov.wt, utilizzato per calcolare matrici di covarianza ponderata. Sto guardando il codice nella R 3.0.1. Qui sweepviene utilizzato per sottrarre le medie delle colonne prima di calcolare la covarianza. Alla riga 19 del codice viene derivato il vettore di centratura:

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

e sulla linea 54 viene spazzato via dalla matrice

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

L'autore del codice sta usando il valore predefinito FUN = "-", che mi ha confuso per un po '.


3

Un utilizzo è quando si calcolano somme ponderate per un array. Dove rowSumso si colSumspuò presumere che significhi 'pesi = 1', sweeppuò essere usato prima di questo per fornire un risultato ponderato. Ciò è particolarmente utile per array con dimensioni> = 3.

Ciò si verifica ad esempio quando si calcola una matrice di covarianza ponderata secondo l'esempio di @James King.

Eccone un altro basato su un progetto in corso:

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

È possibile utilizzare la sweepfunzione per ridimensionare e centrare i dati come il codice seguente. Nota che meanse sdsqui sono arbitrari (potresti avere alcuni valori di riferimento su cui vuoi standardizzare i dati in base a essi):

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

Questo codice converte i punteggi grezzi in punteggi T (con media = 50 e 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

1
@ BenBolker come ho menzionato nella risposta, perché potrei voler ridimensionare gli elementi in base a una media di riferimento e sd, non la media e la sd del campione corrente stesso. Si verifica quando ti occupi di test somministrati e standardizzati in campioni di grandi dimensioni e desideri standardizzare il punteggio del tuo piccolo campione in base alle loro statistiche.
Ehsan88,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.