2014-01-21 4 views
1

거대한 데이터 프레임 (180000 x 400)을 사용하여 훨씬 더 작은 다른 데이터 프레임을 계산하려고합니다.다른 데이터 프레임을 기반으로 새 데이터 프레임을 만듭니다.

나는 다음과 같은 dataframe

df1=data.frame(LOCAT=c(1,2,3,4,5,6),START=c(120,345,765,1045,1347,1879),END=c(150,390,802,1120,1436,1935),CODE1=c(1,1,0,1,0,0),CODE2=c(1,0,0,0,-1,-1)) 

df1 
    LOCAT START END CODE1 CODE2 
1  1 120 150  1  1 
2  2 345 390  1  0 
3  3 765 802  0  0 
4  4 1045 1120  1  0 
5  5 1347 1436  0 -1 
6  6 1879 1935  0 -1 

이 샘플 dataframe입니다 있습니다. 행은 1800 년까지 계속되고 열은 400을 넘습니다. 각 행의 크기가 "1"또는 "-1"을 계속 표시하고 위치를 반환하는 각 열을 기반으로 새 데이터 프레임을 만드는 것이 필요합니다. 크기와 가치. 코드 1이 같은

뭔가 :

LOCAT SIZE VALUE 
1 1 to 2 270 POS 
2 4 to 4 75 POS 

그리고 CODE2이 같은

:
LOCAT SIZE VALUE 
1 1 to 1 30 POS 
2 5 to 6 588 NEG 

불행하게도 난 아직이 작업을 수행하는 방법을 알아낼하지 않았다. 나는 이것을 자동으로 수행하는 함수를 개발하기 위해 몇 줄의 코드를 시도해 왔지만 길을 잃거나 루프에 갇히기 시작했다.

도움을 주시면 감사하겠습니다. 미리 감사드립니다.

답변

3

다음은 "시작"및 "중지"라는 제목의 두 열로 "LOCAT"열을 나눈 것을 제외하고는 원하는 형식으로 답변을 제공하는 코드입니다. 이 코드는 전체 데이터 프레임에서 작동하므로 각 CODE (CODE1, CODE2 등)에 대해 수동으로 복제 할 필요가 없습니다.

코드가 아닌 열만 "LOCAT" "START"및 "END"라는 이름을 가진 것으로 가정합니다.

# need package "plyr" 
library("plyr") 

# test2 is the example data frame that you gave in the question 
test2 <- data.frame(
    "LOCAT"=1:6, 
    "START"=c(120,345,765, 1045, 1347, 1879), 
    "END"=c(150,390,803,1120,1436, 1935), 
    "CODE1"=c(1,1,0,1,0,0), 
    "CODE2"=c(1,0,0,0,-1,-1) 
    ) 

codeNames <- names(test2)[!names(test2)%in%c("LOCAT","START","END")] # the names of columns that correspond to different codes 
test3 <- reshape(test2, varying=codeNames, direction="long", v.names="CodeValue", timevar="Code") # reshape so the different codes are variables grouped into the same column 
test4 <- test3[,!names(test3)%in%"id"] #remove the "id" column 

sss <- function(x){ # sss gives the starting points, stopping points, and sizes (sss) in a data frame 
    rleX <- rle(x[,"CodeValue"]) # rle() to get the size of consecutive values 
    stops <- cumsum(rleX$lengths) # cumulative sum to get the end-points for the indices (the second value in your LOCAT column) 
    starts <- c(1, head(stops,-1)+1) # the starts are the first value in your LOCAT column 
    ssX0 <- data.frame("Value"=rleX$values, "Starts"=starts, "Stops"=stops) #the starts and stops from X (ss from X) 
    ssX <- ssX0[ssX0[,"Value"]!=0,] # remove the rows the correspond to CODE_ values that are 0 (not POS or NEG) 

    # The next 3 lines calculate the equivalent of your SIZE column 
    sizeX1 <- x[ssX[,"Starts"],"START"] 
    sizeX2 <- x[ssX[,"Stops"],"END"] 
    sizeX <- sizeX2 - sizeX1 

    sssX <- data.frame(ssX, "Size"=sizeX) # Combine the Size to the ssX (start stop of X) data frame 
    return(sssX) #Added in EDIT 

} 

answer0 <- ddply(.data=test4, .variables="Code", .fun=sss) # use the function ddply() in the package "plyr" (apply the function to each CODE, why we reshaped) 
answer <- answer0 # duplicate the original, new version will be reformatted 
answer[,"Value"] <- c("NEG",NA,"POS")[answer0[,"Value"]+2] # reformat slightly so that we have POS/NEG instead of 1/-1 

잘하면 행운을 빕니다!

+0

Whoaaaaa ... 이것은 매우 쉽습니다. 여전히 sss 함수를 더 잘 살펴볼 필요가 있지만 결과는 훌륭하며 동일한 데이터 프레임에 모든 코드를 포함하는 것이 편리합니다. 큰 데이터 프레임에 모든 것을 적용하려고 노력할 것이며 문제가 발생할 경우 알려 드리겠습니다. 다시 한번 감사드립니다. – JMarchante

+0

문제가 없습니다! 함수 sss에서 sssX를 반환하는 대답을 편집했음을 유의하십시오. 그렇지 않으면'sss (test4 [test4 [, "Code"] == 1,))'을 (를) 수행하면 아무 것도 반환하지 않습니다. 최종 제품은 동일합니다. – rbatt

2

CODE1이 같은 값을 갖는 그룹을 결정하려면 런 - 길이 인코딩을 사용하십시오.

편의상, 값이 0이 아닌 지점과 해당 블록의 길이를 찾으십시오. CODE1 제로이다

CODE1_is_nonzero <- rle_of_CODE1$values != 0 
n <- rle_of_CODE1$lengths[CODE1_is_nonzero] 

df1의 부분을 무시한다.

df1_with_nonzero_CODE1 <- subset(df1, CODE1 != 0) 

rle으로 발견 된 연속 블록을 기반으로 그룹을 정의하십시오.

df1_with_nonzero_CODE1$GROUP <- rep(seq_along(n), times = n) 

각 그룹에 대한 요약 통계를 보려면 ddply을 사용하십시오.

summarised_by_CODE1 <- ddply(
    df1_with_nonzero_CODE1, 
    .(GROUP), 
    summarise, 
    MinOfLOCAT = min(LOCAT), 
    MaxOfLOCAT = max(LOCAT), 
    SIZE  = max(END) - min(START) 
) 
summarised_by_CODE1$VALUE <- ifelse(
    rle_of_CODE1$values[CODE1_is_nonzero] == 1, 
    "POS", 
    "NEG" 
) 
summarised_by_CODE1 
## GROUP MinOfLOCAT MaxOfLOCAT SIZE VALUE 
## 1  1   1   2 270 POS 
## 2  3   4   4 75 POS 

지금 CODE2으로 반복합니다.

+0

친절한 도움에 감사드립니다. 나는 모든 것을 단순화하는 방법과 모든 것이 합리적이는 방식을 좋아합니다. 내가 그것을 한 후에 나는 그것이 어렵지 않다는 것을 깨달았다. 나는 그가 원하는 모든 것을 한 번에 적용 할 수 있도록 관리하는 답을 받아 들였지만 모든 컬럼을 적용하는 수식에 조언을 사용할 수 있습니다. 나는 함수 rle에 대해 몰랐다. 나는 그것을 더 자주 확실히 사용할 것이다. 다시 한번 감사드립니다. 환호 – JMarchante

관련 문제