Нахождение совпадающих значений в двух векторах разной длины в R - PullRequest
0 голосов
/ 29 октября 2018

У меня есть два вектора с названиями видов, которые следуют за двумя разными методами. Некоторые имена одинаковые, другие разные, и оба отсортированы по-разному. Пример: список 1: c (Homo sapiens sapiens, Homo sapiens neanderthalensis, Homo erectus, ..., n) Список 2: c (Homo erectus, Homo sapiens, Homo neanderthalensis, ..., n + 1)

Я пишу n и n + 1, чтобы обозначить, что эти списки имеют разную длину.

Я хотел бы создать новый список, состоящий из двух значений: в случае совпадения двух векторов (например, Homo erectus) мне бы хотелось, чтобы имя списка 2 находилось в месте, где находится имя в списке 1, или в случае несоответствия «0» в местоположении в списке 1. Таким образом, в этом случае этот новый список будет новым списком: c (0,0, Homo erectus, ...)

Для этого я написал следующий код, но он не работает.

data<-read.table("species.txt",sep="\t",header=TRUE)
list1<-as.vector(data$Species1)
list2<-as.vector(data$Species2)
newlist<-as.character(rep(0,length(list1)))

for (i in 1:length(list1)){
for (j in 1:length(list2)){
if(list1[i] == list2[j]){newlist[i]<- list2[j]}else {newlist[i]= 0}
}
}

Надеюсь, это понятно.

Спасибо за любую помощь!

Ответы [ 3 ]

0 голосов
/ 29 октября 2018

Я не совсем уверен, что понимаю, чего вы пытаетесь достичь, но я думаю, что это делает то, что вы после.

list1 <- c("Homo sapiens sapiens","Homo sapiens neanderthalensis","Homo erectus")
list2 <- c("Homo erectus","Homo sapiens","Homo neanderthalensis")

sapply(list1, function(x) { ifelse(x %in% list2, list2[which(list1 == x)], 0) } )
0 голосов
/ 29 октября 2018

Внутренний цикл for использует newname[i], где он должен быть newlist[i]. Используя ваш код, вы перезаписываете newlist[i] записи j раз либо 0, либо названием вида. Это, вероятно, не то, что вы хотите.

0 голосов
/ 29 октября 2018

Возьмите этот воспроизводимый пример:

set.seed(1)
list1 <- letters[1:10]
list1names
list2 <- letters[sample(1:10, 10)]

Вы можете избежать цикла, используя ifelse:

newlist <- ifelse(list1==list2, list2, 0)

Проблема в том, что вы не объявили newname, вы имели в виду newlist?

Если вы хотите использовать цикл, вы можете использовать только один цикл, а не 2, потому что length(list1) = length(list2):

for (i in 1:length(list1)){
    if(list1[i] == list2[i]){newlist[i]<- list2[i]}else {newlist[i]= 0}
}

В общем, если вы хотите сопоставить элементы в векторах, вы можете использовать match, например:

> list1
 [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
> list2
 [1] "c" "d" "e" "g" "b" "h" "i" "f" "j" "a"
> match(list1, list2)
 [1] 10  5  1  2  3  8  4  6  7  9

Как видите, match получает индексы элементов в list2, которые равны элементам в list1. Это полезно, если у вас есть другая таблица data2, и вы хотите извлечь столбец в data2 для соответствующих элементов из данных $ list1 в data2$list3, вы должны использовать:

data <- data.frame(list1, list2)
list3 <- list2
columntoget <- 1:length(list2)
data2 <- data.frame(list3, columntoget)
data$mynewcolumn <- data2$columntoget[match(data$list1, data2$list3)]
> data$mynewcolumn
 [1] 10  5  1  2  3  8  4  6  7  9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...