web-dev-qa-db-ja.com

論理条件が否定されるdplyrのselect_ifの方法

データフレームからすべての数値列を選択してから、すべての非数値列を選択したいと思います。これを行うための明白な方法は次のとおりです:-

mtcars %>%
    select_if(is.numeric) %>%
    head()

これは私が期待するとおりに機能します。

mtcars %>%
    select_if(!is.numeric) %>%
    head()

これは行われず、エラーメッセージを生成します!is.numericのエラー:無効な引数タイプ

同じことをする別の方法を見てください:-

mtcars %>%
    select_if(sapply(., is.numeric)) %>%
    head()

完璧に動作しますが

mtcars %>%
    select_if(sapply(., !is.numeric)) %>%
    head()

同じエラーメッセージで失敗します。 (purrr :: keepはまったく同じように動作します)。

どちらの場合も、-を使用して不要な列を削除すると失敗し、is.numericバージョンの場合と同じエラーが発生します。 sapplyバージョンエラー:整数ベクトルを関数に変換できません

Is.numericのヘルプページには

is.numericは、内部の汎用プリミティブ関数です。特定のクラスのオブジェクトを処理するメソッドを記述できます。InternalMethodsを参照してください。 ... is.numericのメソッドは、クラスの基本型がdoubleまたはintegerであり、値が数値と合理的に見なされる場合にのみtrueを返す必要があります(たとえば、それらの算術は意味があり、比較は基本型を介して行う必要があります) 。

!のヘルプページ言う

!の場合、xと同じ長さの論理ベクトルまたはrawベクトル(raw xの場合):名前、dim、dimnameがxからコピーされ、強制が行われない場合は他のすべての属性(クラスを含む)がコピーされます。

有用な質問を見てください 否定!dplyrパイプライン内%>% これが機能しない理由のいくつかはわかりますが、どちらの解決策も機能しないことが示唆されています。

mtcars %>%
    select_if(not(is.numeric())) %>%
    head()

妥当なエラーを返しますis.numeric()のエラー:1を必要とする 'is.numeric'に渡される0個の引数。

mtcars %>%
    select_if(not(is.numeric(.))) %>%
    head()

このエラーで失敗します:-tbl_if_vars(.tbl、.predicate、caller_env()、. include_group_vars = TRUE)のエラー:length(.p)== length(tibble_vars)はTRUEではありません

この振る舞いは、驚き最小の原則に間違いなく違反しています。今はそれほど大きな影響はありませんが、もっと根本的なポイントを理解できていないことを示唆しています。

何かご意見は?

9
astaines

述語関数の否定は、(!演算子ではなく)専用のNegate()またはpurrr::negate()関数を使用して実行できます。 、vector)を否定します:

library(dplyr)

mtcars %>% 
  mutate(foo = "bar") %>% 
  select_if(Negate(is.numeric)) %>% 
  head()

#   foo
# 1 bar
# 2 bar
# 3 bar
# 4 bar
# 5 bar
# 6 bar

または(purrr::negate()(小文字)の動作はわずかに異なります。それぞれのヘルプページを参照してください):

library(purrr)
library(dplyr)

mtcars %>% 
  mutate(foo = "bar") %>% 
  select_if(negate(is.numeric)) %>% 
  head()

#   foo
# 1 bar
# 2 bar
# 3 bar
# 4 bar
# 5 bar
# 6 bar
11
Aurèle

独自の「数値ではない」関数を定義して、代わりにそれを使用することができます

is_not_num <- function(x) !is.numeric(x)

mtcars %>%
select_if(is_not_num) %>%
head()
5
Daniel Heemann
mtcars %>%
  select_if(funs(!is.numeric(.))) %>%
  head()

同じことをします

2
Nicolas2