2016-06-29 2 views
2

여러 개의 열 집합을 모으는 문제는 이미 여기에서 다루었습니다 : Gather multiple sets of columns, 제 경우에는 열이 고유하지 않습니다.중복 된 열 집합을 단일 열로 집합하십시오.

I 다음 데이터가 : 질문 위한

  1. 식별자 :

    input <- data.frame(
        id = 1:2, 
        question = c("a", "b"), 
        points = 0, 
        max_points = c(3, 5), 
        question = c("c", "d"), 
        points = c(0, 20), 
        max_points = c(5, 20), 
        check.names = F, 
        stringsAsFactors = F 
    ) 
    input 
    #> id question points max_points question points max_points 
    #> 1 1  a  0   3  c  0   5 
    #> 2 2  b  0   5  d  20   20 
    

    첫번째 열은 ID이고, 그때 많은 반복 열 (원래의 데이터 셋이 133 개 컬럼을 가짐)이이

  2. 포인트 부여
  3. 최대 포인트
,451,515,

나는이 구조를 끝내고 싶습니다 : 나는 몇 가지를 시도

expected <- data.frame(
    id = c(1, 2, 1, 2), 
    question = letters[1:4], 
    points = c(0, 0, 0, 20), 
    max_points = c(3, 5, 5, 20), 
    stringsAsFactors = F 
) 
expected 
#> id question points max_points 
#> 1 1  a  0   3 
#> 2 2  b  0   5 
#> 3 1  c  0   5 
#> 4 2  d  20   20 

:

  • tidyr::gather(input, key, val, -id)
  • reshape2::melt(input, id.vars = "id")

가 모두 원하는 출력을 제공하지 않습니다. 또한 여기에 표시된 것보다 많은 열을 사용하면 중복 열이 너무 많아서 gather이 더 이상 작동하지 않습니다. 해결 방법으로

나는이 시도 :이 문제는 이미 여기에 설명 된 Duplicate identifiers for rows (3, 9), (4, 10), (1, 7), (2, 8)

: Unexpected behavior with tidyr를,하지만 난 다른를 추가하는 방법을 왜/I 모르는 오류를 제공

# add numbers to make col headers "unique" 
names(input) <- c("id", paste0(1:(length(names(input)) - 1), names(input)[-1])) 

# gather, remove number, spread 
input %>% 
    gather(key, val, -id) %>% 
    mutate(key = stringr::str_replace_all(key, "[:digit:]", "")) %>% 
    spread(key, val) 

식별자. 대부분의 경우이 문제는 주요 문제가 아닐 수 있습니다. 아마 모든 것을 다르게 다뤄야하기 때문입니다.

내 문제를 어떻게 해결할 수 있습니까? tidyr 또는 기본으로 수행 할 수 있습니까? 나는 data.table을 사용하는 방법을 모르지만, 간단한 해결책이있는 경우에 대해서도 그렇게 할 것입니다.

+0

질문, max_points 및 포인트 열 모두 실제로 동일한 이름이 지정 되었습니까? –

+0

아마도'rbind (input [, c (1, 2 : 4)], input [, c (1, 5 : 7)])'? – zx8754

+0

@MikeyMike 예. –

답변

5

이 시도 :

do.call(rbind, 
     lapply(seq(2, ncol(input), 3), function(i){ 
      input[, c(1, i:(i + 2))] 
       }) 
     ) 

# id question points max_points 
# 1 1  a  0   3 
# 2 2  b  0   5 
# 3 1  c  0   5 
# 4 2  d  20   20 
0
당신은 ID 열을 처리하고 싶지만이 같은 아마 뭔가 방식을 명확히해야 할 수도 있습니다

?

runme <- function(word , dat){ 
    grep(paste0("^" , word , "$") , names(dat)) 
} 

l <- mapply(runme , unique(names(input)) , list(input)) 
l2 <- as.data.frame(l) 

output <- data.frame() 
for (i in 1:nrow(l2)) output <- rbind(output , input[, as.numeric(l2[i,]) ]) 

는 확실하지가 반복되는 열을 다른 수의 처리와 관련하여 얼마나 강력하지만, 테스트 데이터를 작동하며 열 배의 동일한 번호를 반복하는 경우 작동합니다.

1

lapply를 사용하지 않고 같은 목표를 달성하기위한 또 다른 방법 :

우리는 질문 MAX_POINTS에 대한 모든 열을 잡아서 시작을 점 우리는 각각 개별적으로 하나와 함께 cbind 모두 녹아.

library(reshape2) 

questions <- input[,c(1,c(1:length(names(input)))[names(input)=="question"])] 
points <- input[,c(1,c(1:length(names(input)))[names(input)=="points"])] 
max_points <- input[,c(1,c(1:length(names(input)))[names(input)=="max_points"])] 

questions_m <- melt(questions,id.vars=c("id"),value.name = "questions")[,c(1,3)] 
points_m <- melt(points,id.vars=c("id"),value.name = "points")[,3,drop=FALSE] 
max_points_m <- melt(max_points,id.vars=c("id"),value.name = "max_points")[,3, drop=FALSE] 

res <- cbind(questions_m,points_m, max_points_m) 
res 
    id questions points max_points 
1 1   a  0   3 
2 2   b  0   5 
3 1   c  0   5 
4 2   d  20   20 
4

데이터에서이를 수행하는 관용적 인 방법.테이블은 매우 간단하다 :

library(data.table) 
setDT(input) 

res = melt(
    input, 
    id = "id", 
    meas = patterns("question", "^points$", "max_points"), 
    value.name = c("question", "points", "max_points") 
) 


    id variable question points max_points 
1: 1  1  a  0   3 
2: 2  1  b  0   5 
3: 1  2  c  0   5 
4: 2  2  d  20   20 

당신은 "변수"라는 여분의 열을 얻을 수 있지만, 원하는 경우 나중에 res[, variable := NULL]으로 제거 할 수 있습니다.

관련 문제