web-dev-qa-db-ja.com

複数の列に基づいた一意のケースを持つサブセット

データフレームをサブセット化して、3つの列の一意の組み合わせを持つ行のみを含めたいと思います。私の状況は this の質問で提示された状況と似ていますが、データ内の他の列も保持したいと思います。これが私の例です:

> df
  v1  v2  v3   v4  v5
1  7   1   A  100  98 
2  7   2   A   98  97
3  8   1   C   NA  80
4  8   1   C   78  75
5  8   1   C   50  62
6  9   3   C   75  75

要求された出力は次のようなものになります。v1、v2、v3のみに基づいた一意のケースを探しています。

> df.new
  v1  v2  v3   v4  v5
1  7   1   A  100  98 
2  7   2   A   98  97
3  8   1   C   NA  80
6  9   3   C   75  75

一意ではない行を回復できたら、それも素晴らしいでしょう:

> df.dupes
  v1  v2  v3   v4  v5
3  8   1   C   NA  80
4  8   1   C   78  75
5  8   1   C   50  62

私はSQLでこれを行う方法に関連する質問を見ました( here )が、Rではこれを取得できません。それは簡単ですが、unique()とsubset()hasn実りありませんでした。前もって感謝します。

38
user1202761

duplicated()関数を使用して、一意の組み合わせを見つけることができます。

> df[!duplicated(df[1:3]),]
  v1 v2 v3  v4 v5
1  7  1  A 100 98
2  7  2  A  98 97
3  8  1  C  NA 80
6  9  3  C  75 75

重複のみを取得するには、双方向で確認できます。

> df[duplicated(df[1:3]) | duplicated(df[1:3], fromLast=TRUE),]
  v1 v2 v3 v4 v5
3  8  1  C NA 80
4  8  1  C 78 75
5  8  1  C 50 62
54
Ken Williams

dplyrを使用すると、次のことができます。

library(dplyr)

# distinct
df %>% 
  distinct(v1, v2, v3, .keep_all = T)

# non-distinct only
df %>% 
  group_by(v1, v2, v3) %>% 
  filter(n() > 1)

# exclude any non-distinct
df %>% 
  group_by(v1, v2, v3) %>% 
  filter(n() == 1)
4
sbha

plyrパッケージを使用できます:

library(plyr)

ddply(df, c("v1","v2","v3"), head, 1)
#   v1 v2 v3  v4 v5
# 1  7  1  A 100 98
# 2  7  2  A  98 97
# 3  8  1  C  NA 80
# 4  9  3  C  75 75

ddply(df, c("v1","v2","v3"), function(x) if(nrow(x)>1) x else NULL)
#   v1 v2 v3 v4 v5
# 1  8  1  C NA 80
# 2  8  1  C 78 75
# 3  8  1  C 50 62
4
flodel

ええ、データが多すぎる場合、plyrとddplyの使用は非常に遅くなります。

この種のものを試してみてください:

df[ cbind( which(duplicated(df[1:3])), which(duplicated(df[1:3], fromLast=TRUE))),]

または::

from = which(duplicated(df[1:3])
to = which(duplicated(df[1:3], fromLast=TRUE))
df[cbind(from,to),]

ほとんどの場合、shdはより高速になります。

それをテストして、私たちに知らせてください

いくつかのエラーがありますが、アイデアが得られれば修正できると思います。

また、ユニークですべてを試してみてください

2
monis rahman

エレガントではないが機能的な方法は、特定の行のエントリを貼り付けて、一意の(または一意ではない)行を見つけることです。

df.vector=apply(df,1,FUN=function(x) {paste(x,collapse="")})
df.table=table(df.vector)

次に、次のようなもので重複のインデックスを取得します。

which(df.vector%in%names(which(df.table>1)))
1
nullalleles