Verwendung der Sweep-Funktion

100

Wenn ich mir die Quelle von R-Paketen ansehe, sehe ich die sweephäufig verwendete Funktion . Manchmal wird es verwendet, wenn eine einfachere Funktion ausgereicht hätte (z. B. apply), manchmal ist es unmöglich, genau zu wissen, was es tut, ohne eine angemessene Zeit damit zu verbringen, den Codeblock zu durchlaufen, in dem es sich befindet.

Die Tatsache, dass ich den sweepEffekt mit einer einfacheren Funktion reproduzieren kann , deutet darauf hin , dass ich die wichtigsten Anwendungsfälle nicht verstehe sweep, und die Tatsache, dass diese Funktion so oft verwendet wird, legt nahe, dass sie sehr nützlich ist.

Der Kontext:

sweepist eine Funktion in der Standardbibliothek von R; seine Argumente sind:

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

Wie Sie sehen können, sind die Argumente , ähnlich wie applywenn sweepman erfordert mehr Parameter STATS.

Ein weiterer wesentlicher Unterschied besteht darin, dass sweepein Array mit derselben Form wie das Eingabearray zurückgegeben wird, während das von zurückgegebene Ergebnis von applyder übergebenen Funktion abhängt.

sweep in Aktion:

# 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

Alles in allem suche ich also ein oder zwei beispielhafte Anwendungsfälle für sweep.

Bitte rezitieren oder verlinken Sie nicht auf die R-Dokumentation, Mailinglisten oder eine der 'primären' R-Quellen - vorausgesetzt, ich habe sie gelesen. Mich interessiert, wie erfahrene R-Programmierer / Analysten sweepihren eigenen Code verwenden.

Doug
quelle
2
M-dx repliziert Ihr Ergebnis nicht. Sie haben Ihre eigene Frage beantwortet.
John
Die einzige Verwendung apply, die ich für dieses Ergebnis herausfinden kann, ist so etwas wie t(apply(t(M), 2, "-", dx)), aber das ist ziemlich böse.
Ken Williams

Antworten:

84

sweep()wird normalerweise verwendet, wenn Sie eine Matrix zeilen- oder spaltenweise bearbeiten und die andere Eingabe der Operation für jede Zeile / Spalte einen anderen Wert hat. Ob Sie nach Zeilen oder Spalten arbeiten, wird wie bei MARGIN festgelegt apply(). Die Werte, die für das verwendet werden, was ich "die andere Eingabe" nannte, werden von STATS definiert. Für jede Zeile (oder Spalte) nehmen Sie einen Wert aus STATS und verwenden ihn in der durch FUN definierten Operation.

Wenn Sie beispielsweise 1 zur 1. Zeile, 2 zur 2. usw. der von Ihnen definierten Matrix hinzufügen möchten, gehen Sie wie folgt vor:

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

Ich habe die Definition in der R-Dokumentation offen gesagt auch nicht verstanden, sondern nur durch Nachschlagen von Beispielen gelernt.

Daniele Merico
quelle
2
ein wenig umschreiben: STATSscheint eine schlechte Bezeichnung für diese Variable zu sein. Diese Eingabe FUNwird verwendet, um den Wert jedes Elements in der Matrix zu ändern ( Min diesem Beispiel). STATSkann entweder eine Konstante oder eine Liste / ein Vektor / usw. mit einer Größe sein, die der Größe der gewählten Größe entspricht MARGIN. Meiner Ansicht nach.
Roland
16

sweep () kann sich hervorragend dazu eignen, eine große Matrix entweder spaltenweise oder zeilenweise systematisch zu bearbeiten, wie unten gezeigt:

> 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

Zugegeben, dieses Beispiel ist einfach, aber wenn Sie das Argument STATS und FUN ändern, sind andere Manipulationen möglich.

Brad Horn
quelle
6

Diese Frage ist etwas alt, aber da ich kürzlich mit diesem Problem konfrontiert war, findet sich im Quellcode für die Statistikfunktion cov.wt, die zur Berechnung gewichteter Kovarianzmatrizen verwendet wird, eine typische Verwendung von Sweep . Ich schaue mir den Code in R 3.0.1 an. Hier sweepwird verwendet, um Spaltenmittelwerte vor dem Berechnen der Kovarianz zu subtrahieren. In Zeile 19 des Codes wird der Zentrierungsvektor abgeleitet:

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

und in Zeile 54 wird es aus der Matrix herausgefegt

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

Der Autor des Codes verwendet den Standardwert FUN = "-", was mich eine Weile verwirrt hat.

James King
quelle
3

Eine Verwendung ist, wenn Sie gewichtete Summen für ein Array berechnen . Wo rowSumsoder colSumsangenommen werden kann, dass 'Gewichte = 1' bedeutet, sweepkann vorher verwendet werden, um ein gewichtetes Ergebnis zu erhalten. Dies ist besonders nützlich für Arrays mit> = 3 Dimensionen.

Dies tritt beispielsweise bei der Berechnung einer gewichteten Kovarianzmatrix gemäß dem Beispiel von @James King auf.

Hier ist eine andere, die auf einem aktuellen Projekt basiert:

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

Sie können die sweepFunktion verwenden, um Daten wie den folgenden Code zu skalieren und zu zentrieren. Beachten Sie, dass meansund sdshier willkürlich sind (möglicherweise haben Sie einige Referenzwerte, mit denen Sie Daten basierend darauf standardisieren möchten):

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

Dieser Code konvertiert Rohwerte in T-Werte (mit Mittelwert = 50 und 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
quelle
1
@BenBolker, wie ich in der Antwort erwähnt habe, weil ich die Elemente möglicherweise nach einem Referenzmittelwert und einem SD skalieren möchte, nicht nach dem Mittelwert und dem SD der aktuellen Stichprobe. Dies tritt auf, wenn Sie sich mit Tests befassen, die in großen Stichproben verwaltet und standardisiert werden, und wenn Sie Ihre kleine Stichprobenbewertung anhand ihrer Statistiken standardisieren möchten.
Ehsan88