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

Когда я смотрю на источник пакетов 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 в своем собственном коде.

Ответ 1

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

Например, если вы хотите добавить 1 в 1-ю строку, 2 во 2-ю и т.д. Матрицы, которую вы определили, вы сделаете:

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

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

Ответ 2

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, возможны другие манипуляции.

Ответ 3

Этот вопрос немного устарел, но, поскольку я недавно столкнулся с этой проблемой, типичное использование sweep можно найти в исходном коде для функции статистики 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 = "-", которое меня некоторое время путало.

Ответ 4

Одно использование - это когда вы вычисляете взвешенные суммы для массива. Если предположить, что rowSums или colSums означает "вес = 1", sweep можно использовать до этого, чтобы получить взвешенный результат. Это особенно полезно для массивов s >= 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)

Ответ 5

Вы можете использовать функцию 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