web-dev-qa-db-ja.com

Rの2つの文字ベクトルを比較します

IDの2つの文字ベクトルがあります。

2つの文字ベクトルを比較したいのですが、特に次の図に興味があります。

  • AとBの両方にあるIDの数
  • AにはあるがBにはないIDの数
  • BにはあるがAにはないIDの数

また、ベン図を描きたいです。

50
Aslan986

試してみるための基本事項を次に示します。

> 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
72
Mittenchops

私は通常、大規模なセットを扱っているため、ベン図の代わりにテーブルを使用します。

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
20
Frank

intersectおよびsetdiffの代わりに%in%および共通要素のブールベクトルを使用する別の方法。実際に比較したいのは2つvectorsで、2つではないlists-a listは任意のタイプの要素を含むRクラスです一方、ベクトルには常に1つのタイプの要素しか含まれていないため、真に等しいものを簡単に比較できます。ここでは、要素は文字列に変換されます。これは、存在する最も柔軟性のない要素タイプであったためです。

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にベン図をプロットするには複数の選択肢があります。これは、gplotを使用した出力です。

venn diagram with gplots

13

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
4
rferrisx

上記の回答の1つと同じサンプルデータを使用します。

_A = c("Dog", "Cat", "Mouse")
B = c("Tiger","Lion","Cat")

match(A,B)
[1] NA  3 NA
_

match関数は、B内のすべての値のA内の位置を含むベクトルを返します。したがって、catの2番目の要素であるAは、Bの3番目の要素です。他に一致するものはありません。

AおよびBの一致する値を取得するには、次のようにします。

_m <- match(A,B)
A[!is.na(m)]
"Cat"
B[m[!is.na(m)]]
"Cat"
_

ABで一致しない値を取得するには:

_A[is.na(m)]
"Dog"   "Mouse"
B[which(is.na(m))]
"Tiger" "Cat"
_

さらに、length()を使用して、一致する値と一致しない値の総数を取得できます。

1
milan

Aがタイプリストのフィールドaを持つdata.tableであり、エントリ自体がプリミティブタイプのベクトルである場合。次のように作成

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]

aの一致するインデックスが必要な場合

A[,which(sapply(a,identical,unlist(B)))]

代わりに、B自体がAと同じ構造を持つdata.tableである場合、たとえば.

B<-data.table(b=c(list(c("zyx","ghi")),list(c("abc","def",123))),z=c(5,7))

そして、1つの列で2つのリストの共通部分を探しています。ここでは、同じ順序のベクトル要素が必要です。

# 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]

data.table 1.12.2のlist型のフィールドをキー入力できないため、A&Bに参加する

同様に、あなたは尋ねることができません

A[a==B[,b]]

==演算子がlist型のRに実装されていないため、AとBが同一であっても

1
mpag