0

バックグラウンド

dplyr パイプラインの一部である別の関数内から呼び出される、計算コストの高い (およびSLOW ) 関数があります。

dat %>%
mutate_at(.vars = vars(dplyr::intersect(starts_with("locale"), ends_with("last_name"))), 
          .funs = funs(native_last_name_alpha(., Type))) %>% 
          {.} -> dat

Typeこの関数は、変数(文字列) が「男性」または「女性」のどちらに一致するかによって、2 つのいずれかを実行します。一致する場合はnative_last_name_alpha、計算コストが高く遅い関数が実行され、他の処理が実行されます。一致しない場合は、native_last_name_alphaを返しNAます。現在、これはベクトル化されているため、何が起こるべきかを判断するためにif_elseandを使用しcase_whenています。たとえば、次のようになります。

native_last_name_alpha <- function(locale, type) {
  case_when(
    type == "male" ~ stringi::stri_trans_toupper(
      fake_single_alpha(locale = locale, 
                        request = "last_name_male", 
                        provider = "faker.providers.person")
    ),
    type == "female" ~ stringi::stri_trans_toupper(
      fake_single_alpha(locale = locale, 
                        request = "last_name_female", 
                        provider = "faker.providers.person")
    ),
    TRUE ~ NA_character_
  )
}

TRUE問題は、条件がまたはに評価されるかどうかに関係なく、高価な関数が実行されるFALSEことです。これにより、スクリプトの実行が非常に遅くなります。

if_else、ifelse、および case_when を深く掘り下げる

ベクトル化された if/else ステートメントif_elseifelse(and case_when) は、従来の if...else ステートメントのようには機能しないことを理解しています。ステートメントのすべての部分が評価され、次に条件を使用して、返される結果がつなぎ合わされます。たとえば、このコードは次の出力と警告を生成します。

v <- c(-100, -10, 10, 100)
ifelse(v > 0, log10(v), log10(-v))

[1] 2 1 1 2

警告メッセージ:

1: ifelse(v > 0, log10(v), log10(-v)) : 生成された NaN

2: ifelse(v > 0, log10(v), log10(-v)) の場合: NaN が生成される

条件が true の場合の戻り値と条件が false の場合の戻り値の両方が評価され、条件を使用して結果のベクトルが結合されます。

その結果、高価で遅い関数が実際に必要な回数よりも多く実行されています。

どうすればこれを回避できますか?

私が欲しいもの

私は、条件が true の場合に true の場合のみ結果を評価するif_elseandの代替のベクトル化された実装を探しています。case_when

これまでに試したこと

if_else/の独自のベクトル化された実装を作成しようとしましifelseたが、成功しませんでした。非標準評価も試しましたが、これを機能させるのに十分な知識がありません。if_else評価されていない式を返すことができ、後で適切なタイミングで評価することができれば(フリーズドライ関数呼び出しのようなもの)、これが解決策の一部になる可能性があると推測しています。しかし、今のところ喜びはありません。

やりたいことを簡単にするために見逃したことはありますか?または、誰かが実装に関するヒントを提供できますか? ありがとう!

4

0 に答える 0