web-dev-qa-db-ja.com

データフレームから特定の行を削除する

データフレームがあります:

sub   day
1      1
1      2
1      3
1      4
2      1
2      2
2      3
2      4
3      1
3      2
3      3
3      4

そして、subとdayの組み合わせで識別できる特定の行を削除したいと思います。たとえば、sub = '1'およびday = '2'およびsub = 3およびday = '4'の行を削除したいとします。どうすればこれができますか?行番号を指定できることはわかっていますが、これは巨大なデータフレームに適用する必要があり、各行を通過してIDを指定するのは面倒です。

24
RodgerDodger
DF[ ! ( ( DF$sub ==1 & DF$day==2) | ( DF$sub ==3 & DF$day==4) ) , ]   # note the ! (negation)

または、引用符の使用によって示唆されるようにsubが要因である場合:

DF[ ! paste(sub,day,sep="_") %in% c("1_2", "3_4"), ]

サブセットも使用できます:

subset(DF,  ! paste(sub,day,sep="_") %in% c("1_2", "3_4") )

(そして、[[]を使用する場合、Dirkの回答でwhichを使用することは推奨されますが、それは必要ではないと主張します。)

35
42-

これは、2つの異なるステップに要約されます。

  1. 条件がいつ真であるかを把握し、ブール値のベクトルを計算します。または、必要に応じて、which()にラップしてインデックスを計算します
  2. 更新されたdata.frame前のステップからインデックスを除外します。

以下に例を示します。

R> set.seed(42)
R> DF <- data.frame(sub=rep(1:4, each=4), day=sample(1:4, 16, replace=TRUE))
R> DF
   sub day
1    1   4
2    1   4
3    1   2
4    1   4
5    2   3
6    2   3
7    2   3
8    2   1
9    3   3
10   3   3
11   3   2
12   3   3
13   4   4
14   4   2
15   4   2
16   4   4
R> ind <- which(with( DF, sub==2 & day==3 ))
R> ind
[1] 5 6 7
R> DF <- DF[ -ind, ]
R> table(DF)
   day
sub 1 2 3 4
  1 0 1 0 3
  2 1 0 0 0
  3 0 1 3 0
  4 0 2 0 2
R> 

sub==2には、day==1

編集複合条件は、次のように「or」を使用して実行できます。

ind <- which(with( DF, (sub==1 & day==2) | (sub=3 & day=4) ))

ここに新しい完全な例があります

R> set.seed(1)
R> DF <- data.frame(sub=rep(1:4, each=5), day=sample(1:4, 20, replace=TRUE))
R> table(DF)
   day
sub 1 2 3 4
  1 1 2 1 1
  2 1 0 2 2
  3 2 1 1 1
  4 0 2 1 2
R> ind <- which(with( DF, (sub==1 & day==2) | (sub==3 & day==4) ))
R> ind
[1]  1  2 15
R> DF <- DF[-ind, ]
R> table(DF)
   day
sub 1 2 3 4
  1 1 0 1 1
  2 1 0 2 2
  3 2 1 1 0
  4 0 2 1 2
R> 
16

dplyrfilter関数を使用した問題の解決策を次に示します。

データフレームをdplyr関数の最初の引数として渡すことができますが、%>%演算子を使用しました。この演算子は、データフレームを1つ以上のdplyr関数にパイプします(この場合はフィルターのみ)。

Dplyrにある程度慣れたら、 cheat sheet は非常に便利です。

> print(df <- data.frame(sub=rep(1:3, each=4), day=1:4))
   sub day
1    1   1
2    1   2
3    1   3
4    1   4
5    2   1
6    2   2
7    2   3
8    2   4
9    3   1
10   3   2
11   3   3
12   3   4
> print(df <- df %>% filter(!((sub==1 & day==2) | (sub==3 & day==4))))
   sub day
1    1   1
2    1   3
3    1   4
4    2   1
5    2   2
6    2   3
7    2   4
8    3   1
9    3   2
10   3   3
9
Ken Lin

シンプルなソリューション

cond1 <- df$sub == 1 & df$day == 2

cond2 <- df$sub == 3 & df$day == 4

df <- df[!cond1,]

df <- df[!cond2,]

2
Ajay Choudhary