dplyrは条件値で変化します


88

4列の大きなデータフレーム( "myfile")では、最初の4列に基づいて条件付きで値を持つ5番目の列を追加する必要があります。

主に大規模なデータセットでの速度のために、dplyrmutateで回答を優先します。

私のデータフレームは次のようになります。

  V1 V2 V3 V4
1  1  2  3  5
2  2  4  4  1
3  1  4  1  1
4  4  5  1  3
5  5  5  5  4
...

5番目の列(V5)の値は、いくつかの条件付きルールに基づいています。

if (V1==1 & V2!=4) {
  V5 <- 1
} else if (V2==4 & V3!=1) {
  V5 <- 2
} else {
  V5 <- 0
}

次に、mutate関数を使用して、すべての行でこれらのルールを使用します(遅いループを回避するため)。このようなもの(そして、はい、私はそれがこのように機能しないことを知っています!):

myfile <- mutate(myfile, if (V1==1 & V2!=4){V5 = 1}
    else if (V2==4 & V3!=1){V5 = 2}
    else {V5 = 0})

これは結果であるはずです:

  V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

でこれを行う方法はdplyr


V1..4がすべて整数(因数、論理、文字列、浮動小数点数ではない)であるかどうかを述べるのは便利ですか?そして、あなたは正しく扱うことを気にしますかNA、(NaN, +Inf, -Inf)?
SMCI

速度が優先の問題であると思われる場合dplyrは、を使用することをお勧めしますdata.table
バレンティン

回答:


108

これを試して:

myfile %>% mutate(V5 = (V1 == 1 & V2 != 4) + 2 * (V2 == 4 & V3 != 1))

与える:

  V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

またはこれ:

myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, ifelse(V2 == 4 & V3 != 1, 2, 0)))

与える:

  V1 V2 V3 V4 V5
1  1  2  3  5  1
2  2  4  4  1  2
3  1  4  1  1  0
4  4  5  1  3  0
5  5  5  5  4  0

注意

データフレームのより適切な名前を取得することをお勧めします。myfileは、ファイル名を保持しているように見せます。

上記はこの入力を使用しました:

myfile <- 
structure(list(V1 = c(1L, 2L, 1L, 4L, 5L), V2 = c(2L, 4L, 4L, 
5L, 5L), V3 = c(3L, 4L, 1L, 1L, 5L), V4 = c(5L, 1L, 1L, 3L, 4L
)), .Names = c("V1", "V2", "V3", "V4"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5"))

更新1 最初に投稿されたdplyrがに変更さ%.%れた%>%ため、それに応じて回答が変更されました。

Update 2 dplyrcase_whenには、別のソリューションを提供するものがあります。

myfile %>% 
       mutate(V5 = case_when(V1 == 1 & V2 != 4 ~ 1, 
                             V2 == 4 & V3 != 1 ~ 2,
                             TRUE ~ 0))

私はあなたの2番目の解決策を試しました。このエラーが発生しました:mutate_impl(.data、named_dots(...)、environment())のエラー:REAL()は「数値」にのみ適用でき、「論理」には適用できません。何が問題になっているのか知っていますか?
rdatasculptor 2014年

5
私はあなたがifelseステートメントを入れ子にしないことを可能にする方法を発見しました:myfile %>% mutate(V5 = ifelse(V1 == 1 & V2 != 4, 1, 0), V5 = ifelse(V2 == 4 & V3 != 1, 2, V5))
Alex

32

ではdplyr 0.7.2、あなたは非常に便利に使用できるcase_when機能を:

x=read.table(
 text="V1 V2 V3 V4
 1  1  2  3  5
 2  2  4  4  1
 3  1  4  1  1
 4  4  5  1  3
 5  5  5  5  4")
x$V5 = case_when(x$V1==1 & x$V2!=4 ~ 1,
                 x$V2==4 & x$V3!=1 ~ 2,
                 TRUE ~ 0)

で表現するとdplyr::mutate、次のようになります。

x = x %>% mutate(
     V5 = case_when(
         V1==1 & V2!=4 ~ 1,
         V2==4 & V3!=1 ~ 2,
         TRUE ~ 0
     )
)

NA誤解を招く可能性があるため、特別に扱われないことに注意してください。この関数はNA、条件が一致しない場合にのみ返されます。TRUE ~ ...私の例で行ったように、を行にすると、戻り値は決してなりませんNA

したがって、のようなステートメントを追加して、それが属する場所を明示的に指示case_whenする必要があります。ヒント:この関数は、ここで非常に役立つ場合があります。NAis.na(x$V1) | is.na(x$V3) ~ NA_integer_dplyr::coalesce()

さらに、NA通常は単独では機能しないことに注意してください。特別なNA値を入力する必要があります:NA_integer_NA_character_またはNA_real_


1
これは、derivatedFactorよりも大幅に高速でした。
fato39 2017

12

それは次のようになりますderivedFactorからmosaic、このために設計されたパッケージ。この例では、次のようになります。

library(mosaic)
myfile <- mutate(myfile, V5 = derivedFactor(
    "1" = (V1==1 & V2!=4),
    "2" = (V2==4 & V3!=1),
    .method = "first",
    .default = 0
    ))

(結果を因数ではなく数値にしたい場合は、をでラップderivedFactorしますas.numeric。)

.defaultと組み合わせたオプション.method = "first"は「else」条件を設定することに注意してください。このアプローチは、のヘルプファイルで説明されていますderivedFactor


.asFactor = Fオプションを使用するかderivedVariable、同じパッケージ内の(類似の)関数を使用して、結果が要因になるのを防ぐこともできます。
ジェイクフィッシャー

以下のように見えますrecodedplyr 0.5からこれを行います。まだ調べていません。blog.rstudio.org/2016/06/27/dplyr-0-5-0
Jake Fisher

これは、1e6行のデータでは低速でした。
fato39 2017

3
@ Fato39はい、mosaic::derivedFactor関数のファミリーは非常に遅いです。理由がわかったら、それについての私のSOの質問に答えてください:stackoverflow.com/questions/33787691/…。私はあなたの他のコメントからdplyr::case_whenより速いのを見てうれしいです-私はそれに切り替える必要があります。
ジェイクフィッシャー

次のコマンドを試しています。library(mosaic)VENEZ.FINAL2 <-mutate(VENEZ、SEX = definedFactor( "M" =(CATEGORY == "BULL"&CATEGORY!= "SIRE")、 "F" =( CATEGORY == "COW"&CATEGORY!= "HEIFER")、. method = "first"、。default = "NA"))ただし、機能しません。条件VENEZ.FINAL2 <-mutate(VENEZ、 SEX = derivedFactor( "M" =(CATEGORY ==「BULLあなたはどうもありがとう私を助けてもらえますか?!
ヨハンナ・ラミレス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.