2017-03-13 2 views
1

내 데이터 열 각각을 다시 스케일링하고 0에서 100까지의 빈 (bins)에 넣습니다. 빈 열은 모델의 피쳐로 사용됩니다. 개별적으로 각 bin을 테스트하려면 각 bin 열을 각 값에 대해 별도의 열로 분할하고 싶습니다. 새 열은 셀의 값이 열의 빈과 일치하는지 여부에 따라 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 
    } 
} 

많은 감사합니다 !!

편집

이들은 모두 훌륭한 답변입니다, 당신에게 모두 감사합니다. 행렬, 테이블 또는 data.table의 최종 오브젝트는 별도의 bin 컬럼 (소스 컬럼 없음)만을 포함합니다. 아래의 솔루션을 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 개 이상의 열을 가지며 B 열 10 열과 B 열 10 열을 구별 할 수 있어야합니다. 이 기술을 여러 원본 열에서 사용할 수 있습니까? –

+0

예, 원하는대로 붙여 넣기 기능에서 "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 

당신에게 참으로 할 수있다. X이 같은 table : 귀하의 추가 요청에 응답하기

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

편집, 당신과 같이 새 열 이름을 만들 수 있습니다

다음
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와 구별 할 수 있습니까? 또한이 방법을 여러 열에 어떻게 적용 할 수 있습니까? –

관련 문제