2017-09-19 2 views
1

미국 국세 조사에서 배포 한 대도시 지역 데이터의 연간 건축 허가 (고정 너비 서식 텍스트 파일로 downloadable here)를 사용해야합니다.고정 너비 서식 데이터를 열 너비를 초과하는 항목으로 읽음

999 10180 Abilene, TX        306  298  8  0  0  0 
184 10420 Akron, OH        909  905  0  4  0  0 
999 13980 Blacksburg-Christiansburg-Radford, 
    VA            543  455  0  4  84  3 
145 14010 Bloomington, IL       342  214  4  0  124  7 
160 15380 Buffalo-Cheektowaga-Niagara Falls,* 
    NY            1964  931  14  14 1005  68 
268 15500 Burlington, NC       1353  938  12  16  387  20 

위에서 보는 바와 같이 다음은 파일의 발췌 한 것입니다 (그들이 좋은 형식이 아닌 및 날짜 프레임에 파일을 읽은 후 교체 할 수있는 나는 열 이름을 제거했습니다) 발췌, 이름 열의 항목 중 많은 수가 열의 너비를 초과합니다 (36 자 여야합니다). 필자는 utils 패키지와 readr의 다양한 fwf 읽기 기능을 실험했지만 이러한 항목을 고려한 솔루션을 찾을 수 없습니다. 모든 팁을 많이 주시면 감사하겠습니다.


편집 : 원래의 파일 포맷을 발췌하기위한 모드로와 제 3 컬럼 폭을 초과 한 예 항목이 삭제 된 방법으로 편집 하였다. 나는 그 이후에 그들을 다시 포함하고 열 이름을 제거하기 위해 발췌 부분을 업데이트했다.

이 편집 전에 제출 된 @markdly 코드는이 문제가없는 모든 항목에서 작동합니다. 나는 CSV로 결과를 수출, 아래 발췌 한이 항목이 어떻게되는지 보여주기 위해 포함 :

"38","999",NA,"13980",NA,"Blacksburg-Christiansburg-Radford,",NA,NA,NA,NA,NA,NA 
"39","V","A",NA,NA,NA,"543",455,0,4,84,3 
"40","145",NA,"14010",NA,"Bloomington, IL","342",214,4,0,124,7 
"51","160",NA,"15380",NA,"Buffalo-Cheektowaga-Niagara Falls,*",NA,NA,NA,NA,NA,NA 
"52","N","Y",NA,NA,NA,"1964",931,14,14,1005,68 
"53","268",NA,"15500",NA,"Burlington, NC","1353",938,12,16,387,20 

편집 2 : 주요 대도시의 대부분 실제로 돈 찾고 있어요 ' 이 문제 범주에 속하지 않으므로 수행 할 수있는 솔루션이 없다면 데이터 세트에서 이러한 항목을 제거하는 방법이 있습니까?

+0

나는 약간이 편집 한 . – thelatemail

답변

0

편집 :
업데이트 된 정보에 따르면 일부 파일에서는 파일의 너비가 고정되어 있지 않습니다. 이 상황에서는 readr::read_tableread_fwf보다 유용하다고 생각합니다. 다음 예제는 소스 파일 중 하나 (tb3u2016.txt)를 가져오고 처리하는 방법을 tidyverse입니다. 기본 접근법은 readLines과 같은 것을 사용하는 것을 포함 할 수 있습니다.

1 단계에서 파일을 읽고 분할을 지정 2는 분할 기록 텍스트 다음 tidyr::extract를 사용하여 별도의 변수에 내용을 넣어 결합 공통 레코드 ID를

library(tidyverse) 
df <- read_table("tb3u2016.txt", col_names = FALSE, skip = 11) %>% 
    rownames_to_column() %>% 
    mutate(record = if_else(lag(is.na(X2) & rowname > 1), lag(rowname), rowname)) 

df[37:40, ] 
#> # A tibble: 4 x 8 
#> rowname             X1 X2 
#>  <chr>             <chr> <int> 
#> 1  37 999 13900 Bismarck, ND       856 629 
#> 2  38   999 13980 Blacksburg-Christiansburg-Radford, NA 
#> 3  39 VA            543 455 
#> 4  40 145 14010 Bloomington, IL       342 214 
#> # ... with 5 more variables: X3 <int>, X4 <int>, X5 <int>, X6 <int>, 
#> # record <chr> 

단계를 기록합니다. 공백을 제거하고 중복 된 레코드를 제거하십시오.

df <- df %>% mutate(new_X1 = if_else(rowname != record, paste0(lag(X1), X1), X1)) %>% extract(new_X1, c("CSA", "CBSA", "Name", "Total"), "([0-9]+) ([0-9]+) (.+) ([0-9]+)") %>% mutate(Name = trimws(Name)) %>% filter((lead(record) != record) | rowname == 1) %>% select(CSA, CBSA, Name, Total, X2, X3, X4, X5, X6) df[37:39, ] #> # A tibble: 3 x 9 #> CSA CBSA Name Total X2 X3 X4 #> <chr> <chr> <chr> <chr> <int> <int> <int> #> 1 999 13900 Bismarck, ND 856 629 16 6 #> 2 999 13980 Blacksburg-Christiansburg-Radford,VA 543 455 0 4 #> 3 145 14010 Bloomington, IL 342 214 4 0 #> # ... with 2 more variables: X5 <int>, X6 <int> 


다음은 readr::read_fwf를 사용하여 질문의 이전 버전에 제공되는 솔루션의 압축 된 버전입니다.당신이 무엇을 다루고 있는지에 대한보다 정확한 표현을 보여줍니다 있도록

예 데이터

library(readr) 

# example data 
txt <- "                      Num of 
                         Struc- 
                         tures 
                         With 
                     3 and 4 5 Units 5 Units 
CSA CBSA Name         Total 1 Unit 2 Units Units or more or more 

999 10180 Abilene, TX        306  298  8  0  0  0 
184 10420 Akron, OH        909  905  0  4  0  0" 

write_file(txt, "example.txt") 

솔루션

col_widths <- c(3, 1, 5, 1, 36, 8, 8, 8, 8, 8, NA) 
col_names <- c("CSA", "blank_1", "CBSA", "blank_2", "Name", "Total", "units_1", "units_2", 
       "units_3_and_4", "units_5_or_more", "num_struc_5_or_more") 
df <- read_fwf("example.txt", fwf_widths(col_widths, col_names), skip = 7) 
df 
#> # A tibble: 2 x 11 
#>  CSA blank_1 CBSA blank_2  Name Total units_1 units_2 
#> <int> <chr> <int> <chr>  <chr> <int> <int> <int> 
#> 1 999 <NA> 10180 <NA> Abilene, TX 306  298  8 
#> 2 184 <NA> 10420 <NA> Akron, OH 909  905  0 
#> # ... with 3 more variables: units_3_and_4 <int>, units_5_or_more <int>, 
#> # num_struc_5_or_more <int> 
+0

@ markdly 답장을 보내 주셔서 감사합니다. 게시물에 대한 편집에서 언급했듯이 형식을 변경하기 위해 수정 한 항목은 문제 항목의 예를 제거했습니다. 이러한 항목은 이름 열의 36 자 너비를 초과합니다. 나는 당신의 코드를 돌렸고 다른 모든 엔트리에서는 완벽하게 작동하지만 원래 포스트에 csv 출력의 발췌 부분을 추가하여 문제의 코드가 어떻게 보이는지 보여줍니다. – user2424281

+0

@ user2424281, 나는 당신이 의미하는 것을 보았습니다 - 특별히 긴 이름은 두 개의 분리 된 선을 가로 지르는 기록의 결과입니다. 이 경우 https://stackoverflow.com/a/35761217/8475145와 같은 것을 사용하여 파일을 한 줄씩 파싱해야 할 수도 있습니다. 빠른 픽스를 위해 Total/units_1/unit_2 컬럼에서 NA에 대한 필터를 수행하여 필수적이지 않은 경우 이러한 문제 레코드를 제외 할 수 있습니다. – markdly

+0

@ user2424281, 나는 이것을 'read_table'을 사용하여 할 수 있다고 생각합니다. 일부 데이터 논쟁과 함께. 자세한 내용은 수정 된 답변보기 ... – markdly

관련 문제