#r #matrix
#r #матрица
Вопрос:
У меня есть матрица с нуклеотидными последовательностями (содержащими NAs) в строках, как показано здесь:
n.mat
samp1 <- c("a","c","a",NA,"t","c")
samp2 <- c("a","c","t","t",NA,"a")
samp3 <- c("a","g","g","c","a","c")
samp4 <- c("a","g",NA,"g","g", NA)
samp5<- c(NA, "g","g","g","t","g")
n.mat <- rbind(samp1,samp2,samp3,samp4,samp5)
[,1] [,2] [,3] [,4] [,5] [,6]
samp1 "a" "c" "a" NA "t" "c"
samp2 "a" "c" "t" "t" NA "a"
samp3 "a" "g" "g" "c" "a" "a"
samp4 "a" "g" NA "g" "g" NA
samp5 NA "g" "g" "g" "t" "g"
У меня также есть фрейм данных с двумя столбцами, содержащими имена последовательностей:
df
df <- data.frame(
X1 = c("samp1", "samp2", "samp3", "samp4", "samp5"),
X2 = c("samp2", "samp5", "samp1", "samp3", "samp2"))
X1 X2
1 samp1 samp2
2 samp2 samp5
3 samp3 samp1
4 samp4 samp3
5 samp5 samp2
Я хотел бы заполнить пробелы строки в матрице нуклеотидами / значениями из другой строки в матрице, обозначенной df$X2
столбцом во фрейме данных.
Так, например: samp1
в матрице есть NA
в своей строке в четвертом столбце. Поэтому я хотел бы взять строку из того же столбца samp2
(обозначается фреймом данных в столбце X2
). Поскольку samp2
я хотел бы заполнить NA
, взяв строку из samp5
(обозначенную фреймом данных в столбце X2
). Если NA
в строке, в которой она находится, нет samp3
, то ничего не делайте. Если в строке их два NAs
(как в samp4
), то я хотел бы взять обе строки из samp3
обоих столбцов.
Я попробовал следующий код:
replace.na <- function(n.mat,val) {
i <- is.na(n.mat)
j <- which(i)
k <- which(!i)
n.mat[j[j > k[length(k)]]] <- val
n.mat
}
n.mat[,-1] <- t(apply(matrix[,-1],1,replace.na))
Но я не совсем уверен, как включить df
таблицу для замены NAs
.
Ответ №1:
Вот очень компактный код, который я объясню (и он предполагает либо использование rv4.x, либо создание фрейма данных ‘df’ с stringsAsFactors=FALSE
помощью):
n.mat[ is.na(n.mat) ] <- n.mat[df[['X2']],][ is.na(n.mat)]
n.mat
#------
[,1] [,2] [,3] [,4] [,5] [,6]
samp1 "a" "c" "a" "t" "t" "c"
samp2 "a" "c" "t" "t" "t" "a"
samp3 "a" "g" "g" "c" "a" "a"
samp4 "a" "g" "g" "g" "g" "a"
samp5 "a" "g" "g" "g" "t" "g"
is.na(.n.mat)
Возвращает логическую матрицу того же измерения, что и n.mat. Он используется в качестве индекса с обеих сторон присваивания, но в правой части присваивания выполняется выбор из матрицы, строки которой переставлены в соответствии с порядком «замещающих строк», который вы указали df
. Если бы столбец ‘X1’ не был в том же порядке, что и целевая матрица, вам нужно было бы изменить порядок этого столбца с помощью order
вызова, но здесь это не понадобилось.
df <- read.table(text= 'X1 X2
1 samp1 samp2
2 samp2 samp5
3 samp3 samp1
4 samp4 samp3
5 samp5 samp2', header=TRUE, stringsAsFactors=FALSE)
Обратите внимание на stringsAsFactors=FALSE
. Я думаю, что моя неспособность использовать это (поскольку я все еще на R 3.6) означала, что у меня были коэффициенты в столбце X2.
Другой способ сделать это — создать индекс из двух столбцов позиций NA с параметром arr.idx, установленным в TRUE:
pos <- which(is.na(n.mat),arr.ind=TRUE)
> pos
row col
samp5 5 1
samp4 4 3
samp1 1 4
samp2 2 5
samp4 4 6
Затем вы можете индексировать с помощью этой матрицы из 2 столбцов:
n.mat[pos] <- n.mat[ df[['X2']] ,][pos]
> n.mat
[,1] [,2] [,3] [,4] [,5] [,6]
samp1 "a" "c" "a" "t" "t" "c"
samp2 "a" "c" "t" "t" "t" "a"
samp3 "a" "g" "g" "c" "a" "a"
samp4 "a" "g" "g" "g" "g" "a"
samp5 "a" "g" "g" "g" "t" "g"
Индексация матрицы R может привести к некоторым очень компактным решениям подобных проблем. Вам следует прочитать страницу ?'['
справки для получения более подробной информации и примеров. Время, потраченное на эти усилия, окупится многократно, если вы продолжите использовать R. Я уверен, что уже прочитал это 10 или 20 раз.
Reprex:
n.mat <- matrix( scan(text = 'samp1 "a" "c" "a" "NA" "t" "c"
samp2 "a" "c" "t" "t" "NA" "a"
samp3 "a" "g" "g" "c" "a" "a"
samp4 "a" "g" "NA" "g" "g" "NA"
samp5 "NA" "g" "g" "g" "t" "g" ', what=""), nrow=5, byrow=TRUE)
n.mat <- matrix(n.mat[ ,-1], nrow=5, dimnames=list(n.mat[,1], NULL))
df <- read.table(text= 'X1 X2
1 samp1 samp2
2 samp2 samp5
3 samp3 samp1
4 samp4 samp3
5 samp5 samp2', header=TRUE, stringsAsFactors=FALSE)
Комментарии:
1. Привет, большое спасибо, я думаю, что ваша идея была очень полезной, и она работает довольно хорошо, если нет повторений. Но я думаю
NA
, что данные из второй строки и 5-го столбца матрицы были преобразованы неправильно. Это должно быть at
. Я также проверял разные варианты расположенияNAs
, и тогда он не будет преобразовывать каждыйNA
. Может быть, у вас есть другой вариант?2. Код был правильным (я думаю), но я подозреваю, что мы оба использовали R 3.6 или ниже и принимали значение по умолчанию
stringsAsFactors
для создания data.frame. Не должно быть проблем с несколькими NAS в строке. Может возникнуть проблема, если в таблице замены df не было записи для конкретной строки матрицы n.mat. В этом случае вы должны вставить заполнитель со строкой, ссылающейся на саму себя. например3 sampx sampx
Ответ №2:
Вы могли бы попробовать что-то вроде этого ниже. Обратите внимание, что результат немного отличается, но я скопировал / вставил ваш код для создания вашей матрицы (см. samp3
Столбец 6).
t(sapply(rownames(n.mat), function(x) {
na_cols <- is.na(n.mat[x, ])
n.mat[x, na_cols] <- n.mat[df[df$X1 == x, "X2"], na_cols]
n.mat[x, ]
}))
Вывод
[,1] [,2] [,3] [,4] [,5] [,6]
samp1 "a" "c" "a" "t" "t" "c"
samp2 "a" "c" "t" "t" "t" "a"
samp3 "a" "g" "g" "c" "a" "c"
samp4 "a" "g" "g" "g" "g" "c"
samp5 "a" "g" "g" "g" "t" "g"
Данные
n.mat <- structure(c("a", "a", "a", "a", NA, "c", "c", "g", "g", "g",
"a", "t", "g", NA, "g", NA, "t", "c", "g", "g", "t", NA, "a",
"g", "t", "c", "a", "c", NA, "g"), .Dim = 5:6, .Dimnames = list(
c("samp1", "samp2", "samp3", "samp4", "samp5"), NULL))
Комментарии:
1. Проверьте свой результат и проверьте, является ли ваш df $ X2 фактором.
2. Мой
df$X2
не был фактором, просто вектор символов (я использую R 4.0.2 и, возможно, привыкаюstringsAsFactors
кFALSE
умолчанию)… Кстати, мне нравится ваш компактный код / ответ…3. Я получаю разные результаты. Посмотрите на столбец 6, строки 3 и 4.
4. Хм … я получил те же результаты, что и ваш ответ. Интересно, может ли это быть связано с различием в
n.mat
данных. Данные примера OP, возможно, изменились —samp3
вектор заканчивается на «c» — но послеrbind
n.mat
того, как матрица имеет строкуsamp3
col 6 как «a». Я добавлю свои данные примера к своему ответу (хотя и испытываю желание удалить, не уверен, насколько это полезно).5. Вы правы. OP изменил пример и не сообщил нам. Я использовал исходную проблему.