Как использовать функцию «развертки»

101

Когда я смотрю на исходный код пакетов R, я вижу, что функция sweepиспользуется довольно часто. Иногда он используется, когда было бы достаточно более простой функции (например, apply), в других случаях невозможно точно знать, что он делает, не потратив достаточное количество времени на пошаговое выполнение блока кода, в котором оно находится.

Тот факт, что я могу воспроизвести sweepэффект с помощью более простой функции, говорит о том, что я не понимаю sweepосновных вариантов использования, а тот факт, что эта функция используется так часто, предполагает, что она весьма полезна.

Контекст:

sweepэто функция в стандартной библиотеке R; его аргументы:

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

Как вы можете видеть, аргументы аналогичны , applyхотя sweepтребует еще один параметр, STATS.

Еще одно ключевое отличие состоит в том, что sweepвозвращает массив той же формы, что и входной массив, тогда как результат, возвращаемый applyфункцией, зависит от переданной функции.

sweep в действии:

# 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

Итак, то, что я ищу, - это один или два примерных варианта использования sweep.

Пожалуйста, не цитируйте и не ссылайтесь на документацию R, списки рассылки или любые «первичные» источники R - предположим, что я их читал. Что меня интересует, так это то, как опытные программисты / аналитики R используют sweepсвой собственный код.

дуг
источник
2
M-dx не копирует ваш результат. Вы ответили на свой вопрос.
Джон
Единственное использование этого, applyкоторое я могу найти для этого результата, - это что-то вроде t(apply(t(M), 2, "-", dx)), но это довольно неприятно.
Кен Уильямс

Ответы:

84

sweep()обычно используется, когда вы работаете с матрицей по строкам или по столбцам, а другой вход операции - это разные значения для каждой строки / столбца. Независимо от того, работаете ли вы по строке или по столбцу, определяется MARGIN, как для apply(). Значения, используемые для того, что я назвал «другим входом», определяются STATS. Итак, для каждой строки (или столбца) вы берете значение из STATS и используете его в операции, определенной FUN.

Например, если вы хотите добавить 1 к 1-й строке, 2 ко 2-й и т. Д. Определенной вами матрицы, вы сделаете:

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

Я, честно говоря, тоже не понимал определения в документации R, я просто узнал, просматривая примеры.

Даниэле Мерико
источник
2
перефразируя немного: STATSкажется, плохой ярлык для этой переменной. Это вход, FUNкоторый используется для изменения значения каждого элемента в матрице ( Mв этом примере). STATSможет быть либо константой, либо списком / вектором / и т.д. размера, соответствующего размеру выбранного MARGIN. Думаю.
Роланд
16

sweep () отлично подходит для систематического управления большой матрицей столбец за столбцом или строка за строкой, как показано ниже:

> 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

Конечно, этот пример простой, но изменяя аргумент STATS и FUN, возможны и другие манипуляции.

Брэд Хорн
источник
6

Этот вопрос немного устарел, но, поскольку я недавно столкнулся с этой проблемой, типичное использование развертки можно найти в исходном коде функции статистики cov.wt, используемой для вычисления взвешенных ковариационных матриц. Я смотрю код в R 3.0.1. Здесь sweepиспользуется , чтобы вычесть из средств столбцов перед вычислением ковариации. В строке 19 кода выводится центрирующий вектор:

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

а в строке 54 он выметается из матрицы

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

Автор кода использует значение по умолчанию FUN = "-", которое меня на некоторое время смутило.

Джеймс Кинг
источник
3

Одно из применений - это когда вы вычисляете взвешенные суммы для массива. Где rowSumsили colSumsможет означать «веса = 1», sweepможет использоваться перед этим для получения взвешенного результата. Это особенно полезно для массивов с> = 3 измерениями.

Это возникает, например, при вычислении взвешенной ковариационной матрицы в соответствии с примером @James King.

Вот еще один, основанный на текущем проекте:

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

Вы можете использовать sweepфункцию для масштабирования и центрирования данных, как в следующем коде. Обратите внимание, что meansи sdsздесь произвольны (у вас могут быть некоторые справочные значения, на основе которых вы хотите стандартизировать данные):

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

Этот код преобразует исходные оценки в оценки T (со средним значением = 50 и 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
источник
1
@BenBolker, как я уже упоминал в ответе, потому что я могу захотеть масштабировать элементы в соответствии с эталонным средним и SD, а не средним и SD самого текущего образца. Это происходит, когда вы имеете дело с тестами, которые проводятся и стандартизированы в больших выборках, и вы хотите стандартизировать свой результат в малой выборке в соответствии с их статистикой.
Ehsan88