Как в R применить функцию «for» с операторами «if» на матрице для создания функции сглаживания - PullRequest
3 голосов
/ 07 ноября 2019

Итак, вот моя проблема:

У меня есть огромный CSV-файл с большим количеством точек данных. Каждая строка представляет значения, принадлежащие эксперименту.

       col1 , col2, col3, col4, col5, col6, ..., coln-1, coln
exp_1  190    10000  845   20    100   67   ..., 2       634
exp_2    3      567   87   465   23    867  ..., 987     43
   .
   .
   .

Каждый эксперимент может быть представлен в гистограмме, но значения должны быть сглажены по среднему значению их четырех соседей. Так, например, значение 845 на matrix[1,3] будет перезаписано на mean(matrix[1,1]:matrix[1,5]). Проблема, которая возникает в позиции matrix[1,1]. Поскольку не осталось левых соседей, сглаживание не работает и выдает ошибку. Поскольку столбцы представляют круговое измерение в диапазоне от до 360°, значения в coln фактически представляют левого соседа col1.

Если я извлекаю вектор exp_1 матрицы(x=matrix[1,]) и примите это в качестве входного аргумента для следующего кода, все будет работать гладко.

for ( i in 1:length(x)){
  if (i < 2) {
    x[i] = mean(c(x[i:(i+2)],x[(length(x)-i):(length(x))]))
  } else if (i >= 2){
    x[i] = mean(x[(i-2):(i+2)])
  } else if (i > (length(x)-2)){
    x[i] = mean(c(x[(i-2):i],x[1:abs(length(x)-(i+2))]))
  }
}

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

smoothing_function = function(x){
for ( i in 1:length(x)){
  if (i < 2) {
    x[i] = mean(c(x[i:(i+2)],x[(length(x)-i):(length(x))]))
  } else if (i >= 2){
    x[i] = mean(x[(i-2):(i+2)])
  } else if (i > (length(x)-2)){
    x[i] = mean(c(x[(i-2):i],x[1:abs(length(x)-(i+2))]))
  }
}
}

Затем я хотел apply(matrix,1,smoothing_function), что приводит к NULL. Я также попытался mapply(smoothing_function,matrix), что приводит к NULL для каждого столбца всей матрицы.

Я думаю, что проблема находится в части length(x), потому что входной аргумент не вектор, а единственный элемент,Поэтому функция не может вычислить среднее значение для любых соседей, поскольку длина одного элемента равна всего лишь 1.

Так что либо мне нужно сгенерировать вектор для каждого эксперимента из матрицы, либо мне нужно изменитьмоя функция. Ребята, у вас есть идеи?

1 Ответ

2 голосов
/ 07 ноября 2019

Одна возможность избежать цикла и условий if - создать новую матрицу, в которую вы вставляете последние два столбца в начале и первые два столбца в конце.

Вот небольшойпример. Сначала я создаю некоторые тойды, используя rpois:

set.seed(1)
my_matrix <- matrix(rpois(20, 10), 2, 10)
colnames(my_matrix) <- paste0("col", 1:10)
my_matrix

     col1 col2 col3 col4 col5 col6 col7 col8 col9 col10
[1,]    8    7   14   11   14    8    8    7   11    12
[2,]   10   11   12    9   11    2   10   12   12    10

. Затем эта матрица расширяется путем добавления столбцов в начале и в конце:

my_matrix2 <- cbind(my_matrix[, 9:10], my_matrix, my_matrix[, 1:2])
my_matrix2
     col9 col10 col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 col1 col2
[1,]   11    12    8    7   14   11   14    8    8    7   11    12    8    7
[2,]   12    10   10   11   12    9   11    2   10   12   12    10   10   11

Наконец, вы можете использоватьrollapply функция из пакета zoo для вычисления среднего значения. Обратите внимание, что сначала вы должны установить пакет zoo.

my_matrix_smooth <- t(apply(my_matrix2, 1, function(z) zoo::rollapply(z, width = 5, FUN = mean)))

     col1 col2 col3 col4 col5 col6 col7 col8 col9 col10
[1,] 10.4 10.4 10.8 10.8 11.0  9.6  9.6  9.2  9.2     9
[2,] 11.0 10.4 10.6  9.0  8.8  8.8  9.4  9.2 10.8    11

Чтобы убедиться, что это правильно, мы можем (например) взглянуть на col10 первой строки. Сглаженная версия должна быть (7+11+12+8+7) / 5 = 9. И это действительно так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...