2017-03-13 13 views
1

データの各列は再スケーリングされ、0から100までのビンに入れられます。ビン列はモデルのフィーチャとして使用されます。それぞれのビンを別々にテストするために、私は各ビンの列をその値ごとに別々の列に分割したいと思います。新しい列は、セル内の値が列のビンと一致するかどうかによって、0または1のいずれかを保持します。これに複数の列の個別の列に一意の値を分割する

row values 
    1  10 
    2  20 
    3  30 
    4  40 
    5  10 
    6  30 
    7  40 

row values_10 values_20 values_30 values_40 
    1   1   0   0   0 
    2   0   1   0   0 
    3   0   0   1   0 
    4   0   0   0   1 
    5   1   0   0   0 
    6   0   0   1   0 
    7   0   0   0   1 

この強引なアプローチは、仕事をしていませんが、より良い(非ループ)方法がなければならない:

values <- c(10,20,30,40,10,30,40) 
dat <- data.frame(values) 

columnNames <- unique(dat$values) 

for(n in 1:length(columnNames)) 
{ 
    dat[as.character(columnNames[n])] <- 0 
} 

columnNames2 <- colnames(dat) 

for(c in 2:ncol(dat)) 
{ 
    hdr <- columnNames2[c] 

    for(r in 1:nrow(dat)) 
    { 
     if(dat$values[r]==as.integer(hdr)) 
      dat[r,c]=1 
    } 
} 

このようなものから、どうもありがとう!!

EDIT

これらはすべての偉大な答えですが、あなたにみんなに感謝します。行列、テーブル、またはデータテーブルのいずれの最終オブジェクトにも、個別のビン列(ソース列なし)のみが含まれます。以下のソリューションは、2000年以上のソース列でどのように使用できますか?以下の私のフォローアップの質問への回答に基づいて

EDIT2

は、将来的にこの質問に来る人のための各方法の実装です。

# read in some data with multiple columns 

df_in <- read.table(text="row val1 val2 
        1  10  100 
        2  20  200 
        3  30  300 
        4  40  400 
        5  10  100 
        6  30  300 
        7  40  400", header=TRUE, stringsAsFactors=FALSE) 

# @Zelazny7 's method using a matrix 

df_in$row <- NULL 

col_names <- names(df_in) 

for(c in 1:length(col_names)){ 

    uniq <- unlist(unique(df_in[col_names[c]])) 

    m <- matrix(0, nrow(df_in), length(uniq), 
       dimnames = list(NULL, paste0(col_names[c], "_", uniq))) 

    for (i in seq_along(df_in[[col_names[c]]])) { 
     k <- match(df_in[[col_names[c]]][i], uniq, 0) 
     m[i,k] <- 1 
    } 

    if(c==1) 
     df_out <- m 
    else 
     df_out <- cbind(df_out,m) 
} 


# @P Lapointe 's method using 'table' 

col_names <- names(df_in) 

for(c in 2:length(col_names)){ 

    m <- table(df_in$row,df_in[[col_names[c]]])  
    uniq <- unlist(unique(df_in[col_names[c]])) 
    newNames <- toString(paste0(col_names[c],'_',uniq)) 

    if(c==2){ 
     df_out <- m 
     hdrs <- newNames 
    } 
    else{ 
     df_out <- cbind(df_out,m) 
     hdrs <- paste(hdrs,newNames,sep=", ") 
    } 
} 

colnames(df_out) <- unlist(strsplit(hdrs, split=", ")) 


# @bdemarest 's method using 'data.table' 
# read in data first 

library(data.table) 

df_in = fread("row val1 val2 
      1  10  100 
      2  20  200 
      3  30  300 
      4  40  400 
      5  10  100 
      6  30  300 
      7  40  400") 

df_in$count = 1L 

col_names <- names(df_in) 

for(c in 2:length(col_names)-1){ 

    m = dcast(df_in, paste('row', '~', col_names[c]), value.var="count", fill=0L) 

    uniq <- unlist(unique(df_in[,get(col_names[c])])) 
    newNames <- toString(paste0(col_names[c],'_',uniq)) 

    m$row <- NULL 

    if(c==2){ 
     df_out <- m 
     hdrs <- newNames 
    } 
    else if(c>2){ 
     df_out <- cbind(df_out,m) 
     hdrs <- paste(hdrs,newNames,sep=", ") 
    } 
} 

colnames(df_out) <- unlist(strsplit(hdrs, split=", ")) 

すべての回答は適切かつ有用であり、最善の回答が最も早い初期応答に与えられました。もう一度あなたの助けに感謝します!

+1

dcast' – mtoto

+4

ダミー列を別々に作成するのではなく、 'cut'を使用してデータの単一の列を因子カテゴリにグループ化することができます(この場合は、順序付け因子が必要です)。 Rのモデル関数は、一般に、モデルに因子列を含めると自動的にダミー列を作成します。もしそうでなければ、 'model.matrix'を使ってダミーカラムを作ることができます。しかし、それはデータをグループ化することが理にかなっていますか?それはちょうど情報を捨てないのですか? – eipi10

+1

これは、あなたが探している行列の基本構造を取得します: 'df $ I = 1; t(tidyr :: spread(df、key = row、value = I))' – Vlo

答えて

2

私はこれを非常に頻繁に行います。これは私がダミーを作るために使う方法です。それは非常に速いです。

## reading in your example data 
df <- read.table(file = "clipboard", header=TRUE) 
df$row <- NULL 

uniq <- unique(df$values) 
m <- matrix(0, nrow(df), length(uniq), dimnames = list(NULL, paste0("column_", uniq))) 

for (i in seq_along(df$values)) { 
    k <- match(df$values[i], uniq, 0) 
    m[i,k] <- 1 
} 

と結果:

> m 
    column_10 column_20 column_30 column_40 
[1,]   1   0   0   0 
[2,]   0   1   0   0 
[3,]   0   0   1   0 
[4,]   0   0   0   1 
[5,]   1   0   0   0 
[6,]   0   0   1   0 
[7,]   0   0   0   1 

行列と行列のインデックスを作成することにより、ループを回避別の変形:

m[cbind(seq.int(nrow(m)), match(df$values, uniq))] <- 1 
+0

ありがとう!私はあなたがラベルとビンで列の名前を変更する方法を組み込んでいるのが好きです。私のソースデータは2000以上のカラムを持ち、カラムAのビン10とカラムBのビン10などを区別することができ、必須です。この手法を複数のソース列で使用できますか? –

+0

はい、 'paste'関数の" column_ "をあなたの望むものに置き換えてください。 'var1_'のようなものです。 – Zelazny7

1

使用table

df1 <- read.table(text="row values 
    1  10 
    2  20 
    3  30 
    4  40 
    5  10 
    6  30 
    7  40", header=TRUE, stringsAsFactors=FALSE) 

    table(df1) 

    values 
row 10 20 30 40 
    1 1 0 0 0 
    2 0 1 0 0 
    3 0 0 1 0 
    4 0 0 0 1 
    5 1 0 0 0 
    6 0 0 1 0 
    7 0 0 0 1 

ます確かにできるこのようなtable×:あなたの追加の要求に答えるために

table(df1)[5,1] 
[1] 1 

EDIT を、あなたはそうのような新しいカラム名を作ることができます:ここでは

tbl <-table(df1) 
out<-as.data.frame.matrix(tbl) #to transform into a data.frame 
colnames(out) <-make.names(colnames(out)) #to make new column names 
out 
    X10 X20 X30 X40 
1 1 0 0 0 
2 0 1 0 0 
3 0 0 1 0 
4 0 0 0 1 
5 1 0 0 0 
6 0 0 1 0 
7 0 0 0 1 
+0

これは素晴らしい、素敵でシンプルです、ありがとう!ソースデータには2000以上の列があり、それぞれがこの方法で分割されます。新しい列名にラベルを含めるようにメソッドを変更できるので、列Aのビンは列Bと区別できますか?また、これを複数の列にどのように適用できますか? –

+0

ラベルを挿入している場合、列名を変更することを意味します。上記の私の編集を参照してください。 –

1

data.tableソリューションです。最初にcount列を追加してから、幅広い形式に変更してdcast()とします。ところで、これは1000万行以上のデータを使用するのに十分速いです。

library(data.table) 

tab = fread("row values 
    1  10 
    2  20 
    3  30 
    4  40 
    5  10 
    6  30 
    7  40") 

tab$count = 1L 

res = dcast(tab, row ~ values, value.var="count", fill=0L) 
res 
# row 10 20 30 40 
# 1: 1 1 0 0 0 
# 2: 2 0 1 0 0 
# 3: 3 0 0 1 0 
# 4: 4 0 0 0 1 
# 5: 5 1 0 0 0 
# 6: 6 0 0 1 0 
# 7: 7 0 0 0 1 
+0

ありがとうございますdata.tableソリューションを提供しています!ソースデータには2000以上の列があり、それぞれがこの方法で分割されます。新しい列名にラベルを含めるようにこのメソッドを変更できるため、列Aのビンは列Bと区別できますか?また、これを複数の列にどのように適用できますか? –

関連する問題