Сравните два символьных вектора в R
У меня есть два символьных вектора идентификаторов.
Я хотел бы сравнить два символьных вектора, в частности меня интересуют следующие цифры:
- Сколько идентификаторов в и B
- Сколько идентификаторов в A, но не в B
- Сколько идентификаторов в B, но не в A
Я также хотел бы нарисовать диаграмму Венна.
Ответы
Ответ 1
Вот некоторые основы для тестирования:
> A = c("Dog", "Cat", "Mouse")
> B = c("Tiger","Lion","Cat")
> A %in% B
[1] FALSE TRUE FALSE
> intersect(A,B)
[1] "Cat"
> setdiff(A,B)
[1] "Dog" "Mouse"
> setdiff(B,A)
[1] "Tiger" "Lion"
Аналогично, вы можете получить счет просто:
> length(intersect(A,B))
[1] 1
> length(setdiff(A,B))
[1] 2
> length(setdiff(B,A))
[1] 2
Ответ 2
Я обычно имею дело с большими иш-множествами, поэтому вместо диаграммы Венна я использую таблицу:
xtab_set <- function(A,B){
both <- union(A,B)
inA <- both %in% A
inB <- both %in% B
return(table(inA,inB))
}
set.seed(1)
A <- sample(letters[1:20],10,replace=TRUE)
B <- sample(letters[1:20],10,replace=TRUE)
xtab_set(A,B)
# inB
# inA FALSE TRUE
# FALSE 0 5
# TRUE 6 3
Ответ 3
Иными словами, с использованием% in% и булевых векторов общих элементов вместо пересечения и setdiff. Я полагаю, вы действительно хотите сравнить два вектора, а не два списка - список - это класс R, который может содержать любой тип элемента, в то время как векторы всегда содержат элементы только одного типа, следовательно, проще сравнивать то, что действительно равно. Здесь элементы преобразуются в символьные строки, поскольку это был самый негибкий тип элемента, который присутствовал.
first <- c(1:3, letters[1:6], "foo", "bar")
second <- c(2:4, letters[5:8], "bar", "asd")
both <- first[first %in% second] # in both, same as call: intersect(first, second)
onlyfirst <- first[!first %in% second] # only in 'first', same as: setdiff(first, second)
onlysecond <- second[!second %in% first] # only in 'second', same as: setdiff(second, first)
length(both)
length(onlyfirst)
length(onlysecond)
#> both
#[1] "2" "3" "e" "f" "bar"
#> onlyfirst
#[1] "1" "a" "b" "c" "d" "foo"
#> onlysecond
#[1] "4" "g" "h" "asd"
#> length(both)
#[1] 5
#> length(onlyfirst)
#[1] 6
#> length(onlysecond)
#[1] 4
# If you don't have the 'gplots' package, type: install.packages("gplots")
require("gplots")
venn(list(first.vector = first, second.vector = second))
Как уже упоминалось, существует множество вариантов построения диаграмм Венна в R. Вот результат с использованием gplots.
![venn diagram with gplots]()
Ответ 4
С sqldf: медленнее, но очень подходит для фреймов данных со смешанными типами:
t1 <- as.data.frame(1:10)
t2 <- as.data.frame(5:15)
sqldf1 <- sqldf('SELECT * FROM t1 EXCEPT SELECT * FROM t2') # subset from t1 not in t2
sqldf2 <- sqldf('SELECT * FROM t2 EXCEPT SELECT * FROM t1') # subset from t2 not in t1
sqldf3 <- sqldf('SELECT * FROM t1 UNION SELECT * FROM t2') # UNION t1 and t2
sqldf1 X1_10
1
2
3
4
sqldf2 X5_15
11
12
13
14
15
sqldf3 X1_10
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Ответ 5
Используя тот же пример данных, что и один из ответов выше.
A = c("Dog", "Cat", "Mouse")
B = c("Tiger","Lion","Cat")
match(A,B)
[1] NA 3 NA
Функция match
возвращает вектор с местоположением в B
всех значений в A
Итак, cat
, второй элемент в A
, является третьим элементом в B
Других матчей нет.
Чтобы получить совпадающие значения в A
и B
, вы можете сделать:
m <- match(A,B)
A[!is.na(m)]
"Cat"
B[m[!is.na(m)]]
"Cat"
Чтобы получить несовпадающие значения в A
и B
:
A[is.na(m)]
"Dog" "Mouse"
B[which(is.na(m))]
"Tiger" "Cat"
Кроме того, вы можете использовать length()
чтобы получить общее количество совпадающих и несоответствующих значений.
Ответ 6
Если является data.table с полем A
a
списке Типа с записями самих в качестве векторов примитивного типа, например, создаются следующим образом
A<-data.table(a=c(list(c("abc","def","123")),list(c("ghi","zyx"))),d=c(9,8))
и B
представляет собой список с вектором примитивных записей, например, созданный следующим образом
B<-list(c("ghi","zyx"))
и вы пытаетесь найти, какой (если есть) элемент A$a
соответствует B
A[sapply(a,identical,unlist(B))]
если вы просто хотите, чтобы запись в a
A[sapply(a,identical,unlist(B)),a]
если вы хотите сопрягая indicies из a
A[,which(sapply(a,identical,unlist(B)))]
если вместо этого B сам является таблицей данных с той же структурой, что и A, например
B<-data.table(b=c(list(c("zyx","ghi")),list(c("abc","def",123))),z=c(5,7))
и вы ищете пересечение двух списков одним столбцом, где вам требуется одинаковый порядок векторных элементов.
# give the entry in A for in which A$a matches B$b
A[,':='(res=unlist(sapply(list(a),function(x,y){
x %in% unlist(lapply(y,as.vector,mode="character"))
},list(B[,b]),simplify=FALSE)))
][res==TRUE
][,res:=NULL][]
# get T/F for each index of A
A[,sapply(list(a),function(x,y){
x %in% unlist(lapply(y,as.vector,mode="character"))
},list(B[,b]),simplify=FALSE)]
Обратите внимание, что вы не можете сделать что-то так просто, как
setkey(A,a)
setkey(B,b)
A[B]
присоединиться к A & B, потому что вы не можете ввести поле типа list
в data.table 1.12.2
Точно так же вы не можете спросить
A[a==B[,b]]
даже если A и B идентичны, так как оператор ==
не был реализован в R для list
типов