2016-07-10 3 views
0

많은 변수가 양수와 음수로 나누어 진 데이터 테이블이 있습니다. 이 열을 결합하여 변수의 부호있는 값이 존재하도록하고 싶습니다. (이러한 변수는 항상 이름에 positivenegative이 있고, 다른 변수는 그러나, positivenegative 문자열은 변수에 어떤 위치에서 발생할 수 없다 않는다 -.. grepl("(positive)|(negative)", names(dt)) 올바르게 식별)이름으로 데이터 테이블 열 요약

들어 예를 들어,

library(data.table) 

set.seed(1) 

(DT <- data.table(x = 1:5, 
        a_positive = sample(1:5), 
        a_negative = sample(1:5), 
        b_positive = sample(1:5), 
        b_negative = sample(1:5), 
        c_normal = sample(1:5))) 

    x a_positive a_negative b_positive b_negative c_normal 
1: 1   2   5   2   3  5 
2: 2   5   4   1   5  1 
3: 3   4   2   3   4  2 
4: 4   3   3   4   1  4 
5: 5   1   1   5   2  3 

가 의도 된 결과 :

하고 내 방법은 그것이 0,123,197,732에 의존
x c_normal a b 
1: 1  5 -3 -1 
2: 2  1 1 -4 
3: 3  2 2 -1 
4: 4  4 0 3 
5: 5  3 0 3 

루프 dplyr :

library(dplyr) 
library(lazyeval) 
library(magrittr) 

unite_positive_negative <- function(dt){ 
    signed_names <- 
    names(dt)[ 
     duplicated(gsub("(positive)|(negative)", "", names(dt))) | 
     duplicated(gsub("(positive)|(negative)", "", names(dt)), fromLast = TRUE)] 

    unsigned_names <- 
    gsub("_*((positive)|(negative))_*", "", signed_names) 

    the_names <- 
    data.table(signed_names = signed_names, 
       unsigned_names = unsigned_names) 

    for (unsigned_name in unsigned_names){ 
    poz <- the_names[unsigned_names == unsigned_name & grepl("positive", signed_names, fixed = TRUE)][["signed_names"]] 
    neg <- the_names[unsigned_names == unsigned_name & grepl("negative", signed_names, fixed = TRUE)][["signed_names"]] 

    dt %<>% 
     mutate_(.dots = setNames(list(interp(~p - n, p = as.name(poz), n = as.name(neg))), unsigned_name)) 
    } 

    # Unimportant 
    unselect_ <- function(.data, .dots){ 
    all_names <- names(.data) 
    keeps <- names(.data)[!names(.data) %in% .dots] 
    dplyr::select_(.data, .dots = keeps) 
    } 

    dt %>% 
    unselect_(.dots = signed_names) 
} 

순수한 data.table 방법이 있나요? (또는 직접적인 방법으로)?

답변

1

melt/dcast으로 시도해 볼 수 있습니다. melt을 'x'및 'c_normal'열로 지정하여 melt으로 'wide'형식에서 'long'형식으로 데이터 세트를 바꿉니다. 'normal'열이 많으면 grep을 사용하여 ' 변수 '열을 tstrsplit을 사용하여 2로 나누고'x ','c_normal '및'var1 '(split에서)로 그룹화 한 다음'값 '의'음수 '와'양수 '의 하위 집합을 -1/1으로 곱한 다음 . 그런 다음, '넓은'형식으로 '긴'에서 dcast.

library(data.table) 
dcast(melt(DT, id.var = c("x", "c_normal"))[, 
     c("var1", "var2") := tstrsplit(variable, "_") 
     ][, -1*value[var2=="negative"] + value[var2=="positive"] , 
     by = .(x, c_normal, var1)], 
       x + c_normal~var1, value.var="V1") 
# x c_normal a b 
#1: 1  5 -3 -1 
#2: 2  1 1 -4 
#3: 3  2 2 -1 
#4: 4  4 0 3 
#5: 5  3 0 3 

melt/dcast없이 또 다른 옵션은 fo를 데이터 집합을 부분 집합하는 것 r "양수"및 "음수"열 (순서가 있다고 가정)에 1/-1을 곱한 다음 추가 (+)를 수행하고 "양수/음수"열없이 해당 출력을 데이터 집합의 하위 집합에 할당합니다.

DT1 <- DT[, c("x", grep("normal", names(DT), value=TRUE)), with = FALSE] 
DT2 <- DT[, grep("positive", names(DT)), with = FALSE] + 
      -1 * DT[, grep("negative", names(DT)), with = FALSE] 
DT1[, c("a", "b") := DT2] 
DT1 
# x c_normal a b 
# 1: 1  5 -3 -1 
# 2: 2  1 1 -4 
# 3: 3  2 2 -1 
# 4: 4  4 0 3 
# 5: 5  3 0 3 
+0

변수는 '음수'또는 '음수'부분 문자열을 포함하는 경우에만 '부호없는'열 *입니다. 따라서 모든 '정상'열에 '정상'이 포함되는 것은 아니며 '양수'와 '음수'는 열 이름의 아무 곳에서나 발생할 수 있습니다. – Hugh

+0

@Hugh 내 솔루션은 사용자가 제공 한 예제를 기반으로했으며 두 가지 모두 해당 예제에서 작동합니다. – akrun