#r #matrix
#r #матрица
Вопрос:
У меня есть матрица с несколькими отдельными элементами в строках и несколькими нуклеотидами (значениями) в столбцах. Это выглядит так:
[,1][,2][,3][,4] ...
ind1 a c a a
ind2 a c t t
ind3 a g g c
ind4 a g g g
.
.
.
Теперь я хотел бы игнорировать все столбцы, в которых встречается только одно значение (как в примере над первым столбцом), и преобразовать каждый столбец с двумя, тремя и четырьмя (возможно не более 4!) различными нуклеотидами (значениями) в двоичный формат. В итоге это должно выглядеть так:
[,1] [,2] [,3] ...
ind1 10 100 1000
ind2 10 010 0100
ind3 01 001 0010
ind4 01 001 0001
.
.
.
Для меня важно получить один и тот же двоичный код только в том случае, если есть два, три или четыре разных значения.
Я уже подсчитывал, сколько разных значений встречается в каждом столбце, но я не уверен, как изменить значения в двоичном формате:
df <- apply(df, 2, function(x) length(unique(x)))
Кто-нибудь может мне помочь?
Комментарии:
1. Не ясно, как вы получаете ожидаемый результат ’01’ ’10’, где значения столбцов просто ‘a’ для первого столбца
2. Неясно, какой ожидаемый результат. Может быть
library(pryr);apply(df[-1], 2, function(x) {n <- length(unique(x)); substr(pryr::bits(x), n, n n-1)})
Ответ №1:
Вот что еще нужно попробовать. Пользовательская функция обработает каждый столбец apply
. Во-первых, вы можете создать вектор числовых значений, соответствующих уникальным символам в столбце ( unique
используется, так как factor
в противном случае порядок будет в алфавитном порядке). Будет создана строка нулей длиной максимального числа, и позиция символа, соответствующая каждому значению, будет заменена на «1».
my_fun <- function(x) {
vec <- as.numeric(factor(x, levels = unique(x)))
vec_max <- max(na.omit(vec))
lapply(vec,
function(y) ifelse(!is.na(y),
sub(paste0("(.{", y - 1, "})."),
"\11",
paste0(rep("0", vec_max), collapse = "")),
NA))
}
m[] <- matrix(unlist(apply(m, 2, my_fun)))
Вывод
[,1] [,2] [,3] [,4]
ind1 "1" "10" "100" "1000"
ind2 "1" "10" "010" "0100"
ind3 "1" "01" "001" "0010"
ind4 "1" "01" "001" "0001"
Данные
m <- structure(c("a", "a", "a", "a", "c", "c", "g", "g", "a", "t",
"g", "g", "a", "t", "c", "g"), .Dim = c(4L, 4L), .Dimnames = list(
c("ind1", "ind2", "ind3", "ind4"), NULL))
Комментарии:
1. большое спасибо за помощь, но я получаю эту ошибку:
Error in rep("0", max(vec)) : invalid 'times' argument
2. Привет, я пробовал со своими собственными данными. Он слишком большой
dput(head(df))
, в нем 543 строки и ~ 11000 столбцов, может быть, в этом причина?3. Да, у меня есть, но я использовал
[!is.na(x)]
. Разве это не сработает? И при вставке в небольшую матрицу и выполнении вашей команды это работает.4. Я бы хотел игнорировать NAs. Возможно ли это?
5. @LukasMe Смотрите Отредактированный ответ — дайте мне знать, если это поможет. Если значение отсутствует, оно будет использоваться
NA
в результате. Кроме того, длина двоичного результата также будет короче. Мне нужно запустить, но я проверю снова через несколько часов.
Ответ №2:
Вот моя попытка:
r1 <- c("a","c","a","a")
r2 <- c("a","c","t","t")
r3 <- c("a","g","g","c")
r4 <- c("a","g","g","g")
n.mat <- rbind(r1,r2,r3,r4)
number_to_nucleotide_binary <- function(x,len) {
out <- rep("0",len)
out[x] <- "1"
return(paste(out,collapse = ""))
}
nuc_to_binary <- function(x) {
len <- length(unique(x))
char <- sort(unique(x))
out <- x
if(len != 1) {
pos <- match(x,char)
out <- sapply(X = pos,FUN = function(x) {number_to_nucleotide_binary(x = x,len = len)})
}
return(out)
}
apply(X = n.mat,FUN = nuc_to_binary,MARGIN = 2)
Ввод:
[,1] [,2] [,3] [,4]
r1 "a" "c" "a" "a"
r2 "a" "c" "t" "t"
r3 "a" "g" "g" "c"
r4 "a" "g" "g" "g"
Вывод:
[,1] [,2] [,3] [,4]
[1,] "a" "10" "100" "1000"
[2,] "a" "10" "001" "0001"
[3,] "a" "01" "010" "0100"
[4,] "a" "01" "010" "0010"
Комментарии:
1. Привет, большое спасибо за помощь, но я хотел бы иметь только
1000 , 0100 , 0010 , 0001
, но нет0011
, например, но, кроме того, ваша команда сработала довольно хорошо!2. Я отредактировал код, чтобы упростить и устранить зависимость от другого ответа SO. Надеюсь, это то, что вам было нужно, хотя ответ Бена более масштабируемый / элегантный / лаконичный.