2016-08-19 4 views
1

2種類の情報(X#とY#)を含むデータフレームがあるとします。私は深く((各列は3つの1/3を含むカテゴリまたは列に分割されている)9つのカテゴリにグループにそれらを(X1及びY1以下)は、2つの列を使用して新しい列cat11に格納R - ハードコードされたスクリプトから関数への移動

df = data.frame(matrix(rnorm(600), nrow=100)) 
colnames(df) <- c("X1", "X2", "Y1", "Y2", "Y3", "Y4") 

私があなたに示す貧弱なコードをお詫びしますが、私はRのちょうど初心者です)。私は今のに苦労しています何

df$tmpx <- cut2(df$X1, g=3) 
levels(df$tmpx) <- c(1,2,3) 
df$tmpy <- cut2(df$Y1, g=3) 
levels(df$tmpy) <- c(1,2,3) 

enum <- 1 
for (x in sort(unique(df$tmpx))) 
{ 
    for (y in sort(unique(df$tmpy))) 
    { 
    print(enum) 
    df$cat11[df$tmpx == x & df$tmpy == y] <- enum 
    enum <- enum + 1 
    } 
} 

は、他の組み合わせの選択(; X2、Y1> cat21; X2、Y3> cat23例えばX1、Y4> cat14)のために、このコードを実行することです。

私は、機能だけでなく、礼儀正しく使うことを試みてきましたが、まだ成功していません。私は何かが明らかに欠けていると思う。

ご協力いただければ幸いです。

答えて

1

まず、私はXとYの列のすべての組み合わせを作成:

combs <- expand.grid(names(df)[grep("X", names(df))], 
        names(df)[grep("Y", names(df))], 
        stringsAsFactors = FALSE) 
# Var1 Var2 
#1 X1 Y1 
#2 X2 Y1 
#3 X1 Y2 
#4 X2 Y2 
#5 X1 Y3 
#6 X2 Y3 
#7 X1 Y4 
#8 X2 Y4 

その後、私はあなたのアプローチへのベクトル化の代替を書き、関数内でそれをラップ:私は[[を使用する方法

library(Hmisc) 
fun <- function(DF, col1, col2) { 
    tmpx <- cut2(df[[col1]], g=3) 
    tmpx <- as.integer(tmpx) 

    tmpy <- cut2(df[[col2]], g=3) 
    tmpy <- as.integer(tmpy) 

    (tmpx - 1) * 3 + tmpy #some simple maths 
} 

注意をプログラムで文字列として与えられた列を抽出します。これには$を使用することはできません(これはよくある質問です)。研究help("[")を調査してください。

それから私は、すべての組み合わせに関数を適用するmapplyを使用します。

df[, paste0("cat", 
      gsub("[[:alpha:]]*", "", combs[,1]), 
      gsub("[[:alpha:]]*", "", combs[,2]))] <- mapply(fun, combs[,1], combs[,2], 
                  MoreArgs = list(DF = df)) 

mapplyは、その引数のすべての要素に対してループし、それらに機能を適用します。たとえば、関数はX1/Y1、X2/Y1に適用されます。

最も複雑な部分は列名を作成しています。私はここで単純な正規表現を使用し、combsで与えられた列名からすべての文字を削除します。

+0

これは非常に洗練されたソリューションです。簡単な質問: 'fun'の中で、' df [、col1] 'の代わりに 'df [、col1]'を使って列をプログラム的に抽出するのに違いはありますか? – thepule

+1

いいえ、どちらもうまくいくでしょう(後者はやや効率的です)。 – Roland

+0

Rolandさん、ありがとうございました。私はまだ質問があります。なぜあなたは関数内に "ライブラリ(Hmisc)"を置いたのですか? – user3541159

関連する問題