실무에서는 unique와 duplicated는 많이 사용하는 데이터 이다. 예를 들어 부동산의 구별로 평당 가격 추세를 그리는 데이터셋을 정리하기 위한 함수를 그릴때, unique를 이용하고, duplicated는 데이터를 취합 할때, 중복이 없는지 확인 한다. 실무에서 데이터 전처리 하거라 모델을 사용할때 많이 사용하므로, R을 진입 할때는 반드시 알고 넘어가야 한다.
두 함수의 차이는 다음 예제를 참고해 이해할 수 있습니다. names 벡터가 다음과 같다고 합니다.
names<-c("Williams","Jones", "Smith", "Williams", "Jones", "Williams")
table 함수를 사용해 각 항목이 얼마나 자주 나타나는지 확인해 볼수 있습니다.
table(names)
## names
## Jones Smith Williams
## 2 1 3
이 벡터는 이름 3개를 데이터를 가지고 있습니다. unique 함수는 3개의 서로 다른 이름을 추출 하며 벡터상에서 각 이름이 발생된 순서대로 정렬되지 않은 길이 3의 결과를 벡터로 생성 합니다.
unique(names)
## [1] "Williams" "Jones" "Smith"
이와 달리 duplicated 함수는 좌측을 기준으로 해당 이름이 이미 나타났는지 여부에 따라 FALSE나 TRUE 논리값을 포함 하는 같은 길이의 벡터를 생성한다. 어떤 결과가 발생하는지와 이것이 왜 필요한지에 대해 이해하기 위해서는 다음 예제를 살펴 봅시다.
duplicated(names)
## [1] FALSE FALSE FALSE TRUE TRUE TRUE
세 번째 까지는 이름 데이터가 중복되지 않은 상태로 발생했고(FALSE), 나머지 3개의 데이터는 모두 복제된 (TRUE) 데이터가 되었음을 알 수 있습니다.
duplicated 함수 결과에 대해 NOT 연산자(!) 적용한 후 첨자 벡터를 사용하면 unique 함수의 기능을 구현할 수 있습니다.
names[!duplicated(names)]
## [1] "Williams" "Jones" "Smith"
고유한 값만을 포함한 단축 벡터가 필요하다면 unique를 사용합니다. 그러나 이름과 같은 길이의 벡터를 만들기 위해서는 duplicated를 사용합니다. 반복값을 제외한 후 평균급여를 계산 하려면 이 함수를 이용해 서로 다른 벡터의 값을 추출 할 수 있습니다.
salary <- c(42,42,48,42,42,42)
mean(salary)
## [1] 43
salary[!duplicated(names)]
## [1] 42 42 48
mean(salary[!duplicated(names)])
## [1] 44
존스와 윌리엄스 두 사람이 동일한 급여(42)를 가지고 있으므로 생략하였고, 이로 인하여 평균 계산값이 서로 다릅니다.
mean(salary[!duplicated(salary)])
## [1] 45
예제 1
2022년 1월 부터 5월까지의 부동산 실거래가 셋이 있다. 이건에 대해서, 서울에 대한 지역을 필터 하시고 각 구별 고유값과, 각 구별 갯수를 구하고, 전체 레코드에서 중복값이 있는지 확인 하십시오.
아래의 크롤링 방법을 이용해서, 데이터 셋을 가지고 옵니다.
library(httr)
library(readxl)
real_estate_fun <- function() {
# 2022년도 데이터 가져오기
url <- "https://drive.google.com/u/0/uc?id=1JC6JPtA4nK5ZRyii64NDO98LyU38kL0R&export=download"
GET(url, write_disk(tf <- tempfile(fileext = ".xlsx")))
apt_2022 <- read_excel(tf, 1L)
df <- rbind(apt_2022)
return(df)
}
system.time(
df <- real_estate_fun()
)
## 사용자 시스템 elapsed
## 1.599 0.382 4.505
서울특별시 데이터만 추출 합니다.
# 서울 특별시 데이터 추출
library(dplyr)
##
## 다음의 패키지를 부착합니다: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(stringr)
seoul <- df %>% filter(str_detect(시군구,"서울특별시"))
시군구가 동 까지 표현되어 있으므로, 시,구까지 데이터를 분리 하겠습니다.
# map 함수를 돌리기 위해 purrr을 사용한다.
library(purrr)
# word를 나누는 함수를 구한다. 여기에서 strsplit 함수가 쓰인다.
word_fun <- function(i){
split <- unlist(strsplit(seoul$시군구[i]," "))
word <- data.frame(
구 = paste(split[1],split[2],sep = " ")
)
return(word)
}
# apt 데이터 프레임의 열의 갯수를 nrow(apt)로 구한다.
x <- 1:nrow(seoul)
# map 함수로 list를 구한다.
system.time(
mylist <- x %>%
map(word_fun)
)
## 사용자 시스템 elapsed
## 0.723 0.000 0.738
# list 파일을 데이터 프레임으로 바꾼다.
apt_split <- as.data.frame(do.call(rbind,mylist))
# 나누어진 데이터 프레임을 cbind로 컬럼을 묶는다.
seoul <- cbind(apt_split, seoul)
# head 를 이용하여, 1번째 부터 4번째 행만 보여준다.
head(seoul[1:4])
## 구 시군구 번지 본번
## 1 서울특별시 강남구 서울특별시 강남구 개포동 1280 1280
## 2 서울특별시 강남구 서울특별시 강남구 개포동 12 0012
## 3 서울특별시 강남구 서울특별시 강남구 개포동 12 0012
## 4 서울특별시 강남구 서울특별시 강남구 개포동 12 0012
## 5 서울특별시 강남구 서울특별시 강남구 개포동 653 0653
## 6 서울특별시 강남구 서울특별시 강남구 개포동 654 0654
데이터가 많이 있을 경우 속도 문제로 map 함수를 사용하였습니다. 이것에 대한 예제는 데이터가 많지 않기 때문에 속도가 빨라 보일 수 있습니다. 하지만, 거래수가 1천만건 넘어서면, 속도가 매우 느려지는 단점이 있습니다.
# 구(gu)라고 벡터 변수를 저장한다.
gu <- seoul$구
gu[1:30]
## [1] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [4] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [7] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [10] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [13] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [16] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [19] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [22] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [25] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
## [28] "서울특별시 강남구" "서울특별시 강남구" "서울특별시 강남구"
구
라고 하는 벡터 변수를 보면 같은 구가 계속 반복해서 보일 수 있음을 알수 있습니다. 이것을 우선 table 함수를 이용해서 구별로 얼마나 거래되었는지 확인 할 수 있습니다.
table(gu)
## gu
## 서울특별시 강남구 서울특별시 강동구 서울특별시 강북구 서울특별시 강서구
## 320 236 93 323
## 서울특별시 관악구 서울특별시 광진구 서울특별시 구로구 서울특별시 금천구
## 217 114 408 127
## 서울특별시 노원구 서울특별시 도봉구 서울특별시 동대문구 서울특별시 동작구
## 412 172 248 190
## 서울특별시 마포구 서울특별시 서대문구 서울특별시 서초구 서울특별시 성동구
## 227 173 338 164
## 서울특별시 성북구 서울특별시 송파구 서울특별시 양천구 서울특별시 영등포구
## 220 286 175 259
## 서울특별시 용산구 서울특별시 은평구 서울특별시 종로구 서울특별시 중구
## 103 238 80 88
## 서울특별시 중랑구
## 298
unique 함수를 사용하면, 중복된 데이터가 하나로 묶어 집니다. 즉 구만 나옵니다.
unique(gu)
## [1] "서울특별시 강남구" "서울특별시 강동구" "서울특별시 강북구"
## [4] "서울특별시 강서구" "서울특별시 관악구" "서울특별시 광진구"
## [7] "서울특별시 구로구" "서울특별시 금천구" "서울특별시 노원구"
## [10] "서울특별시 도봉구" "서울특별시 동대문구" "서울특별시 동작구"
## [13] "서울특별시 마포구" "서울특별시 서대문구" "서울특별시 서초구"
## [16] "서울특별시 성동구" "서울특별시 성북구" "서울특별시 송파구"
## [19] "서울특별시 양천구" "서울특별시 영등포구" "서울특별시 용산구"
## [22] "서울특별시 은평구" "서울특별시 종로구" "서울특별시 중구"
## [25] "서울특별시 중랑구"
그리고 seoul
이라는 데이터 프레임을 가지고, 중복거래가 데이터상으로 존재 하는지 확인해 봅시다.
head(duplicated(seoul),200)
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [73] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [145] FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE
## [157] FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE
## [169] FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE
## [181] TRUE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
## [193] FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
위의 데이터를 보면, 중복되어 있는 데이터가 조금 보입니다. 한번 전체적으로 중복이 몇개가 되는지 알아보겠습니다.
sum(duplicated(seoul))
## [1] 124
127,256개 데이터 중에서 124개 이면, 중복 입력 또는 또 다른 사유에 의한 원인이 될 수 있습니다. 만약에 데이터 중복이 15%이상이 되었다면, 취합이 잘되었는지 위심 해봐야 합니다.
which(duplicated(seoul))
## [1] 76 151 156 159 163 165 168 171 176 180 181 184 188 191 195
## [16] 686 2851 2852 2853 2854 2858 2859 2860 2861 2864 2868 2872 2873 2874 2875
## [31] 2876 2877 2880 2881 2882 2883 2887 2888 2889 2890 2894 2896 2897 2898 2899
## [46] 2901 3644 3702 4237 4634 4835 4897 5377 5378 5382 5383 5388 5390 5393 5394
## [61] 5396 5397 5400 5401 5402 5406 5408 5409 5410 5413 5415 5416 5417 5419 5420
## [76] 5423 5427 5428 5429 5430 5432 5433 5434 5437 5441 5442 5446 5447 5451 5453
## [91] 5454 5455 5457 5458 5459 5461 5462 5464 5465 5467 5469 5470 5472 5475 5476
## [106] 5478 5479 5480 5482 5483 5484 5485 5486 5488 5490 5491 5492 5493 5494 5496
## [121] 5497 5498 5499 5500
데이터 중복을 확인 하기 위해서, 데이터 셋을 정리하고, 중복된 데이터를 같이 봅시다.
dup_df <- seoul %>% select(시군구, 단지명, '전용면적(㎡)',계약년월, 계약일,층,'거래금액(만원)')
rbind(
dup_df[75,],
dup_df[76,]
)
## 시군구 단지명 전용면적(㎡) 계약년월 계약일 층
## 75 서울특별시 강동구 길동 현대웰하임(101동) 16.959 202201 18 7
## 76 서울특별시 강동구 길동 현대웰하임(101동) 16.959 202201 18 7
## 거래금액(만원)
## 75 11800
## 76 11800
댓글 없음:
댓글 쓰기