Jak korzystać z funkcji „sweep”

100

Kiedy patrzę na źródło pakietów R, widzę sweepczęsto używaną funkcję . Czasami jest używany, gdy prostsza funkcja wystarczyłaby (np. apply), Innym razem nie można dokładnie wiedzieć, co robi, bez poświęcania dużej ilości czasu na przejście przez blok kodu, w którym się znajduje.

Fakt, że mogę odtworzyć sweepefekt za pomocą prostszej funkcji, sugeruje, że nie rozumiem sweeppodstawowych przypadków użycia, a fakt, że ta funkcja jest używana tak często, sugeruje, że jest całkiem przydatna.

Kontekst:

sweepjest funkcją w standardowej bibliotece języka R; jej argumenty to:

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

Jak widać, argumenty są podobne apply, choć sweepwymaga jeszcze jednego parametru STATS.

Inną kluczową różnicą jest to, że sweepzwraca tablicę o tym samym kształcie co tablica wejściowa, podczas gdy wynik zwracany przez applyzależy od przekazanej funkcji.

sweep w akcji:

# 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

Podsumowując, szukam przykładowego przypadku użycia lub dwóch dla sweep.

Prosimy nie recytować ani nie łączyć się z dokumentacją R, listami mailingowymi ani żadnym z „głównych” źródeł języka R - załóżmy, że je przeczytałem. Interesuje mnie sposób, w jaki doświadczeni programiści / analitycy języka R wykorzystują sweepswój własny kod.

Doug
źródło
2
M-dx nie odtwarza twojego wyniku. Odpowiedziałeś na swoje pytanie.
Jan
Jedyne zastosowanie tego, applyjakie mogę znaleźć dla tego wyniku, to coś w rodzaju t(apply(t(M), 2, "-", dx)), ale to dość paskudne.
Ken Williams

Odpowiedzi:

84

sweep()jest zwykle używany, gdy operujesz macierzą według wiersza lub kolumny, a inne dane wejściowe operacji to inna wartość dla każdego wiersza / kolumny. To, czy operujesz wierszem, czy kolumną, definiuje MARGINES, jak w przypadku apply(). Wartości używane dla tego, co nazwałem „innym wejściem”, są zdefiniowane przez STATYSTYKI. Zatem dla każdego wiersza (lub kolumny) weźmiesz wartość ze STATS i użyjesz jej w operacji zdefiniowanej przez FUN.

Na przykład, jeśli chcesz dodać 1 do pierwszego wiersza, 2 do drugiego itd. Zdefiniowanej macierzy, zrobisz:

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

Szczerze mówiąc, również nie rozumiałem definicji w dokumentacji R, po prostu nauczyłem się, patrząc na przykłady.

Daniele Merico
źródło
2
trochę parafrazując: STATSwydaje się być złą etykietą dla tej zmiennej. Jest to dane wejściowe FUNużywane do modyfikowania wartości każdego elementu w macierzy ( Mw tym przykładzie). STATSmoże być stałą lub listą / wektorem / itp. o rozmiarze pasującym do wybranego rozmiaru MARGIN. Myślę.
Roland
16

sweep () doskonale nadaje się do systematycznego manipulowania dużą macierzą kolumna po kolumnie lub wiersz po wierszu, jak pokazano poniżej:

> 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

To prawda, ten przykład jest prosty, ale po zmianie argumentu STATS i FUN, możliwe są inne manipulacje.

Brad Horn
źródło
6

To pytanie jest trochę stare, ale ponieważ ostatnio miałem do czynienia z tym problemem, typowe użycie wobulacji można znaleźć w kodzie źródłowym funkcji stats cov.wt, używanej do obliczania ważonych macierzy kowariancji. Patrzę na kod w R 3.0.1. Tutaj sweepsłuży do odejmowania średnich kolumnowych przed obliczeniem kowariancji. W linii 19 kodu wyprowadzany jest wektor centrujący:

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

aw linii 54 jest wymieciony z macierzy

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

Autor kodu używa wartości domyślnej FUN = "-", co przez chwilę mnie zmyliło.

James King
źródło
3

Jednym z zastosowań jest obliczanie sum ważonych dla tablicy. Tam, gdzie rowSumslub colSumsmożna założyć, że oznacza „wagi = 1”, sweepmożna tego użyć wcześniej, aby uzyskać wynik ważony. Jest to szczególnie przydatne w przypadku tablic o wymiarach> = 3.

Pojawia się to np. Przy obliczaniu ważonej macierzy kowariancji, jak na przykładzie @James King.

Oto kolejny oparty na bieżącym projekcie:

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
źródło
0

Możesz użyć sweepfunkcji do skalowania i wyśrodkowywania danych, jak w poniższym kodzie. Zauważ, że meansi sdssą tutaj arbitralne (możesz mieć pewne wartości odniesienia, które chcesz ujednolicić dane na ich podstawie):

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

Ten kod konwertuje surowe wyniki na wyniki T (ze średnią = 50 i 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
źródło
1
@BenBolker, jak wspomniałem w odpowiedzi, ponieważ mogę chcieć skalować pozycje zgodnie ze średnią odniesienia i sd, a nie średnią i sd samej bieżącej próbki. Występuje, gdy masz do czynienia z testami, które są podawane i standaryzowane w dużych próbach i chcesz ustandaryzować wynik małej próbki zgodnie z ich statystykami.
Ehsan88