머신러닝 02. 탐색적 데이터분석: 기술통계분석(EDA)과 데이터 전처리1


    목차

    1. 기술통계 함수
      (1) 범주형, 연속형 데이터 요약
    2. 데이터셋을 처음 접할 때 할 일: dplyr이 가장 편리
      (1) ggplot2에 내장된 diamonds 데이터셋 로딩
      (2) 데이터셋 조회: psych::headTail
      (3) 데이터셋 구조 파악: dplyrs::glimpse()
      (4) 데이터셋 기술 통계: summary() | Hmisc::describe() | prettyR::describe() | psych::describe() | skimr::skim()
    3. 인덱싱 / 셀렉션: 컬럼 대상
      (1) 특정 변수 컬럼 인덱싱 / 셀렉션: 직접 | subset() | dplyr::select
      (2) 특정 변수 컬럼 1개 제외하고 인덱싱 / 셀렉션
      (3) 특정 변수 컬럼 2개 이상 지정해서 인덱싱 / 셀렉션
      (4) 특정 변수 컬럼 2개 이상 제외하고 인덱싱 / 셀렉션
      (5) 연속된 위치의 변수 컬럼 인덱싱 / 셀렉션: 콜론(:) 기호 이용
      (6) 연속된 위치의 변수 컬럼 제외하고 인덱싱 / 셀렉션: 콜론(:) 기호 이용
    4. 정규표현식으로 인덱싱 / 셀렉션: 문자열 패턴 일치하는 컬럼 찾기, grep()
      (1) 특정 변수 컬럼 인덱싱 / 셀렉션: 직접 | subset() | dplyr::select
      (2) 특정 변수 컬럼 1개 제외하고 인덱싱 / 셀렉션
      (3) 특정 변수 컬럼 2개 이상 지정해서 인덱싱 / 셀렉션
      (4) 특정 변수 컬럼 2개 이상 제외하고 인덱싱 / 셀렉션
    5. 필터링 / 슬라이싱: 레코드 대상
      (1) 특정 범주형 변수 1개에 대한 특정 값 1개 포함하는 / 제외하는 기준으로 레코드 필터링: == / != / dplyr::filter
      (2) 특정 범주형 변수 1개에 대한 복합 조건 포함하는 레코드 필터링
      (3) 특정 범주형 변수 1개에 대한 복합 조건 제외하는 레코드 필터링
      (4) 특정 범주형 변수 2개에 대한 복합 조건 포함하는 레코드 필터링
      (5) 특정 연속형 변수 1개에 대한 특정 조건 일치하는 레코드 필터링
      (6) 특정 연속형 변수 2개에 대한 복합 조건 일치하는 레코드 필터링
      (7) 범주형과 연속형 변수에 대한 복합 조건과 일치하는 레코드 필터링
    6. 데이터셋에 있는 특정 관찰치를 슬라이싱(slicing) 하기
      (1) 특정 일치행 1개범위 지정 슬라이싱: [] / dplyr::slice()
      (2) 특정 일치행 1개범위 제외 슬라이싱
      (3) 특정 일치행 복수범위 지정 슬라이싱
      (4) 특정 일치행 복수범위 제외 슬라이싱
    7. 데이터셋에 있는 특정 관찰치를 무작위 추출(sampling) 하기
      (1) 레코드 개수만큼 무작위 추출하는 경우: sample() / dplyr::sample_n()
      (2) 레코드 비율만큼 무작위 추출하는 경우: : sample() / dplyr::sample_frac()
    8. 레코드 대상 필터링 구현 시 정규표현식 사용
      (1) cut 변수에 good 이라는 단어가 들어간 레코드 조회: [] / subset() / dplyr::filter()
      (2) clarity 변수에 “문자v+아무문자+숫자”가 들어간 레코드 조회



—————코딩——————————————————————————————————

1. 기술통계 분석

  • 기술통계 분석에서 중점을 두는 과제: 중심성, 변동가능성, 정규성
  • 중심성(centrality): 데이터가 어느 부분에 집중되어 있는가
  • 변동성(variability): 데이터가 가운데를 중심으로 얼마나 흩어져 있는가 (첨도로 측정)
  • 정규성(normality): 데이터가 정규분포 모양에서 얼마나 벗어나 있는가 (왜도로 측정)

—————코딩——————————————————————————————————

1. 기술통계 함수


(1) 범주형, 연속형 데이터 요약


str() 	# 변수 내부 구조 표시. class 정보, mode 정보, length 정보 한번에 알 수 있음
table() # 범주형 변수의 빈도수 계산
mean()

sum() 	# 합
min()	# 최솟값
max()	# 최댓값
var()	# 분산
sd()	# 표준편차



2. 데이터셋을 처음 접할 때 할 일: dplyr이 가장 편리


(1) ggplot2에 내장된 diamonds 데이터셋 로딩


install.packages("ggplot2")
library(ggplot2)
help(package = "ggplot2")	# 패키지의 코드에 대한 도움말 호출
data(package = "ggplot2")	# 패키지에 들어있는 데이터 목록 호출
data(diamonds)				# 다이아몬드 데이터만 호출


(2) 데이터셋 조회: psych::headTail


diamonds
View(diamonds)		# 별도의 창에 데이터 표시
head(diamonds)
head(diamonds, n=15)
tail(diamonds)

library(psych)
psych::headTail(diamonds)


  • tibble 구조에서는 변수 컬럼명 밑에 데이터 유형이 표시됨.
  • ord: ordered. 팩터형(서열형) 변수
  • dbl: double. 실수형 변수
  • tibble 구조는 데이터 조회할 때 콘솔 창이 허용하는 범위 내에서 데이터를 보여준다


  • View() 함수의 장점: 데이터를 오름차순, 내림차순으로 쉽게 확인 가능


(3) 데이터셋 구조 파악: dplyrs::glimpse()


str(diamonds)

library(tibble)
glimpse(diamonds)


(4) 데이터셋 기술 통계: summary() / Hmisc::describe() / prettyR::describe() / psych::describe() / skimr::skim()


summary(diamonds)

library(Hmisc)
Hmisc::describe(diamonds)

library(prettyR)
prettyR::describe(diamonds)

library(psych)
psych::describe(diamonds)

library(skimr)
skim(diamonds)


  • summary(): 변수컬럼 별로 6가지 정보 안내
  • 중심성을 표현하는 건 mean, median. 둘 사이의 차이가 얼마나 큰지를 살피자
  • min / max / 1stQu. / 3rdQu.를 이용해 오른쪽 꼬리분포인지 왼쪽 꼬리분포인지, 정규분포인지 예상 해보자


  • Hmisc::describe(): 변수컬럼 별로 summary()보다 상세한 정보 제공
  • missing data 개수를 보여준다.
  • 연속형 변수와 범주형 변수 별로 다른 정보를 보여준다.
  • 연속형 변수에서는
    • info: 0에 가까울수록 범주 데이터일 가능성이 높고, 1에 가까울수록 연속 데이터일 가능성이 높다.
    • lowest, highest: 최소, 최대의 극단값을 5개 정도씩 보여준다.
  • 범주형 변수에서는
    • value: 범주 항목 내용
    • Frequency: 빈도
    • Proportion: 비율


  • prettyR::describe(): 연속데이터끼리, 범주형데이터끼리 묶어서 보여준다.
  • 연속형 데이터: mean, median, var, sd, valid.n(레코드 개수) 제공
  • 범주형 데이터: 범주항목 별로 count, percent 제공


  • psych::describe(): 가장 여러가지 정보를 보여주는 함수
  • 연속과 범주형 변수 구분 X: n(레코드 개수), mean, sd, median, trimmed, mad, min, max, range, skew, kurtosis, se 제공
  • trimmed: 5%까지 잘라낸 값. 이 값과 mean 값의 차이가 크면 5% 내에 극단값 있을 가능성이 높다.
  • 오른쪽 꼬리 분포(skewed to the right): 왜도(skewness)는 양수. 절댓값 클수록 긴꼬리 분포
  • 왼쪽 꼬리 분포(skewed to the left): 왜도는 음수. 절댓값 클수록 긴꼬리 분포
  • 정규분포의 첨도(kurtosis)는 0
  • kurtosis > 0 : 분포가 중앙에 덜 집중(뭉툭)
  • kurtosis < 0 : 분포가 중앙에 더 집중(뾰족)
  • 분포들 간의 뾰족한 정도를 비교할 때 중요한 점은 분포가 동일한 분산을 가가정하고, 첨도를 비교해야 한다.


  • skimr {skim} : 연속 데이터와 범주형 데이터를 구분해서 표시하며, 연속데이터는 시각적 그래프 그려준다.



3. 인덱싱 / 셀렉션: 컬럼 대상


(1) 특정 변수 컬럼 인덱싱 / 셀렉션: 직접 / subset() / dplyr::select


diamonds$carat


diamonds["carat"]
diamonds[ , "carat"]
diamonds[1]
diamonds[ , 1]


subset(diamonds, select = "carat")
subset(diamonds, select = 1)


library(dplyr)
select(diamonds, carat)
select(diamonds, 1)


library(magrittr)
diamonds %>% subset(select = "carat")
diamonds %>% subset(select = 1)

diamonds %>% select(carat)
diamonds %>% select(1)


  • base {subset} 함수: 변수 컬럼명이나 인덱스 번호로 인덱싱. 티블(data.frame)형 인덱싱
  • dplyr::select() : dplyr패키지는 tibble 구조 데이터 다룰 때 속도 면에서 data.frame 보다도 빠름


(2) 특정 변수 컬럼 1개 제외하고 인덱싱 / 셀렉션


diamonds[-1]
diamonds[ , -1]


subset(diamonds, select = -1)
diamonds %>% subset(select = -1)


library(dplyr)
select(diamonds, -carat)
select(diamonds, -1)
diamonds %>% select(-carat)
diamonds %>% select(-1)


(3) 특정 변수 컬럼 2개 이상 지정해서 인덱싱 / 셀렉션


diamonds[c("carat", "price")]
diamonds[ , c("carat", "price")]
diamonds[c(1, 7)]
diamonds[ , c(1, 7)]


target <- c("carat", "price")
diamonds[target]
diamonds[ , target]
target2 <- c(1, 7)
diamonds[target2]
diamonds[ , target2]


subset(diamonds, select = c("carat", "price"))
subset(diamonds, select = c(1, 7))
diamonds %>% subset(select = target)
diamonds %>% subset(select = target2)


library(dplyr)
select(diamonds, carat, price)
select(diamonds, 1, 7)
diamonds %>% select(target)
diamonds %>% select(target2)


  • 지정할 목록이 많을 때는 벡터 변수를 사용해 주면 편리하고, 관리에 용이


(4) 특정 변수 컬럼 2개 이상 제외하고 인덱싱 / 셀렉션


diamonds[c(-1, -7)]
diamonds[ , c(-1, -7)]
diamonds[-c(1, 7)]
diamonds[ , -c(1, 7)]
diamonds[-target2]


subset(diamonds, select = c(-1, -7))
subset(diamonds, select = -c(1, 7))
subset(diamonds, select = -target2)
diamonds %>% subset(select = -target2)


library(dplyr)
select(diamonds, -carat, -price)
select(diamonds, -1, -7)
select(diamonds, -target)
select(diamonds, -target2)
diamonds %>% select(-target)
diamonds %>% select(-target2)


(5) 연속된 위치의 변수 컬럼 인덱싱 / 셀렉션: 콜론(:) 기호 이용


diamonds[c(1:4)]
diamonds[ , c(1:4)]
diamonds[1:4]
diamonds[ , 1:4]
diamonds[target2]
diamonds[ , target2]


subset(diamonds, select = c(1:4))
subset(diamonds, select = 1:4)
subset(diamonds, select = target2)
diamonds %>% subset(select = target2)


library(dplyr)
select(diamonds, carat:clarity)
select(diamonds, c(1:4))
select(diamonds, 1:4)
select(diamonds, target)
select(diamonds, target2)
diamonds %>% select(target)
diamonds %>% select(target2)


(6) 연속된 위치의 변수 컬럼 제외하고 인덱싱 / 셀렉션: 콜론(:) 기호 이용


diamonds[-c(1:4)]
diamonds[ , -c(1:4)]
diamonds[c(-1:-4)]
diamonds[ , c(-1:-4)]
diamonds[-1:-4]
diamonds[ , -1:-4]
diamonds[-(1:4)]
diamonds[ , -(1:4)]
diamonds[-target2]
diamonds[ , -target2]


subset(diamonds, select = c(-1:-4))
subset(diamonds, select = -c(1:4))
subset(diamonds, select = -1:-4)
subset(diamonds, select = -(1:4))
subset(diamonds, select = -target2)
diamonds %>% subset(select = -target2)


library(dplyr)
select(diamonds, -carat:-clarity)
select(diamonds, -(carat:clarity))
select(diamonds, -1:-4)
select(diamonds, -(1:4))
select(diamonds, -target2)
diamonds %>% select(-carat:-clarity)
diamonds %>% select(-target2)



4. 정규표현식으로 인덱싱 / 셀렉션: 문자열 패턴 일치하는 컬럼 찾기, grep()


(1) 데이터셋 로딩 및 요약: ames_raw

library(help = AmesHousing)
help(package = AmesHousing)

data(ames_raw, package = "AmesHousing")
help(ames_raw)

psych::headTail(ames_raw)		# 데이터셋 조회
dplyr::glimpse(ames_raw)				# 데이터셋 구조파악
skimr::skim(ames_raw)			# 데이터셋 기술통계


(2) grep 함수 vs starts_with 함수로 패턴 찾기


grep(pattern = "Exter", x = colnames(ames_raw), ignore.case = FALSE, value = T)		# 패턴 문자열이 들어간 인덱스를 반환


  • grep 함수의 인자: pattern / x / ignore.case / value
  • pattern: 찾고자 하는 문자열. 정규표현식 이용해서 정교한 검색이 가능
  • x: 타겟 자료
  • ignore.case: TRUE면 대소문자 상관없이, FALSE면 대소문자 구분. 디폴트는 TRUE
  • value: T 면 인덱스 번호 뿐 아니라 찾아낸 문자열까지 알려줌


starts_with(match = "Exter", vars = colnames(ames_raw))		# 매칭 문자열이 들어간 인덱스를 반환


  • starts_with(): match 인자로 받은 문자열로 시작하는 문자열을 찾음. 정규표현식 작성 안해도 되는 장점
  • starts_with 함수의 인자: match / vars
  • match: 찾고자 하는 문자열.
  • vars: 타겟 자료


  • ends_with(): match 인자로 받은 문자열로 끝나는 문자열을 찾음
  • matches(): starts_with, ends_with(), matches() 함수는 모두 tidyselect 패키지의 함수로, dplyr 만났을 때 속도 빠름


(3) tibble(data.frame)에서 변수 컬럼 인덱싱


ames_raw[grep("^Exter", colnames(ames_raw))]
ames_raw[starts_with("Exter", vars = colnames(ames_raw))]

ames_raw[c(25, 26, 29, 30)]		# 이 식이 위 두 개 식과 같은 의미

ames_raw[ , grep("^Exter", colnames(ames_raw))]		
ames_raw[ , starts_with("Exter", vars = colnames(ames_raw))]

ames_raw[ , c(25, 26, 29, 30)]		# 결국엔 모두 같은 의미의 식

library(magrittr)
ames_raw %>% subset(select = grep("^Exter", colnames(ames_raw)))
ames_raw %>% subset(select = starts_with("Exter", vars = colnames(ames_raw)))


  • starts_with와 dplyr이 잘 맞물리는 패키지에 속해서 속도 면에서 이점. 특히 tibble에서 더 빨라진다.

(4) 정규표현식


"A$"		# A로 끝나는 문자 찾음 (ends_with())
"^B"		# B로 시작하는 문자 찾음 (starts_with())


"^sa.+e$"		# "sa로 시작 + 아무 문자(.) + e로 끝나는 문자열"
"...sa.+"		# "세 글자(...) + sa + 아무 자리의 아무 문자(.)"


"\d"		# 0~9 중 아무 숫자



grep(pattern = "^sa.+e$", x = colnames(ames_raw), ignore.case = TRUE)
matches(match = "^sa.+e$", vars = colnames(ames_raw), ignore.case = TRUE)

grep(pattern = "\\d", x = colnames(ames_raw), ignore.case = TRUE)			# 수치 데이터로 된 컬럼은 모두 찾아서 인덱스 번호 반환
matches(match = "\\d", vars = colnames(ames_raw), ignore.case = TRUE)

subset(ames_raw, select = grep("\\d", colnames(ames_raw)))			# 숫자 들어간 컬럼 변수를 인덱싱
select(ames_raw, grep("\\d", colnames(ames_raw)))

grep(pattern = "Fin.+\\d", x = colnames(ames_raw), ignore.case = TRUE)		# "Fin + 아무 문자 + 숫자"가 들어간 컬럼의 인덱스 번호 반환
matches(match = "Fin.+\\d", vars = colnames(ames_raw), ignore.case = TRUE)

subset(ames_raw, select = grep("Fin.+\\d", x = colnames(ames_raw)))			# "Fin + 아무 문자 + 숫자"가 들어간 컬럼 변수 인덱싱
subset(ames_raw, select = matches("Fin.+\\d", vars = colnames(ames_raw)))
select(ames_raw, grep("Fin.+\\d", x = colnames(ames_raw)))
select(ames_raw, matches("Fin.+\\d", vars = colnames(ames_raw)))


  • R은 공백을 무시하지만 따옴표 안의 공백은 문자로 인식한다. 따라서 “^L.+K$” != “^L . + K$”
  • \d 가 숫자를 의미하는 정규표현식이지만, 탈출문자 \를 하나 더 써서 \d가 R에 인식될 수 있도록 해야한다.



5. 필터링 / 슬라이싱: 레코드 대상


(1) 특정 범주형 변수 1개에 대한 특정 값 1개 포함하는 / 제외하는 기준으로 레코드 필터링: == / != / dplyr::filter


  • 질의한다 = 쿼리한다: 필요한 조건을 넣어서 원하는 결과를 낳는 행위
  • 지정하고 싶은 조건은 == 나 != 를 넣어서 질의한 후 데이터셋에서 해당 레코드를 추출


diamonds[diamonds$cut == "Ideal", ]					# cut (컬럼 명) 변수 중에서 "Ideal"(행이름) 등급의 데이터만 필터링하기
diamonds[which(diamonds$cut == "Ideal"), ]	
diamonds[diamonds$cut != "Ideal", ]					# cut (컬럼 명) 변수 중에서 "Ideal" (행이름) 등급 아닌 데이터만 필터링하기
diamonds[which(diamonds$cut != "Ideal"), ]			


subset(diamonds, cut == "Ideal")				# 필터링을 subset() 함수로 진행
diamonds %>% subset(cut == "Ideal")
subset(diamonds, cut != "Ideal")
diamonds %>% subset(cut != "Ideal")



library(dplyr)
filter(diamonds, cut == "Ideal")			# 필터링을 dplyr::filter() 함수로 진행
diamonds %>% filter(cut == "Ideal")
filter(diamonds, cut != "Ideal")
diamonds %>% filter(cut != "Ideal")


x <- filter(diamonds, cut == "Ideal")
table(x$cut, useNA = "ifany")			# cut 컬럼의 데이터가 Ideal인 레코드만 필터링 됐는지 확인 


  • 고전적인 대괄호 연산자 방식은 코딩이 중복된다.
  • subset() 보다는 filter() 함수의 연산이 빠르다.


  • 참고: 파이프 연산자의 장점: 아래와 같은 식이 몹시 간편
diamonds %>% filter (cut == "Ideal") %>%		# cut 변수에서 Ideal 값 가지는 레코드만 필터링
		     select(cut) %>%					# cut 컬럼 인덱싱
		     table(useNA = "ifany") %>%			# cut 컬럼의 항목 별로 빈도 수 반환
		     addmargins %>%						# 위의 테이블에 sum 항목이 있도록 해서 총합 확인
		     as.data.frame 						# 테이블을 데이터프레임 유형으로 변경


(2) 특정 범주형 변수 1개에 대한 복합 조건 포함하는 레코드 필터링


  • 직접 필터링
diamonds[diamonds$cut %in% c("Ideal", "Good"), ]				# %in%: or 조건 표시
diamonds[diamonds$cut == "Ideal" | diamonds$cut == "Good", ]
diamonds[which(diamonds$cut == "Ideal" | diamonds$cut == "Good"), ]
diamonds[with(diamonds, cut == "Ideal" | cut == "Good"), ]		# with() 문법: 괄호 안에 데이터셋 한번 설정하면 모든 개별 변수에 영향을 미친다.


x <- diamonds[diamonds$cut %in% c("Ideal", "Good"), ]
table(x$cut, useNA ="ifany")			# cut 변수는 Ideal 과 Good 값만 들어있는지 확인


  • subset()
subset(diamonds, cut %in% c("Ideal", "Good"))
subset(diamonds, cut == "Ideal" | cut == "Good")
diamonds %>% subset(cut %in% c("Ideal", "Good"))
diamonds %>% subset(cut == "Ideal" | cut == "Good")


y <- subset(diamonds, cut %in% c("Ideal", "Good"))
table(y%cut, useNA = "ifany")						# 필터링 확인


  • dplyr::filter()
library(dplyr)

filter(diamonds, cut %in% c("Ideal", "Good"))
filter(diamonds, cut == "Ideal" | cut == "Good")
diamonds %>% filter(cut %in% c("Ideal", "Good"))
diamonds %>% filter(cut == "Ideal" | cut == "Good")


y <- filter(diamonds, cut %in% c("Ideal", "Good"))
table(y$cut, useNA = "ifany")				# 필터링 확인

diamonds %>% filter(cut %in% c("Ideal", "Good")) %>%
		 	 select(cut) %>% table(useNA = "ifany") %>% 
		 	 addmargins %>%
		 	 as.data.frame 					# 필터링 확인


(3) 특정 범주형 변수 1개에 대한 복합 조건 제외하는 레코드 필터링


diamonds[diamonds$cut != "Ideal" & diamonds$cut != "Good", ]			# 대괄호 연산자로 필터링
diamonds[which(diamonds$cut != "Ideal" & diamonds$cut != "Good"), ]
diamonds[with(diamonds, cut != "Ideal" & cut != "Good"), ]


subset(diamonds, cut != "Ideal" & cut != "Good")						# subset() 함수로 필터링
diamonds %>% subset(cut != "Ideal" & cut != "Good")


filter(diamonds, cut != "Ideal" & cut != "Good")						# dplyr::filter() 함수로 필터링
filter(diamonds, cut != "Ideal", cut != "Good")
dimonds %>% filter(cut != "Ideal" & cut != "Good")


y <- filter(diamonds, cut != "Ideal" & cut != "Good")
table(y$cut, useNA = "ifany")


(4) 특정 범주형 변수 2개에 대한 복합 조건 포함하는 레코드 필터링


  • 대괄호 연산자로 필터링
diamonds[diamonds$cut == "Ideal" & diamonds$clarity == "VS2", ]
diamonds[which(diamonds$cut == "Ideal" & diamonds$clarity == "VS2"), ]
diamonds[with(diamonds, cut == "Ideal" & clarity == "VS2"), ]


x <- diamonds[with(diamonds, cut == "Ideal" & clarity == "VS2"), ]
table(x$cut, dnn = "커팅 품질 항목별 빈도수")
table(x$clarity, dnn = "투명도 항목별 빈도수")


  • subset() 함수로 필터링
subset(diamonds, cut == "Ideal" & clarity == "VS2")
diamonds %>% subset(cut == "Ideal" & clarity == "VS2")


y <- subset(diamonds, cut == "Ideal" & clarity == "VS2")
table(y$cut, dnn = "커팅 품질 항목별 빈도수")
table(y$clarity, dnn = "투명도 항목별 빈도수")


  • dplyr::filter() 함수로 필터링
filter(diamonds, cut == "Ideal" & clarity == "VS2")
diamonds %>% filter(cut == "Ideal" & clarity == "VS2")


(5) 특정 연속형 변수 1개에 대한 특정 조건 일치하는 레코드 필터링


  • 대괄호 연산자로 필터링
diamonds[diamonds$price >= 1000, ]
diamonds[which(diamonds$price >= 1000), ]


x <- diamonds[diamonds$price >= 1000, ]
summary(x$price)


  • subset() 함수로 필터링
subset(diamonds, price >= 1000)
diamonds %>% subset(price >= 1000)


y <- subset(diamonds, price >= 1000)
summary(y$price)


  • dplyr::filter() 함수로 필터링
filter(diamonds, price >= 1000)
diamonds %>% filter(price >= 1000)

diamonds %>% filter(price >= 1000) %>%
			 select(price) %>%
			 summary


(6) 특정 연속형 변수 2개에 대한 복합 조건 일치하는 레코드 필터링


diamonds[diamonds$carat > 2 & diamonds$price < 14000, ]			# 대괄호 연산자로 필터링
diamonds[which(diamonds$carat > 2 & diamonds$price < 14000), ]
diamonds[with(diamonds, carat > 2 & price < 14000), ]


subset(diamonds, carat > 2 & price < 14000)						# subset() 함수로 필터링
subset(diamonds, carat > 2, price < 14000)
diamonds %>% subset(carat > 2 & price < 14000)
diamonds %>% subset(carat > 2, price < 14000)


filter(diamonds, carat > 2 & price < 14000)						# dplyr::filter() 함수로 필터링
filter(diamonds, carat > 2, price  , 14000)
diamonds %>% filter(carat > 2 & price < 14000)
diamonds %>% filter(carat > 2, price < 14000)


y <- subset(diamonds, carat > 2 & price < 14000)				# 필터링이 잘 됐는지 확인
summary(y$carat)
summary(y$price)


diamonds %>% filter(carat > 2, price < 14000) %>%
			 select(carat, price) %>%
			 summary


  • 만일 & 와 가 동시에 있으면 연산 우선순위는 &


(7) 범주형과 연속형 변수에 대한 복합 조건과 일치하는 레코드 필터링


diamonds[diamonds$cut == "Ideal" & diamonds$price > 15000, ]
diamonds[which(diamonds$cut == "Ideal" & diamonds$price > 15000), ]
diamonds[with(diamonds, cut == "Ideal" & price > 15000), ]


x <- diamonds[diamonds$cut == "Ideal" & diamonds$price > 15000, ]
summary(x[c("cut", "price")])



6. 데이터셋에 있는 특정 관찰치를 슬라이싱(slicing) 하기


(1) 특정 일치행 1개범위 지정 슬라이싱: [] / dplyr::slice()


diamonds[5, ]			# 대괄호 연산자로 5행 슬라이싱


library(dplyr)
slice(diamonds, 5)		# slice() 함수로 5행 슬라이싱


(2) 특정 일치행 1개범위 제외 슬라이싱


diamonds[-5, ]

library(dplyr)
slice(diamonds, -5)
diamonds %>% slice(-5)


(3) 특정 일치행 복수범위 지정 슬라이싱


diamonds[c(2, 7, 3:5), ]

slice(diamonds, c(2, 7, 3:5))
diamonds %>% slice(c(2, 7, 3:5))


(4) 특정 일치행 복수범위 제외 슬라이싱


diamonds[-c(2, 7, 3:5), ]
slice(diamonds, -c(2, 7, 3:5))
diamonds %>% slice(-c(2, 7, 3:5))



7. 데이터셋에 있는 특정 관찰치를 무작위 추출(sampling) 하기


(1) 레코드 개수만큼 무작위 추출하는 경우: sample() / dplyr::sample_n()


base::sample() 함수 이용한 비복원추출


set.seed(1)			# 샘플링 재현성을 위한 초기 난수값 생성

index <- sample(1:nrow(diamonds), size = 100, replace = FALSE)
index 				# diamonds 데이터셋의 레코드번호가 무작위로 100개 비복원 추출됨

sub.dd <- diamonds[index, ]
sub.dd


  • boosting 기법: 데이터가 작을 때 데이터를 키우는 기법
  • 주어진 데이터셋을 여러번 복원 추출해서 계속 학습시킨다.
  • 복원 추출할 때는 replace인자값을 TRUE로 준다.
base::sample() 함수 이용한 복원추출


set.seed(200)			# 샘플링 재현성을 위한 초기 난수값 생성

index2 <- sample(1:100, size = 1000, replace = TRUE)
index2 				# diamonds 데이터셋의 레코드번호가 무작위로 1000개 복원 추출됨

sub.dd2 <- diamonds[index2, ]
sub.dd2
skim(sub.dd2)


dplyr::sample_n() 함수 이용한 비복원추출


set.seed(1234)			# 샘플링 재현성을 위한 초기 난수값 생성

result <- sample_n(diamonds, size = 100, replace = FALSE)	# 레코드 번호 아닌, 실제 레코드 내용을 추출
result


set.seed(1234)
diamonds %>% sample_n(size = 100) %>% skim


  • 이 기법은 머신러닝에서 많이 쓴다.


dplyr::sample_n() 함수 이용한 복원추출


set.seed(5678)			# 샘플링 재현성을 위한 초기 난수값 생성

result2 <- sample_n(diamonds[1:100, ], size = 1000, replace = TRUE)	# 레코드 번호 아닌, 실제 레코드 내용을 추출
result2


set.seed(5678)
diamonds %>% slice(1:100) %>% sample_n(size = 1000, replace = TRUE %>% skim


(2) 레코드 비율만큼 무작위 추출하는 경우: : sample() / dplyr::sample_frac()


base::sample() 함수 이용한 비율추출


set.seed(333)			# 샘플링 재현성을 위한 초기 난수값 생성

index <- sample(1:nrow(diamonds), size = nrow(diamonds)*0.7, replace = FALSE)
index 				# 5만 여개 레코드의 0.7배(70%)인 약 3만 여개의 레코드 번호 추출

train.dd <- diamonds[index, ]		# train 데이터 70%
train.dd
skim(train.dd)

test.dd <- diamonds[-index, ]		# test 데이터 30%
test.dd
skim(test.dd)


dplyr::sample_frac() 함수 이용한 비율추출


set.seed(1234)			# 샘플링 재현성을 위한 초기 난수값 생성

TrainD <- sample_frac(diamonds, size = 0.7, replace = FALSE)
TrainD					# train 데이터 70%
skim(TrainD)


TestD <- dplyr::setdiff(diamonds, TrainD)
TestD					# test 데이터 30%
skim(TestD)



8. 레코드 대상 필터링 구현 시 정규표현식 사용


(1) cut 변수에 good 이라는 단어가 들어간 레코드 조회: [] / subset() / dplyr::filter()


대괄호연산자 사용 필터링


table(diamonds$cut)

grep("good", diamonds$cut, ignore.case = TRUE)	 				# 해당 레코드 번호 추출
grep("good", diamonds$cut, ignore.case = TRUE, value = TRUE)	# 해당 레코드 값 추출 
grepl("good", diamonds$cut, ignore.case = TRUE) 				# 해당 레코드의 논리값 추출


diamonds[grep("good", diamonds$cut, ignore.case = TRUE), ]
diamonds[grepl("good", diamonds$cut, ignore.case = TRUE), ]
x <- diamonds[grep("good", diamonds$cut, ignore.case = TRUE), ]
table(x$cut)


  • grepl: grep logical


subset() 함수 사용 필터링


subset(diamonds, grepl("good", diamonds$cut, ignore.case = TRUE))

y <- diamonds[diamonds, grepl("good", diamonds$cut, ignore.case = TRUE), ]
table(y$cut)		# 필터링 결과 확인


dplyr::filter() 함수 사용 필터링


filter(diamonds, grepl("good", diamonds$cut, ignore.case = TRUE))
diamonds %>% filter(grepl("good", diamonds$cut, ignore.case = TRUE))

diamonds %>% filter(grepl("good", diamonds$cut, ignore.case = TRUE)) %>% 
			 select(cut) %>%
			 table 					# 필터링 결과 확인


(2) clarity 변수에 “문자v+아무문자+숫자”가 들어간 레코드 조회


[] 연산자 사용 필터링
table(diamonds$clarity)

grep("v.+\\d", diamonds$clarity, ignore.case = TRUE)				# 해당 레코드 번호 추출
grep("v.+\\d", diamonds$clarity, ignore.case = TRUE, value = TRUE)	# 해당 레코드 값 추출
grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE)				# 해당 레코드 논리값 추출


diamonds[grep("v.+\\d", diamonds$clarity, ignore.case = TRUE), ]
diamonds[grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE), ]


x <- diamonds[grep("v.+\\d", diamonds$clarity, ignore.case = TRUE), ]
table(x$clarity)


subset() 함수 사용 필터링


subset(diamonds, grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE))


y <- subset(diamonds, grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE))
table(y$clarity)		# 필터링 결과 확인


dplyr::filter() 함수 사용 필터링


filter(diamonds, grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE))
diamonds %>% filter(grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE))


diamonds %>% filter(grepl("v.+\\d", diamonds$clarity, ignore.case = TRUE)) %>%
  			 select(clarity) %>% table 			# 필터링 결과 확인



<참고 문헌="">


  1. 데이터과학 입문자를 위한 R (제리드 랜더 지음)
  2. 최점기 박사님 강의
comments powered by Disqus