2012-05-07 13 views
16

他の2つの変数のうちの1つの値に等しい新しい変数を作成したいと思います。ここに、偽のデータを持つおもちゃの例があります。2つの他の変数の1つの値に条件変数を代入する

データフレームの各行は学生を表します。各生徒は2科目(subj1subj2)まで勉強することができ、各科目で学位( "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 
... 

は、今私はsubj2が一次長であればsubj1は学生の主な主要な、またはsubj2の値である場合subj1の値に等しい第六変数、df$majorを作成したいです。主要なメジャーは学位が "BA"に等しい最初の科目です。私は、次のコードを試してみました:私はこの割り当ては、少なくともためにNAに評価された場合、ベクトル化割り当てが使用できないことを意味想定し

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

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

は残念ながら、私は、エラーメッセージが表示されました1行

私はここで基本的なものを欠いているに違いないと思うが、上記のコードは明らかにそうであるように思え、私は別の方法を考え出すことができなかった。

それが答えを書くには参考になる場合は、ここでのサンプルデータはだ、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") 
+0

degree1とdegree2両方がBAいる行があります。そのような場合、主要なコラムはどうあるべきですか? –

+0

deg1 = "BA"の場合、subj1は主要メジャーです。 deg1!= "BA"&deg2 == "BA"の場合、subj2が主要メジャーです。私が抱えている問題の点では、プライマリメジャーを選択するための特定の条件は、この割り当て方法が失敗する理由ほど重要ではありません。 – eipi10

答えて

26

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

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

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

whichがTRUE

> 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 
あるオブジェクトのインデックスを返しながら違いは、その ==戻り TRUEFALSENAです

2)添え字付きの割り当てを行うときは、右手側が左手側にぴったり収まる必要があります(これは私の考え方です)。これは左右の長さが等しいことを意味します。あなたの例が示唆しているようなものです。 erefore、あなたにも割り当ての右側をサブセットする必要があります:

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

私はあなたの元の試みは、エラーが発生し、なぜそれが明確に願っています。

@DavidRobinsonによって提案されているように、ifelseを使用すると、このタイプの割り当てを行う良い方法です。それが私の感想:

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

これは、ネストされたifelse文の深さに応じて、

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")] 

に相当し、別のアプローチは、あなたの実際のデータのためのより良いかもしれません。


EDIT:

は私が失敗し、元のコード(すなわち、そのdf$majorがまだ割り当てられていなかった)のための第三の理由を書くつもりだったが、それはそれを行うことなく、私のために動作します。これは私が過去に覚えていた問題でした。どのRのバージョンを実行していますか? (私にとっては2.15.0)ifelse()アプローチを使用する場合は、この手順は不要です。 [を使用しているとき、私は、(要因のために相当し、levels(x)[x]を呼び出す)as.character()を使用する代わりに、因子レベルのインデックスの、被験者の文字値を取得するには

df$major <- NA 

を選択しているだろうが、あなたのソリューションは、罰金です。

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)) 
+0

+ 1-良い答え –

+0

まず、詳細な説明はこちら!非常に役立ちます。 – eipi10

+1

第2に、「どの」方法を試したときに、私が期待しなかった結果が得られました。 df $ majorに適切なdf $ subj1の値が設定されていたのに対し、df $ majorには1,2,3のいずれかの番号が割り当てられていました。最初はdf $ subj1の要素に対応していましたが、またはdf $ majorの数値がdf $ subj1の対応する値になった理由。 (私の質問のデータで)実行したものは次のとおりです。df1 $ major [which(df1 $ degree1 == "BA")] < - df1 $ subj1 [df1 $ degree1 == "BA"]] – eipi10

7

ifelse機能が権利でありますこのような状況のための選択、のようなもの:df$degree1df$degree2両方が「BA」であれば

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

はしかし、その正確な使用は、あなたが何をするかに依存します。

+0

デビット、私の実際のデータセットでは、正式にメジャーに入学していない学生も「前メジャー」を持つことができます。学生が専攻前だけを持っている場合、私はその専攻科目として割り当てます。しかし、彼らが前奏曲と大曲の両方を持っているなら、私は彼らの主要なメジャーとしてメジャーを割り当てます。そのような複雑な可能性を扱うために 'ifelse'文を入れ子にすることはできますか? – eipi10

+0

はい:典型的なネストされた例は、 'ifelse(A、B、ifelse(C、D))'のようなものです。 –

+0

(例を挙げればもっと見せてくれるでしょう) –

関連する問題