web-dev-qa-db-ja.com

dplyrの文字列列で複数の値をフィルター処理する

列の1つに文字データを持つdata.frameがあります。同じ列からdata.frameの複数のオプションをフィルター処理したいと思います。これを行う簡単な方法はありますか?

例:data.frame name = dat

days      name
88        Lynn
11          Tom
2           Chris
5           Lisa
22        Kyla
1          Tom
222      Lynn
2         Lynn

たとえば、TomLynnを除外したいと思います。
私がする時:

target <- c("Tom", "Lynn")
filt <- filter(dat, name == target)

私はこのエラーを受け取ります:

longer object length is not a multiple of shorter object length
57
Tom O

%in%の代わりに==が必要です:

library(dplyr)
target <- c("Tom", "Lynn")
filter(dat, name %in% target)  # equivalently, dat %>% filter(name %in% target)

生産する

  days name
1   88 Lynn
2   11  Tom
3    1  Tom
4  222 Lynn
5    2 Lynn

理由を理解するために、ここで何が起こるかを考えてください。

dat$name == target
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

基本的に、2つの長さのtargetベクトルを4回リサイクルして、dat$nameの長さに一致させています。つまり、次のことを行っています。

 Lynn == Tom
  Tom == Lynn
Chris == Tom
 Lisa == Lynn
 ... continue repeating Tom and Lynn until end of data frame

この場合、データフレームには実際にはリサイクルを許可しない行の数が異なると思われるため、エラーは発生しませんが、提供するサンプル(8行)にはあります。サンプルの行数が奇数だった場合、同じエラーが発生していました。しかし、リサイクルが機能する場合でも、これは明らかにあなたが望むものではありません。基本的に、ステートメントdat$name == targetは次のことと同等です:

「Tom」に等しいすべての奇数値または「Lynn」に等しいすべての偶数値に対してTRUEを返します。

サンプルデータフレームの最後の値が偶数で「Lynn」に等しいため、上記のTRUEになります。

対照的に、dat$name %in% targetは次のように言います。

dat$nameの各値について、targetに存在することを確認してください。

非常に異なります。結果は次のとおりです。

[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE

あなたの問題はdplyrとは関係がなく、単に==の誤用に注意してください。

156
BrodieG

これは、CRANで利用可能なdplyrパッケージを使用して実現できます。これを達成する簡単な方法:

  1. dplyrパッケージをインストールします。

  2. library(dplyr) df<- select(filter(dat,name=='tom'| name=='Lynn',c('days','name))

説明:

したがって、dplyrをダウンロードしたら、このパッケージの2つの異なる関数を使用して新しいデータフレームを作成します。

フィルター:最初の引数はデータフレームです。 2番目の引数は、サブセット化する条件です。結果は、必要な行のみを含むデータフレーム全体です。選択:最初の引数はデータフレームです。 2番目の引数は、そこから選択する列の名前です。 names()関数を使用する必要はなく、引用符を使用する必要もありません。列名をオブジェクトとしてリストするだけです。

9
AutomationNerd

baseパッケージの使用:

df <- data.frame(days = c(88, 11, 2, 5, 22, 1, 222, 2), name = c("Lynn", "Tom", "Chris", "Lisa", "Kyla", "Tom", "Lynn", "Lynn"))

# Three lines
target <- c("Tom", "Lynn")
index <- df$name %in% target
df[index, ]

# One line
df[df$name %in% c("Tom", "Lynn"), ] 

出力:

  days name
1   88 Lynn
2   11  Tom
6    1  Tom
7  222 Lynn
8    2 Lynn

sqldfの使用:

library(sqldf)
# Two alternatives:
sqldf('SELECT *
      FROM df 
      WHERE name = "Tom" OR name = "Lynn"')
sqldf('SELECT *
      FROM df 
      WHERE name IN ("Tom", "Lynn")')
8
mpalanco