Jak korzystać z funkcji "sweep"

Kiedy patrzę na źródło pakietów R, widzę często używaną funkcję sweep. Czasami jest używany, gdy wystarczyłaby prostsza funkcja (np. apply), innym razem nie można dokładnie wiedzieć, co robi bez spędzając sporo czasu, aby przejść przez blok kodu, w którym się znajduje.

Fakt, że mogę odtworzyć efekt sweep za pomocą prostszej funkcji sugeruje, że nie rozumiem podstawowych przypadków użycia i faktu, że to funkcja jest używana tak często sugeruje, że jest bardzo przydatna.

Kontekst:

sweep jest funkcją w bibliotece standardowej 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 do apply choć sweep wymaga jeszcze jeden parametr, STATS.

Kolejna kluczowa różnica polega na tym, że sweep zwraca tablicę tego samego kształtu co tablica wejściowa, podczas gdy wynik zwracany przez apply zależy od przekazanej funkcji.

sweep w działanie:

# 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, to, czego szukam, to przykładowy przypadek użycia lub dwa dla sweep.

Proszę, nie recytuj ani nie Linkuj do dokumentacji R, list dyskusyjnych,ani żadnych 'podstawowych' źródeł R -- Załóżmy, że je przeczytałem. Interesuje mnie to, jak doświadczeni programiści/analitycy r używają sweep w swoim własnym kodzie.

 105
Author: Ben Bolker, 2010-08-09

5 answers

sweep() jest zwykle używany, gdy używasz macierzy według wierszy lub kolumn, a inne wejście operacji jest inną wartością dla każdego wiersza / kolumny. To, czy operujesz wierszem czy kolumną, jest zdefiniowane przez margines, tak jak dla apply(). Wartości używane dla tego, co nazwałem "drugim wejściem" są zdefiniowane przez statystyki. Tak więc dla każdego wiersza (lub kolumny) weźmiesz wartość ze statystyk i wykorzystasz ją w operacji zdefiniowanej przez FUN.

Na przykład, jeśli chcesz dodać 1 do pierwszego wiersza, 2 do drugiego itd. z macierz, którą zdefiniowałeś, zrobisz:

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

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

 92
Author: Daniele Merico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-25 10:13:01

Sweep () może być świetny do systematycznego manipulowania dużą macierzą kolumną 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

Oczywiście, ten przykład jest prosty, ale zmiana statystyk i zabawnych argumentów, inne manipulacje są możliwe.

 16
Author: Brad Horn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-10 17:35:15

To pytanie jest trochę stare, ale ponieważ ostatnio spotkałem się z tym problemem, typowe użycie funkcji sweep 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 sweep jest używany do odejmowania środków kolumn przed obliczeniem kowariancji. W linii 19 kodu wyprowadzony jest wektor centrujący:

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

I na linii 54 jest wyrzucany z matrycy

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

Autor kodu używa domyślna wartość FUN = "-", która na chwilę mnie zdezorientowała.

 6
Author: James King,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-26 01:19:42

Jednym z zastosowań jest obliczanie ważonych Sum dla tablicy. Gdzie rowSums lub colSums można założyć, że oznacza "wagi=1", sweep można wcześniej użyć do uzyskania ważonego wyniku. 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 Jamesa Kinga.

Oto kolejny oparty na aktualnym 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)
 3
Author: dardisco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-11 19:33:33

Możesz użyć funkcji sweep do skalowania i wyśrodkowywania danych, jak poniższy kod. Zauważ, że means i sds są tutaj dowolne (możesz mieć pewne wartości referencyjne, które chcesz standaryzować 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
 0
Author: Ehsan88,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 22:19:23