web-dev-qa-db-ja.com

論理を使用したdplyrselect

Dplyrのselectを論理ベクトルで使用できますか?

_dat <- tbl_df(mtcars)
isNum <- sapply(dat, is.numeric)
select(dat, isNum)
_
_select(dat, isNum)
_

名前のエラー(sel)[unnamed] <-sel [unnamed]:添え字付きの割り当てではNAは許可されていません

インデックスは機能します:select(dat,(1:ncol(dat))[isNum])では、なぜ論理的ではないのですか?

_starts_with_ select(dat,starts_with("m"))のようなselectのヘルパー関数を見たとき、それらは論理的に機能すると思いました...

22
Vincent

私の答えは次のようになります。

  • いいえ(「dplyrで選択して論理ベクトルで使用できますか?」)

証拠 :( 1)あなたの例、(2)ヘルプページ:

...:引用符で囲まれていない式のコンマ区切りリスト。変数名は位置のように扱うことができます。正の値を使用して変数を選択します。負の値を使用して変数を削除します。

論理ベクトルについては何も言いません。ごめんなさい。

  • わからない(「なぜ論理的ではないのか?」)-「理由だけで」(開発者以外の誰もが本当にこれに答えることができるとは思わない)。あなたは機能リクエストを入れることができます...

少し不格好ですが

select_(dat,.dots=names(isNum)[isNum])

動作します(文字ベクトルを使用できるようにするには、select_バリアントが必要であることに注意してください)。でも古き良き

subset(dat,select=isNum)

(私が考えていなかった他の方法でdplyrとうまく機能しない場合を除いて)、うまく機能しているようです。

dplyr:::starts_withのコードを見ると、論理ベクトルではなく、位置のベクトルを返していることがわかります。

function (vars, match, ignore.case = TRUE) 
{
    stopifnot(is.string(match), !is.na(match), nchar(match) > 
        0)
    if (ignore.case) 
        match <- tolower(match)
    n <- nchar(match)
    if (ignore.case) 
        vars <- tolower(vars)
    which(substr(vars, 1, n) == match)
}

この関数を変更してis_numericに相当するものを作成することをお勧めしますが、基礎となる魔法を十分に理解していません...

12
Ben Bolker

ベンが提案したように:

select(dat, which(isNum))

24
Vincent

他の回答で非常に明確に述べられているように、あなたの特定の質問への回答はnoです。 dplyr::select()で論理ベクトルを使用することはできません。

ただし、dplyrの最近のバージョン(v> = 0.5.0)には、列または論理ベクトルに適用される述語関数の使用をサポートする新しい関数がありますselect_if()

述語関数でselect_ifを使用すると、例を次のように簡略化できます。

tbl_df(mtcars) %>% dplyr::select_if(is.numeric)

ただし、論理ベクトルでselect_ifを使用することもできます。これは、次のような上記のユースケースに直接対応します。

dat <- tbl_df(mtcars)
isNum <- sapply(dat, is.numeric)
select_if(dat, isNum)
4
jackinovik