条件付きdplyr評価 に関する議論に基づいて、渡されたデータフレームに参照列が存在するかどうかに応じて、パイプラインでステップを条件付きで実行したいと思います。
_1)
_と_2)
_で生成された結果は同じである必要があります。
_# 1)
mtcars %>%
filter(am == 1) %>%
filter(cyl == 4)
# 2)
mtcars %>%
filter(am == 1) %>%
{
if("cyl" %in% names(.)) filter(cyl == 4) else .
}
_
_# 1)
mtcars %>%
filter(am == 1)
# 2)
mtcars %>%
filter(am == 1) %>%
{
if("absent_column" %in% names(.)) filter(absent_column == 4) else .
}
_
使用可能な列の場合、渡されたオブジェクトは初期データフレームに対応していません。元のコードはエラーメッセージを返します。
filter(cyl == 4)
のエラー:オブジェクト_'cyl'
_が見つかりません
私は別の構文を試しました(運が悪い):
_>> mtcars %>%
... filter(am == 1) %>%
... {
... if("cyl" %in% names(.)) filter(.$cyl == 4) else .
... }
Show Traceback
Rerun with Debug
Error in UseMethod("filter_") :
no applicable method for 'filter_' applied to an object of class "logical"
_
filter
呼び出しの_==
_の右側の評価を説明するこの質問を拡張したいと思いました。たとえば、以下の構文は、最初の使用可能な値でフィルタリングを試みます。 mtcars%>%
_filter({
if ("does_not_ex" %in% names(.))
does_not_ex
else
NULL
} == {
if ("does_not_ex" %in% names(.))
unique(.[['does_not_ex']])
else
NULL
})
_
予想通り、呼び出しはエラーメッセージに評価されます。
filter_impl(.data, quo)
のエラー:結果の長さは0ではなく32でなければなりません
既存の列に適用した場合:
_mtcars %>%
filter({
if ("mpg" %in% names(.))
mpg
else
NULL
} == {
if ("mpg" %in% names(.))
unique(.[['mpg']])
else
NULL
})
_
警告メッセージが表示されます:
_ mpg cyl disp hp drat wt qsec vs am gear carb
1 21 6 160 110 3.9 2.62 16.46 0 1 4 4
_
警告メッセージ:_
{
_の場合:長いオブジェクトの長さは短いオブジェクトの長さの倍数ではありません
filter
呼び出しの右側で条件付き評価を取得するために、既存の構文を拡張して、理想的にはdplyrワークフロー内にとどまる、きちんとした方法はありますか?
ここでスコープが機能するため、if
ステートメント内からデータフレームにアクセスすることはできません。幸いなことに、その必要はありません。
試してください:
mtcars %>%
filter(am == 1) %>%
filter({if("cyl" %in% names(.)) cyl else NULL} == 4)
ここでは、条件内で '.
'オブジェクトを使用できるため、列が存在するかどうかを確認でき、存在する場合は、filter
関数に列を返すことができます。
編集:質問に対するdocendo discimusのコメントに従って、暗黙的にではなくデータフレームにアクセスできます-つまり、.
で具体的に参照する必要があります
私はパーティーに遅れていることを知っていますが、ここでは、あなたが当初考えていたものに少し沿った答えを示します。
mtcars %>%
filter(am == 1) %>%
{
if("cyl" %in% names(.)) filter(., cyl == 4) else .
}
基本的に、filter
に.
がありませんでした。これは、.
で囲まれた式内にあるため、{}
をfilter(expr)
に追加しないためです。
このコードはトリックを実行し、かなり柔軟です。 ^と$は、完全一致を実行するために使用される正規表現です。
mtcars %>%
set_names(names(.) %>%
str_replace("am","1") %>%
str_replace("^cyl$","2") %>%
str_replace("Doesn't Exist","3")
)
編集:残念ながら、これは本当であるには余りにも良かった
パーティーには少し遅れるかもしれません。しかし
mtcars %>%
filter(am == 1) %>%
try(filter(absent_column== 4))
解決策?