2016-08-18 4 views
1

for 루프로 쉽게 해결할 수있는 질문이 있습니다. 그러나 데이터 프레임에 수십만 행이 있기 때문에 계산 시간이 매우 오래 걸리므로 빠르고 효율적인 솔루션을 찾고 있습니다. 제 dataframe의 각 행에 대해 각 행에 대해 셀의 다른 값과 일치하는 열 이름의 값을 추출하십시오.

는, I는 그 열 이름 (INDEX) 첫 번째 열 중 하나와 일치

dataframe이

> mydata 
    INDEX 1 2 3 4 5 6 
1  2 18.9 9.5 22.6 4.7 16.2 7.4 
2  2 18.9 9.5 22.6 4.7 16.2 7.4 
3  2 18.9 9.5 22.6 4.7 16.2 7.4 
4  4 18.9 9.5 22.6 4.7 16.2 7.4 
5  4 18.9 9.5 22.6 4.7 16.2 7.4 
6  5 18.9 9.5 22.6 4.7 16.2 7.4 

같다 셀의 값을 붙여하고자 여기를 재생 코드입니다 :

mydata <- data.frame(INDEX=c(2,2,2,4,4,5), ONE=(rep(18.9,6)), TWO=(rep(9.5,6)), 
        THREE=(rep(22.6,6)), FOUR=(rep(4.7,6)), FIVE=(rep(16.2,6)), SIX=(rep(7.4,6))) 
colnames(mydata) <- c("INDEX",1,2,3,4,5,6) 

는 그리고이 새로 계산 된 변수를 사용하여 새로운 dataframe입니다 :

,
> new_mydf 
    INDEX 1 2 3 4 5 6 VARIABLE 
3  2 18.9 9.5 22.6 4.7 16.2 7.4  9.5 
2  2 18.9 9.5 22.6 4.7 16.2 7.4  9.5 
1  2 18.9 9.5 22.6 4.7 16.2 7.4  9.5 
5  4 18.9 9.5 22.6 4.7 16.2 7.4  4.7 
4  4 18.9 9.5 22.6 4.7 16.2 7.4  4.7 
6  5 18.9 9.5 22.6 4.7 16.2 7.4  16.2 

여기서는 for 루프를 사용하여 해결했지만, 위에서 썼 듯이 루프는 다음과 같이 단순 솔루션 (어쩌면 dplyr이나 다른 함수를 사용하고 있습니까?)을 찾고 있습니다.

mydata$VARIABLE<-apply(mydata, 1, function(x) { x[names(x)==x[names(x)=="INDEX"]] }) 

편집 : 내 확장 된 데이터 세트에 대한 느린 루프를 바탕으로

id = mydata$INDEX 
new_mydf <- data.frame() 
for (i in 1:length(id)) { 
    mydata_row <- mydata[i,] 
    value <- mydata_row$INDEX 
    mydata_row["VARIABLE"] <- mydata_row[,names(mydata_row) == value] 
    new_mydf <- rbind(mydata_row,new_mydf) 
} 
new_mydf <- new_mydf[ order(new_mydf[,1]), ] 
+0

는이있다 : http://stackoverflow.com/q/33310179/ – Frank

+0

감사합니다. data.table의 솔루션은 잘 작동합니다! – refroll

답변

1

, 익명 함수와 apply의 사용은 (당신의 mydata 초기 정의와) 더 빠를 수 있습니다 그리고 그것은 심지어 작동 0 문자 1,238,451,918,849,이 빠르게 apply보다 것이다, 지수와 부분 집합을 사용

new_mydf <- data.frame(mydata, 
         VARIABLE=mydata[cbind(seq_len(nrow(mydata)), 
              match(as.character(mydata$INDEX),colnames(mydata)))]) 

:

mydata <- data.frame(INDEX=c("B","B","B","D","D","E"), "A"=(rep(18.9,6)), "B"=(rep(9.5,6)), 
       "C"=(rep(22.6,6)), "D"=(rep(4.7,6)), "E"=(rep(16.2,6)), "F"=(rep(7.4,6))) 

mydata$VARIABLE<-apply(mydata, 1, function(x) { x[names(x)==x[names(x)=="INDEX"]] }) 

> mydata INDEX A B C D E F VARIABLE 1 B 18.9 9.5 22.6 4.7 16.2 7.4 9.5 2 B 18.9 9.5 22.6 4.7 16.2 7.4 9.5 3 B 18.9 9.5 22.6 4.7 16.2 7.4 9.5 4 D 18.9 9.5 22.6 4.7 16.2 7.4 4.7 5 D 18.9 9.5 22.6 4.7 16.2 7.4 4.7 6 E 18.9 9.5 22.6 4.7 16.2 7.4 16.2

+0

감사합니다.이 솔루션은 잘 작동합니다. 그러나 원래의 확장 된 데이터 프레임에서는 "1", "2"등이 아닌 문자를 사용하여 열의 이름을 바꿔야했습니다. – refroll

+0

오신 것을 환영합니다. 당신을 도와 주셔서 감사합니다! @aichao 하위 집합 솔루션은 훌륭하고 매우 빠릅니다! 매우 큰 데이터 세트를 가지고 있다면 더 나은 사용법이 될 수 있습니다. 인자 (INDEX)를 사용하여 문자 색인에 쉽게 적용될 수 있다고 생각하십니까? – Toshiro

+0

@Toshiro : 일치하도록 'match'로 답변을 업데이트했습니다. 열 이름에 대한 'INDEX'의 데이터. – aichao

1

당신이 원하는 것은하여 수행 할 수 있습니다. 예를 들어, 데이터 세트 인 경우 :

INDEX Alpha Beta Charlie Delta Epsilon Foxtrot 
1 Beta 18.9 9.5 22.6 4.7 16.2  7.4 
2 Beta 18.9 9.5 22.6 4.7 16.2  7.4 
3 Beta 18.9 9.5 22.6 4.7 16.2  7.4 
4 Delta 18.9 9.5 22.6 4.7 16.2  7.4 
5 Delta 18.9 9.5 22.6 4.7 16.2  7.4 
6 Epsilon 18.9 9.5 22.6 4.7 16.2  7.4 

이 줄 것이다 : 벤치 마크

INDEX Alpha Beta Charlie Delta Epsilon Foxtrot VARIABLE 
1 Beta 18.9 9.5 22.6 4.7 16.2  7.4  9.5 
2 Beta 18.9 9.5 22.6 4.7 16.2  7.4  9.5 
3 Beta 18.9 9.5 22.6 4.7 16.2  7.4  9.5 
4 Delta 18.9 9.5 22.6 4.7 16.2  7.4  4.7 
5 Delta 18.9 9.5 22.6 4.7 16.2  7.4  4.7 
6 Epsilon 18.9 9.5 22.6 4.7 16.2  7.4  16.2 

, 시뮬레이션 큰 데이터 세트를 : data.table와

## simulate some data with 1000 columns and 1000 rows 
INDEX <- ceiling(runif(1000,0,1000)) 
data <- rep(runif(1000,0,1), each=1000) 
mydata <- data.frame(INDEX=INDEX,matrix(data,nrow=1000)) 
colnames(mydata) <- c("INDEX", seq_len(1000)) 

## using indexing 
system.time(new_mydf <- data.frame(mydata, VARIABLE=mydata[cbind(seq_len(nrow(mydata)),match(as.character(mydata$INDEX),colnames(mydata)))])) 
## user system elapsed 
## 0.030 0.001 0.031 

## using apply 
system.time(mydata$VARIABLE<-apply(mydata, 1, function(x) { x[names(x)==x[names(x)=="INDEX"]] })) 
## user system elapsed 
## 0.268 0.010 0.291 

## check that we computed the same thing 
all.equal(mydata,new_mydf,check.names=FALSE) 
##[1] TRUE