Как использовать функцию "развертки"
Когда я смотрю на источник пакетов 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