본문 바로가기
Prop : 부동산/업데이트 일지

[R] API로 수집한 일간(daily)업데이트 파일을 어제날짜 파일과 비교하는 쉬운 방법

by 프롭테크 2025. 9. 24.
반응형

<문제>
매일 업데이트 되는 API로 데이터를 수집하는 도중에 오류가 발생할 경우 신규데이터가 제대로 수집되지 못하는 케이스

=> API의 에러핸들링이 완벽할 수 없으므로 추후 누락된 내용을 새로 받아야 하는데, 특정 기간(파일)만 재시도함으로써 시간/리소스 절감

<해결방법>
- 파일 내용을 데이터프레임으로 읽어서 diff 비교

 

<더 쉬운 해결방법>

- 내용을 읽기 전에 용량만 비교해서 전일 대비 감소한 경우를 확인

 

<R 소스코드>
*path는 사용자 환경에 맞춰서 수정 필요

> f.compare_file_sizes
function(path1 = NULL, path2 = NULL, sort_by_change = FALSE) {
  
  # 기본값 설정
  if (is.null(path1)) {
    yesterday <- format(Sys.Date() - 1, "%Y%m%d")
    path1 <- paste0("output/", yesterday)
  }
  
  if (is.null(path2)) {
    today <- format(Sys.Date(), "%Y%m%d")
    path2 <- paste0("output/", today)
  }
  
  # 파일 크기 단위 변환 함수
  format_size <- function(bytes) {
    abs_bytes <- abs(bytes)
    sign <- ifelse(bytes < 0, "-", "")
    
    if (abs_bytes < 1024) {
      return(paste0(sign, round(abs_bytes, 1), "B"))
    } else if (abs_bytes < 1024^2) {
      return(paste0(sign, round(abs_bytes/1024, 1), "K"))
    } else if (abs_bytes < 1024^3) {
      return(paste0(sign, round(abs_bytes/1024^2, 1), "M"))
    } else {
      return(paste0(sign, round(abs_bytes/1024^3, 1), "G"))
    }
  }
  
  # 경로명을 간단하게 변환 (마지막 디렉토리명 사용)
  path1_name <- basename(path1)
  path2_name <- basename(path2)
  
  # 파일 목록 및 크기 가져오기
  files1 <- file.info(list.files(path1, full.names = TRUE))
  files2 <- file.info(list.files(path2, full.names = TRUE))
  
  # 파일명만 추출
  files1$filename <- basename(rownames(files1))
  files2$filename <- basename(rownames(files2))
  
  # 병합
  result <- merge(files1[c("filename", "size")], 
                  files2[c("filename", "size")], 
                  by = "filename", 
                  suffixes = c(paste0("_", path1_name), paste0("_", path2_name)))
  
  # 변화량과 비율 계산
  size1_col <- paste0("size_", path1_name)
  size2_col <- paste0("size_", path2_name)
  
  result$change <- result[[size2_col]] - result[[size1_col]]
  result$change_pct <- round((result$change / result[[size1_col]]) * 100, 1)
  
  # 크기 포맷팅
  result$size1_fmt <- sapply(result[[size1_col]], format_size)
  result$size2_fmt <- sapply(result[[size2_col]], format_size)
  result$change_fmt <- sapply(result$change, format_size)
  
  # 최종 결과 (동적 컬럼명)
  final <- data.frame(
    filename = result$filename,
    stringsAsFactors = FALSE
  )
  
  final[[path1_name]] <- result$size1_fmt
  final[[path2_name]] <- result$size2_fmt
  final[["change"]] <- paste0(result$change_fmt, " (", ifelse(result$change_pct > 0, "+", ""), result$change_pct, "%)")
  
  # 정렬 기준에 따른 결과 반환
  if (sort_by_change) {
    # 변화율 기준으로 내림차순 정렬 (절대값 기준)
    final <- final[order(-abs(result$change_pct)), ]
  } else {
    # 파일명 기준으로 정렬
    final <- final[order(final$filename), ]
  }
  
  return(final)
}

 

<사용 예시>

> f.compare_file_sizes()
                                   filename 20250923 20250924          change
1    단독다가구 매매 실거래자료_202507.xlsx   293.4K   293.6K    173B (+0.1%)
2    단독다가구 매매 실거래자료_202508.xlsx   268.2K   269.9K    1.7K (+0.6%)
3    단독다가구 매매 실거래자료_202509.xlsx   130.1K   142.4K   12.2K (+9.4%)
4  단독다가구 전월세 실거래자료_202507.xlsx     2.5M     2.7M  168.9K (+6.6%)
5  단독다가구 전월세 실거래자료_202508.xlsx     2.3M     2.3M   27.3K (+1.2%)
6  단독다가구 전월세 실거래자료_202509.xlsx   890.1K   971.7K   81.6K (+9.2%)
7   아파트 분양권전매 신고 자료_202507.xlsx   214.8K   214.9K        83B (0%)
8   아파트 분양권전매 신고 자료_202508.xlsx   196.9K   197.2K    294B (+0.1%)
9   아파트 분양권전매 신고 자료_202509.xlsx   124.3K   134.3K      9.9K (+8%)
10           아파트 전월세 자료_202507.xlsx     7.2M     7.3M   89.1K (+1.2%)
11           아파트 전월세 자료_202508.xlsx     6.8M     6.2M -580.3K (-8.3%)
12           아파트 전월세 자료_202509.xlsx     3.3M     3.6M  288.9K (+8.6%)
13  아파트매매 실거래 상세 자료_202504.xlsx     6.8M     6.8M    7.9K (+0.1%)
14  아파트매매 실거래 상세 자료_202505.xlsx     7.5M     7.5M  -17.6K (-0.2%)
15  아파트매매 실거래 상세 자료_202506.xlsx     8.8M     8.8M    6.5K (+0.1%)
16  아파트매매 실거래 상세 자료_202507.xlsx     5.6M     5.6M    4.5K (+0.1%)
17  아파트매매 실거래 상세 자료_202508.xlsx     5.3M     5.3M   19.8K (+0.4%)
18  아파트매매 실거래 상세 자료_202509.xlsx     3.2M     3.5M  281.3K (+8.6%)
19        아파트매매 실거래자료_202504.xlsx     4.1M     4.2M    4.6K (+0.1%)
20        아파트매매 실거래자료_202505.xlsx     4.5M     4.5M      5K (+0.1%)
21        아파트매매 실거래자료_202506.xlsx     5.4M     5.4M    4.1K (+0.1%)
22        아파트매매 실거래자료_202507.xlsx     3.4M     3.4M    2.8K (+0.1%)
23        아파트매매 실거래자료_202508.xlsx     3.2M     3.2M     12K (+0.4%)
24        아파트매매 실거래자료_202509.xlsx     1.9M     2.1M  169.6K (+8.5%)
25   연립다세대 매매 실거래자료_202507.xlsx   716.1K   716.2K        11B (0%)
26   연립다세대 매매 실거래자료_202508.xlsx   670.4K   674.3K    3.9K (+0.6%)
27   연립다세대 매매 실거래자료_202509.xlsx     343K   378.6K  35.7K (+10.4%)
28 연립다세대 전월세 실거래자료_202507.xlsx     1.8M     1.8M    1.6K (+0.1%)
29 연립다세대 전월세 실거래자료_202508.xlsx     1.5M     1.6M   12.4K (+0.8%)
30 연립다세대 전월세 실거래자료_202509.xlsx   741.9K   800.1K   58.3K (+7.9%)
31     오피스텔 매매 실거래자료_202507.xlsx   283.2K   283.2K         1B (0%)
32     오피스텔 매매 실거래자료_202508.xlsx   254.5K   258.3K    3.8K (+1.5%)
33     오피스텔 매매 실거래자료_202509.xlsx   154.1K     164K    9.9K (+6.4%)
34   오피스텔 전월세 실거래자료_202507.xlsx       2M       2M    1.1K (+0.1%)
35   오피스텔 전월세 실거래자료_202508.xlsx     1.7M     1.7M   14.2K (+0.8%)
36   오피스텔 전월세 실거래자료_202509.xlsx     745K   812.1K     67.1K (+9%)
> i=3
>   f.base(i)
단독다가구 전월세 실거래자료 -> Pointing at 아파트 전월세 자료
> get_date_range(base_date, i)[2]
[1] "2025-08-01"

수집 기간: 2025-07 ~ 2025-09 (3개월)
[1] "11110"
[1] "11140"
[1] "11170"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11200"
[1] "11215"
[1] "11230"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11260"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11290"
[1] "11305"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11320"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11350"
[1] "11380"
[1] "11410"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11440"
[1] "11470"
[1] "11500"
[1] "11530"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11545"
[1] "11560"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11590"
[1] "11620"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11650"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11680"
[1] "11710"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "11740"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26110"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26140"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26170"
[1] "26200"
[1] "26230"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26260"
[1] "26290"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26320"
[1] "26350"
[1] "26380"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26410"
[1] "26440"
[1] "26470"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26500"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26530"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "26710"
[1] "27110"
[1] "27140"
[1] "27170"
[1] "27200"
[1] "27230"
[1] "27260"
[1] "27290"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "27710"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "27720"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "28110"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "28140"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "28177"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "28185"
[1] "28200"
[1] "28237"
[1] "28245"
[1] "28260"
[1] "28710"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "28720"
[1] "29110"
[1] "29140"
[1] "29155"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "29170"
[1] "29200"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "30110"
[1] "30140"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "30170"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "30200"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "30230"
JSON 파싱 중 에러 발생: lexical error: invalid char in json text.
                                       <OpenAPI_ServiceResponse> 	<cmm
                     (right here) ------^

could not find function "read_xml"[1] "31110"
[1] "31140"
[1] "31170"
[1] "31200"
[1] "31710"
[1] "36110"
[1] "41111"
[1] "41113"
[1] "41115"
[1] "41117"
[1] "41131"
[1] "41133"
[1] "41135"
[1] "41150"
[1] "41171"
[1] "41173"
[1] "41192"
[1] "41194"
[1] "41196"
[1] "41210"
[1] "41220"
[1] "41250"
[1] "41271"
[1] "41273"
[1] "41281"
[1] "41285"
[1] "41287"
[1] "41290"
[1] "41310"
[1] "41360"
[1] "41370"
[1] "41390"
[1] "41410"
[1] "41430"
[1] "41450"
[1] "41461"
[1] "41463"
[1] "41465"
[1] "41480"
[1] "41500"
[1] "41550"
[1] "41570"
[1] "41590"
[1] "41610"
[1] "41630"
[1] "41650"
[1] "41670"
[1] "41800"
[1] "41820"
[1] "41830"
No Data : 충청북도 청주시43110 (202508)
[1] "43111"
[1] "43112"
[1] "43113"
[1] "43114"
[1] "43130"
[1] "43150"
[1] "43720"
[1] "43730"
[1] "43740"
[1] "43745"
[1] "43750"
[1] "43760"
[1] "43770"
No Data : 충청북도 단양군43800 (202508)
No Data : 충청남도 천안시44130 (202508)
[1] "44131"
[1] "44133"
[1] "44150"
[1] "44180"
[1] "44200"
[1] "44210"
[1] "44230"
[1] "44250"
[1] "44270"
[1] "44710"
[1] "44760"
[1] "44770"
[1] "44790"
[1] "44800"
[1] "44810"
[1] "44825"
[1] "46110"
[1] "46130"
[1] "46150"
[1] "46170"
[1] "46230"
[1] "46710"
[1] "46720"
[1] "46730"
[1] "46770"
[1] "46780"
[1] "46790"
[1] "46800"
[1] "46810"
[1] "46820"
[1] "46830"
[1] "46840"
[1] "46860"
[1] "46870"
[1] "46880"
[1] "46890"
No Data : 전라남도 진도군46900 (202508)
No Data : 전라남도 신안군46910 (202508)
No Data : 경상북도 포항시47110 (202508)
[1] "47111"
[1] "47113"
[1] "47130"
[1] "47150"
[1] "47170"
[1] "47190"
[1] "47210"
[1] "47230"
[1] "47250"
[1] "47280"
[1] "47290"
[1] "47730"
No Data : 경상북도 청송군47750 (202508)
No Data : 경상북도 영양군47760 (202508)
[1] "47770"
[1] "47820"
[1] "47830"
No Data : 경상북도 성주군47840 (202508)
[1] "47850"
[1] "47900"
No Data : 경상북도 봉화군47920 (202508)
[1] "47930"
No Data : 경상북도 울릉군47940 (202508)
No Data : 경상남도 창원시48120 (202508)
[1] "48121"
[1] "48123"
[1] "48125"
[1] "48127"
[1] "48129"
[1] "48170"
[1] "48220"
[1] "48240"
[1] "48250"
[1] "48270"
[1] "48310"
[1] "48330"
[1] "48720"
[1] "48730"
[1] "48740"
[1] "48820"
No Data : 경상남도 남해군48840 (202508)
[1] "48850"
[1] "48860"
[1] "48870"
[1] "48880"
[1] "48890"
[1] "50110"
[1] "50130"
[1] "51110"
[1] "51130"
[1] "51150"
[1] "51170"
[1] "51190"
[1] "51210"
[1] "51230"
[1] "51720"
[1] "51730"
[1] "51750"
No Data : 강원특별자치도 평창군51760 (202508)
[1] "51770"
[1] "51780"
No Data : 강원특별자치도 화천군51790 (202508)
[1] "51800"
[1] "51810"
[1] "51820"
[1] "51830"
No Data : 전북특별자치도 전주시52110 (202508)
[1] "52111"
[1] "52113"
[1] "52130"
[1] "52140"
[1] "52180"
[1] "52190"
[1] "52210"
[1] "52710"
[1] "52720"
[1] "52730"
[1] "52740"
[1] "52750"
No Data : 전북특별자치도 순창군52770 (202508)
[1] "52790"
[1] "52800"
[1] "Done: output/APTprice/20250924/아파트 전월세 자료_202508.xlsx has been saved."
OK : 아파트 전월세 자료_202508
[1] 17
> f.compare_file_sizes()
                                   filename 20250923 20250924          change
1    단독다가구 매매 실거래자료_202507.xlsx   293.4K   293.6K    173B (+0.1%)
2    단독다가구 매매 실거래자료_202508.xlsx   268.2K   269.9K    1.7K (+0.6%)
3    단독다가구 매매 실거래자료_202509.xlsx   130.1K   142.4K   12.2K (+9.4%)
4  단독다가구 전월세 실거래자료_202507.xlsx     2.5M     2.7M  168.9K (+6.6%)
5  단독다가구 전월세 실거래자료_202508.xlsx     2.3M     2.3M   27.3K (+1.2%)
6  단독다가구 전월세 실거래자료_202509.xlsx   890.1K   971.7K   81.6K (+9.2%)
7   아파트 분양권전매 신고 자료_202507.xlsx   214.8K   214.9K        83B (0%)
8   아파트 분양권전매 신고 자료_202508.xlsx   196.9K   197.2K    294B (+0.1%)
9   아파트 분양권전매 신고 자료_202509.xlsx   124.3K   134.3K      9.9K (+8%)
10           아파트 전월세 자료_202507.xlsx     7.2M     7.3M   89.1K (+1.2%)
11           아파트 전월세 자료_202508.xlsx     6.8M     6.3M -493.7K (-7.1%)
12           아파트 전월세 자료_202509.xlsx     3.3M     3.6M  288.9K (+8.6%)
반응형

댓글