web-dev-qa-db-ja.com

if_else() `false`は整数ではなくdouble型でなければなりません-R

Dplyrパイプの長い文字列の終わりは

mutate(n = if_else(FiscalYear == "FY2018" & Candy == "SNICKERS", n - 3, n))

このエラーが発生します

_Error in mutate_impl(.data, dots) : Evaluation error: `false` must be type double, not integer.
_

代わりにこれら2つのいずれかを行うと、それはなくなります

mutate(n = ifelse(FiscalYear == "FY2018" & Candy == "SNICKERS", n - 3, n))

mutate(n = if_else(FiscalYear == "FY2018" & Candy == "SNICKERS", n - 3L, n))

簡単な再現可能なレクリエーションを作成するのが最も簡単だと思ったので、以下に示すものを実行しましたが、もうエラーを取得することはできません。何が起こっているのでしょうか? なぜifelseは_if_else_が機能しないのに、なぜ_if_else_は3Lに変更すると機能するのですか?Lを理解しています強制3は整数である、それは正しいですか?

_library(tidyverse)
df <- tribble(
  ~name, ~fruit, ~qty,
  "Bob", "Apple", 10,
  "Bill", "Apple", 10
)

# THIS WORKS AGAIN AS IT SHOULD
df %>% mutate(qty = ifelse(name == "Bob" & fruit == "Apple", qty / 2, qty))

# BUT IF_ELSE DOESN'T FAIL THIS TIME, WEIRD
df %>% mutate(qty = if_else(name == "Bob" & fruit == "Apple", qty / 2, qty))
_
8
stackinator

if_else from dplyrは型が安定しているため、「true」条件と「false」条件が同じ型であるかどうかをチェックします。そうでない場合、if_elseはエラーをスローします。 Base Rのifelseはそれを行いません。

書くとき:

mutate(n = if_else(FiscalYear == "FY2018" & Candy == "SNICKERS", n - 3, n))

nは元々整数型であったため、「false」は整数型であり、n-33がdoubleであるため、trueをdoubleに強制します。 「true」と「false」はタイプが異なるため、if_elseはエラーをスローします。

書くとき:

mutate(qty = if_else(name == "Bob" & fruit == "Apple", qty / 2, qty))

qtyはすでに倍精度である可能性が高いため、倍精度を2(倍精度)で除算しても倍精度が得られます。 「true」と「false」は同じタイプです。したがって、エラーはありません。

とはいえ、これは次のtypeofsで簡単に確認できます。

> typeof(6)
[1] "double"

> typeof(6L)
[1] "integer"

> typeof(6L-3)
[1] "double"

> typeof(6L-3L)
[1] "integer"

> typeof(6/2)
[1] "double"

Base Rのifelseは、すべてを同じ型に変換する暗黙の強制を行います。これは、「true」と「false」のタイプが異なる場合にエラーをスローしないことを意味します。暗黙の強制後に予期しない結果が生じる可能性があるため、これはより便利で危険です。

一時的なプログラムやアドホックプログラムにはifelseを使用し、組み込みの単体テストを利用したい場合にはif_elseを使用することをお勧めします。

18
avid_useR