26

さらに他の変数の値を条件として、他の 2 つの変数のいずれかの値と等しい新しい変数を作成したいと考えています。これは、偽のデータを使用したおもちゃの例です。

データ フレームの各行は生徒を表します。各学生は、最大 2 つの科目 (subj1およびsubj2) を学習することができ、各科目で学位 (「BA」) または副専攻 (「MN」) を取得することができます。私の実際のデータには、数千人の学生、数種類の学位、約 50 の科目が含まれており、学生は最大 5 つの専攻/副専攻を持つことができます。

   ID  subj1 degree1  subj2 degree2
1   1    BUS      BA   <NA>    <NA>
2   2    SCI      BA    ENG      BA
3   3    BUS      MN    ENG      BA
4   4    SCI      MN    BUS      BA
5   5    ENG      BA    BUS      MN
6   6    SCI      MN   <NA>    <NA>
7   7    ENG      MN    SCI      BA
8   8    BUS      BA    ENG      MN
...

次に、6 番目の変数 を作成します。この変数は、 ifが学生の主要な専攻である場合、またはifの値が主要な専攻である場合df$majorに等しくなります。主要な専攻は、「BA」に等しい学位を持つ最初の科目です。次のコードを試しました:subj1subj1subj2subj2

df$major[df$degree1 == "BA"] = df$subj1
df$major[df$degree1 != "BA" & df$degree2 == "BA"] = df$subj2

残念ながら、次のエラー メッセージが表示されました。

> df$major[df$degree1 == "BA"] = df$subj1
Error in df$major[df$degree1 == "BA"] = df$subj1 : 
  NAs are not allowed in subscripted assignments

これは、割り当てが少なくとも 1 つの行で NA と評価される場合、ベクトル化された割り当てを使用できないことを意味すると思います。

ここで何か基本的なことが欠けているように感じますが、上記のコードは当然のことのように思われ、代替案を思いつくことができませんでした。

回答を書くのに役立つ場合は、dput()上記の偽のデータと同じ形式で、 を使用して作成されたサンプル データを次に示します。

structure(list(ID = 1:20, subj1 = structure(c(3L, NA, 1L, 2L, 
2L, 3L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 1L, 3L, 3L, 1L, 2L, 1L
), .Label = c("BUS", "ENG", "SCI"), class = "factor"), degree1 = structure(c(2L, 
NA, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L), .Label = c("BA", "MN"), class = "factor"), subj2 = structure(c(1L, 
2L, NA, NA, 1L, NA, 3L, 2L, NA, 2L, 2L, 1L, 3L, NA, 2L, 1L, 1L, 
NA, 2L, 2L), .Label = c("BUS", "ENG", "SCI"), class = "factor"), 
    degree2 = structure(c(2L, 2L, NA, NA, 2L, NA, 1L, 2L, NA, 
    2L, 1L, 1L, 2L, NA, 1L, 2L, 2L, NA, 1L, 2L), .Label = c("BA", 
    "MN"), class = "factor")), .Names = c("ID", "subj1", "degree1", 
"subj2", "degree2"), row.names = c(NA, -20L), class = "data.frame")
4

2 に答える 2

35

元の割り当て方法は、少なくとも 2 つの理由で失敗しています。

1) 添字付き割り当ての問題df$major[df$degree1 == "BA"] <-。を使用すると、エラー==が発生する可能性がNAあります。From ?"[<-": "置換する場合 (つまり、割り当ての lhs でインデックスを使用する場合)、NA は置換する要素を選択しません。rhs の要素を使用する必要があるかどうかについてあいまいさがあるため、これは次の場合にのみ許可されます。 rhs 値の長さは 1 です (したがって、2 つの解釈は同じ結果になります)。これを回避するには多くの方法がありますが、私は以下を使用することを好みwhichます。

df$major[which(df$degree1 == "BA")] <-

違いは、 、 、およびを==返すことですが、TRUE であるオブジェクトのインデックスを返します。TRUEFALSENAwhich

> df$degree1 == "BA"
 [1] FALSE    NA  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

> which(df$degree1 == "BA")
 [1]  3  4  5  8  9 10 11 12 13 14 15 16 17 18 19 20

2) 添字付きの代入を実行するときは、右側が左側に適切に収まる必要があります (これが私が考える方法です)。これは、同じ長さの左側と右側を意味する可能性があります。これは、あなたの例が暗示しているようです。したがって、割り当ての右側もサブセット化する必要があります。

df$major[which(df$degree1 == "BA")] <- df$subj1[which(df$degree1 == "BA")]

最初の試行でエラーが発生した理由が明確になることを願っています。

@DavidRobinsonifelseによって提案されているように、を使用することは、このタイプの割り当てを行う良い方法です。私の見解:

df$major2 <- ifelse(df$degree1 == "BA", df$subj1, ifelse(df$degree2 == "BA",
  df$subj2,NA))

これは、

df$major[which(df$degree1 == "BA")] <- df$subj1[which(df$degree1 == "BA")]
df$major[which(df$degree1 != "BA" & df$degree2 == "BA")] <- 
  df$subj2[which(df$degree1 != "BA" & df$degree2 == "BA")]

ネストされたステートメントの深さによっては、ifelse実際のデータには別のアプローチが適している場合があります。


編集:

df$major元のコードが失敗する 3 番目の理由 (つまり、まだ割り当てられていない)を書くつもりでしたが、それをしなくてもうまくいきます。しかし、これは私が過去に経験したことを覚えている問題でした。実行している R のバージョンは何ですか? ifelse()(私にとっては 2.15.0 です。)アプローチを使用する場合、この手順は必要ありません。を使用する場合、あなたのソリューションは問題[ありませんが、私は選択したでしょう

df$major <- NA

被験者の特性値を取得するには、因子レベル インデックスの代わりに次を使用しますas.character()(因子の場合は と を呼び出しますlevels(x)[x])。

df$major[which(df$degree1 == "BA")] <- as.character(df$subj1)[which(df$degree1 == "BA")]
df$major[which(df$degree1 != "BA" & df$degree2 == "BA")] <- 
  as.character(df$subj2)[which(df$degree1 != "BA" & df$degree2 == "BA")]

方法も同じですifelse()

df$major2 <- ifelse(df$degree1 == "BA", as.character(df$subj1),
  ifelse(df$degree2 == "BA", as.character(df$subj2), NA))
于 2012-05-07T22:24:56.083 に答える
8

一般に、次のような状況では、ifelse関数が適切な選択です。

df$major = ifelse((!is.na(df$degree1) & df$degree1 == "BA") & (is.na(df$degree2) | df$degree1 != "BA"), df$subj1, df$subj2)

df$degree1ただし、との両方df$degree2が「BA」である場合、その正確な使用方法は、あなたが何をするかによって異なります。

于 2012-05-07T21:52:50.220 に答える