2017-04-21 3 views
0

모든 DataFrame을 가져 와서 각 열을 평가하여 요약 테이블을 반환하는 함수를 작성했습니다. 이제 Answer Label 열로 분류 된 요소 인 Variable Name에 대해 Variable TypeAnswer Code을 한 행 아래로 이동하고 싶습니다.R : DataFrame 형식 지정 조작

샘플 코드 :이 데이터 집합 MASS::anorexia를 사용

CreateCodebook <- function(dF){ 
    numbercols <- length(colnames(dF)) 

    table <- data.frame() 

    for (i in 1:length(colnames(dF))){ 
    AnswerCode <- if (sapply(dF, is.factor)[i]) 1:nrow(unique(dF[i])) else NA 
    AnswerLabel <- if (sapply(dF, is.factor)[i]) as.vector(unique(dF[order(dF[i]),][i])) else "Open ended" 
    VariableName <- if (length(AnswerCode) > 1) c(colnames(dF)[i], 
                rep(NA,length(AnswerCode) - 1)) else colnames(dF)[i] 
    VariableLabel <- if (length(AnswerCode) > 1) c(colnames(dF)[i], 
                rep(NA,length(AnswerCode) - 1)) else colnames(dF)[i] 
    VariableType <- if (length(AnswerCode) > 1) c(sapply(dF, class)[i], 
                rep(NA,length(AnswerCode) - 1)) else sapply(dF, class)[i] 

    df = data.frame(VariableName, VariableLabel, AnswerLabel, AnswerCode, VariableType, stringsAsFactors = FALSE) 
    names(df) <- c("Variable Name", "Variable Label", "Variable Type", "Answer Code", "Answer Label") 
    table <- rbind(table, df) 

    } 
    rownames(table) <- 1:nrow(table) 
    return(table) 
} 

, 내 기능에서이 출력을 얻을 :

Variable Name Variable Label Variable Type Answer Code Answer Label 
1   Treat   Treat   CBT   1  factor 
2   <NA>   <NA>   Cont   2   <NA> 
3   <NA>   <NA>   FT   3   <NA> 
4   Prewt   Prewt Open ended   NA  numeric 
5  Postwt   Postwt Open ended   NA  numeric 

원하는 출력 :

Variable Name Variable Label Variable Type Answer Code Answer Label 
1   Treat   Treat   <NA>   NA  factor 
2   <NA>   <NA>   CBT   1   <NA> 
3   <NA>   <NA>   Cont   2   <NA> 
4   <NA>   <NA>   FT   3   <NA> 
5   Prewt   Prewt Open ended   NA  numeric 
6  Postwt   Postwt Open ended   NA  numeric 
+0

이 기능을 테스트 할 샘플 입력을 [재현 예 (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) 확인 제공합니다 . – MrFlick

+0

고맙습니다. 지금 내 게시물에 재현 가능한 예를 제공했습니다. –

답변

2

희망이 작동합니다

CreateCodebook <- function(dF){ 
    numbercols <- length(colnames(dF)) 

    table <- data.frame() 

    for (i in 1:length(colnames(dF))){ 
     AnswerCode <- if (sapply(dF, is.factor)[i]) 1:nrow(unique(dF[i])) else NA 
     AnswerLabel <- if (sapply(dF, is.factor)[i]) as.vector(unique(dF[order(dF[i]),][i])) else "Open ended" 
     VariableName <- if (length(AnswerCode) > 1) c(colnames(dF)[i], 
                 rep(NA,length(AnswerCode) - 1)) else colnames(dF)[i] 
     VariableLabel <- if (length(AnswerCode) > 1) c(colnames(dF)[i], 
                 rep(NA,length(AnswerCode) - 1)) else colnames(dF)[i] 
     VariableType <- if (length(AnswerCode) > 1) c(sapply(dF, class)[i], 
                 rep(NA,length(AnswerCode) - 1)) else sapply(dF, class)[i] 

     df = data.frame(VariableName, VariableLabel, AnswerLabel, AnswerCode, VariableType, stringsAsFactors = FALSE) 
     names(df) <- c("Variable Name", "Variable Label", "Variable Type", "Answer Code", "Answer Label") 
     table <- rbind(table, df) 

    } 


    # add a new column of row id 
    table$row <- 1:nrow(table) 

    # created new rows to be added 
    x <- table[which(table$`Answer Label` == 'factor'), ] 
    x[, c(1, 2, 5)] <- NA 

    # change original factor rows 
    table[which(table$`Answer Label` == 'factor'), 3:4] <- NA 

    # combine the two data.frame and reorder rows 
    table <- rbind(table, x) 
    table <- table[order(table$row), -ncol(table)] 

    rownames(table) <- 1:nrow(table) 
    return(table) 
} 
+0

감사합니다.하지만 내 기능에 통합되어 모든 데이터 프레임에 적용될 수 있어야합니다. 자기 방식이 하드 코딩 된 것처럼 보입니까? –

+0

@RileyHun, 이건 어때? – mt1022

+0

와우! 이것은 잘 작동합니다. 정말 고마워. 정말 감사합니다. –

1

다음 솔루션은 dplyr, tidyrdata.table 패키지의 기능이 필요합니다.

# Load packages 
library(dplyr) 
library(tidyr) 
library(data.table) 

# A function to adjust the output of the CreateCodebook function 
Adjust_factor <- function(dF){ 

    dF2 <- dF %>% 
    # Create a new column called Indicator, which is a copy of Answer Label 
    mutate(Indicator = `Answer Label`) %>% 
    # Impute NA based on the previous and nearest non-NA value 
    fill(Indicator) %>% 
    # Create run length group number 
    mutate(Index = rleid(Indicator)) 

    # Split the data frame to list based on the Index 
    dF_list <- split(dF2, f = dF2$Index) 

    # Adjust each data frame subset 
    dF_list2 <- lapply(dF_list, function(x){ 

    if (x$Indicator[1] == "factor"){ # If Indicator is "factor" 

     # Copy and bind the first row 
     x <- bind_rows(x[1, ], x) 
     # Change the content of the first and second row. Replace the value with NA 
     x[1, c("Variable Type", "Answer Code")] <- NA 
     x[2, c("Variable Name", "Variable Label", "Answer Label")] <- NA 
    } 
    return(x) 
    }) 

    # Combine all data frame 
    dF3 <- bind_rows(dF_list2) %>% 
    # Remove the Indicator and Index column 
    select(-Indicator, -Index) 

    return(dF3) 
} 

# Test the function 
library(MASS) 
data(anorexia) 
dat1 <- anorexia 
dat2 <- CreateCodebook(dat1) 
dat3 <- Adjust_factor(dat2) 

test1 <- data.frame(a = c("a", "b", "c"), 
        b = c(1, 2, 3), 
        c = 10:12, 
        d = seq(as.Date("2001-01-01"), as.Date("2001-01-03"), 1), 
        e = c("o", "p", "q")) 

test2 <- CreateCodebook(test1) 
test3 <- Adjust_factor(test2) 
+0

감사합니다. ycw. 이것은 훌륭한 해결책입니다. 나는 외부 패키지에 의존하지 않고 내 기능에 통합 되었기 때문에 다른 하나를 사용했다. –