2017-11-22 10 views
1

아래와 같은 attributes.txt 파일 (Sawtooth 조사 연구 결과)을 파싱하여 출력 결과가 아래와 같이 표시되도록하고 싶습니다. 아래에서 내 시도를 볼 수 있습니다. 그것은 작동합니다. 그러나 그것은 매우 추합니다. 더 좋은 방법이있을거야, 맞지? (그들이 사용할 수 있다면 나는 tidyverse 솔루션을 선호)R 구조의이 구조화 된 텍스트 파일 구문 분석

attributes.txt :

attribute,level,label 
1,1,brand01 
1,2,brand02 
1,3,brand03 
1,4,otherbrand 
2,1,1 
2,2,2 
2,3,3 
2,4,4 
2,5,5 
3,1,99 
3,2,199 
3,3,299 

내 시도 :

분석에서

================================================================================ 
ATTRIBUTES AND LEVELS 
================================================================================ 

======================================== 
Display Text 
======================================== 

<Same structure as shown below. But I do not want to extract any of this text> 

======================================== 
Internal Labels 
======================================== 

[Attribute List]: 

1 brand 
2 rating 
3 price 

--------------------------- 
Attribute 1: 
    brand 

Levels: 
1 brand01 
2 brand02 
3 brand03 
4 otherbrand 

--------------------------- 
Attribute 2: 
    rating 

Levels: 
1 1 
2 2 
3 3 
4 4 
5 5 

--------------------------- 
Attribute 3: 
    price 

Levels: 
1 99 
2 199 
3 299 

원하는 출력

library(stringr) parse_attributes_file <- function(ATTRIBUTES_FILE_PATH) { con = file(ATTRIBUTES_FILE_PATH, "r") reached_internal_labels <- FALSE attribute_num <- NA datalist <- list() idx <- 0 while (TRUE) { line = readLines(con, n = 1) if (length(line) == 0) { break } if (!reached_internal_labels) { reached_internal_labels <- str_detect(line, "Internal Labels") } else { attribute_num_extract <- str_match(line, "Attribute ([[:digit:]]+): ")[,2] if(!is.na(attribute_num_extract)) { attribute_num <- attribute_num_extract } else { if (!is.na(attribute_num)) { my_match <- str_match(line, "([[:digit:]]+)\t(.*)") if(!is.na(my_match[,1])) { idx <- idx + 1 datalist[[idx]] <- c(attribute_num, my_match[,2], my_match[,3]) } } } } } close(con) attributes = do.call(rbind, datalist) colnames(attributes) <- c("attribute", "level", "label") return(attributes) } 

답변

1

tidyverse 함수를 사용하여 똑같은 일을하는 코드가 약간 더 적습니다. 먼저 샘플 데이터를로드하십시오.

# you'd do something like 
# text <- readLines("yourtextfile") 
# but for this sample... 
text <- strsplit("================================================================================\nATTRIBUTES AND LEVELS\n================================================================================\n\n========================================\nDisplay Text\n========================================\n\n<Same structure as shown below. But I do not want to extract any of this text>\n\n========================================\nInternal Labels\n========================================\n\n[Attribute List]:\n\n1 brand\n2 rating\n3 price\n\n---------------------------\nAttribute 1: \nbrand\n\nLevels: \n1 brand01\n2 brand02\n3 brand03\n4 otherbrand\n\n---------------------------\nAttribute 2: \nrating\n\nLevels: \n1 1\n2 2\n3 3\n4 4\n5 5\n\n---------------------------\nAttribute 3: \nprice\n\nLevels: \n1 99\n2 199\n3 299", "\n")[[1]] 

이제 파일을 구문 분석합니다. "레벨 :"지금 우리가 속성을 결합 빈 줄

markers <- case_when(str_detect(lines, "^Levels:")~2, 
      str_detect(lines, "^$")~1, 
      TRUE~0) 
levels <- markers %>% accumulate(function(a,b) case_when(b==2~TRUE, b==1~FALSE, TRUE~a), .init=FALSE) %>% head(-1) %>% 
    modify_if(markers==3, function(x) FALSE) %>% unlist 

에서 중지 첫 번째로 선을 찾고 각 라인 그리고

library(tidyverse) 
attributes <- str_match(lines, "Attribute (\\d)")[, 2] %>% 
    accumulate(function(a, b) coalesce(b,a)) 

은 "수준"블록을 찾아 적합한 속성을 찾을 수 및 레벨 테이블에 데이터 및

를 반환하는 tibble

read_table(paste(attributes[levels], lines[levels], collapse="\n"), 
      col_names=c("attribute", "level", "label")) 

에 불과 readr 구문 분석을

# A tibble: 12 x 3 
    attribute level  label 
     <int> <int>  <chr> 
1   1  1 brand01 
2   1  2 brand02 
3   1  3 brand03 
4   1  4 otherbrand 
5   2  1   1 
6   2  2   2 
7   2  3   3 
8   2  4   4 
9   2  5   5 
10   3  1   99 
11   3  2  199 
12   3  3  299 
+0

조금 펑키. 나 한테 줄곧 몰랐어. 그러나 이것이 내가 본 최고의 것입니다. 그래서 답으로 표시하십시오. – lowndrul