2 R 설치 및 기본 사용법


2.1 R 및 RStudio 개요


  • R은 통계 계산과 그래픽을 위한 프로그래밍 언어인 프리웨어이다.
  • R은 다양한 통계 기법과 수치 해석 기법을 지원한다.
  • R은 사용자가 제작한 패키지를 추가하여 기능을 확장할 수 있다.
  • R은 수학 기호를 포함할 수 있는 출판물 수준의 그래프를 제공한다.
  • Rstudio: 오픈 소스인 R를 좀 더 편하게 사용하기 위해 개발된 프로그램(IDE, 통합 개발 환경)이다.


2.2 R 및 RStudio 설치 방법


2.2.1 R 설치하기


  • R 공식 웹사이트에 접속합니다: https://cran.r-project.org/
  • 운영체제에 맞는 설치 파일을 선택합니다 (Windows, macOS, Linux).
  • 다운로드한 파일을 실행하여 설치를 진행합니다. 기본 설정으로 설치해도 무방합니다.


2.2.2 R Studio 설치하기

  • RStudio 공식 웹사이트에 접속합니다: https://posit.co/downloads/
  • 운영체제에 맞는 설치 파일을 선택합니다 (Windows, macOS, Linux).
  • 다운로드한 파일을 실행하여 설치를 진행합니다. 기본 설정으로 설치해도 무방합니다.


2.3 기본적인 R 명령어와 스크립트 작성 방법


2.3.1 기본적인 R 명령어


2.3.1.1 변수 할당: <- 연산자를 사용하여 변수를 할당합니다.

x <- 10
y <- 20


2.3.1.2 벡터 생성: c() 함수를 사용하여 벡터를 생성합니다.

numbers <- c(1, 2, 3, 4, 5)


2.3.1.3 기본 연산: 사칙연산을 수행할 수 있습니다.

sum <- x + y
product <- x * y


2.3.1.4 함수 사용: mean(), sum() 등의 기본 함수를 사용할 수 있습니다.

average <- mean(numbers)
total <- sum(numbers)


2.3.2 스크립트 작성 방법


2.3.2.1 RStudio에서 새로운 스크립트 파일 생성


상단 메뉴에서 File -> New File -> R Script를 선택합니다.


2.3.2.2 스크립트 작성


스크립트 창에 코드를 작성합니다. 예를 들어, 다음과 같이 작성할 수 있습니다.


# 변수 할당
x <- 10
y <- 20

# 벡터 생성
numbers <- c(1, 2, 3, 4, 5)

# 기본 연산
sum <- x + y
product <- x * y

# 함수 사용
average <- mean(numbers)
total <- sum(numbers)

# 결과 출력
print(paste("Sum:", sum))
print(paste("Product:", product))
print(paste("Average:", average))
print(paste("Total:", total))


2.3.2.3 스크립트 실행


  • 작성한 스크립트를 실행하려면, 스크립트 창에서 Ctrl + Enter를 눌러 현재 줄을 실행하면 됩니다.
  • 전체 스크립트를 실행하려면 Source 버튼을 클릭합니다. 이 때 반드시 해당 내용을 저장한 뒤 실행해야 합니다.


2.4 RStudio 인터페이스 소개 및 기본 설정


2.4.1 RStudio 인터페이스 소개


RStudio는 R 프로그래밍 언어를 위한 통합 개발 환경(IDE)입니다. RStudio의 주요 패널과 기능을 소개합니다.


2.4.1.1 스크립트 창 (Script Editor)


  • 위치: 좌측 상단
  • 기능: 코드를 작성하고 편집하는 공간입니다. 작성한 코드를 저장하고 실행할 수 있습니다.


2.4.1.2 콘솔 (Console)


  • 위치: 좌측 하단
  • 기능: R 명령어를 직접 입력하고 실행 결과를 확인할 수 있는 공간입니다.


2.4.1.3 환경/히스토리 (Environment/History)


  • 위치: 우측 상단
  • 기능: 현재 작업 중인 변수와 데이터 객체를 확인할 수 있으며, 이전에 실행한 명령어의 기록을 볼 수 있습니다.


2.4.1.4 파일/플롯/패키지/헬프 (Files/Plots/Packages/Help)


  • 위치: 우측 하단
  • 기능:
    • Files: 작업 디렉토리의 파일을 탐색하고 관리할 수 있습니다.
    • Plots: 생성된 그래프를 확인할 수 있습니다.
    • Packages: 설치된 패키지를 관리하고 새로운 패키지를 설치할 수 있습니다.
    • Help: R 함수와 패키지에 대한 도움말을 검색할 수 있습니다.


2.4.2 RStudio 기본 설정


RStudio를 처음 사용할 때 설정해야 할 몇 가지 기본 사항을 소개합니다.


2.4.2.1 테마 및 레이아웃 설정


  • 테마 변경: Tools -> Global Options -> Appearance에서 테마를 변경할 수 있습니다.
  • 레이아웃 조정: Tools -> Global Options -> Pane Layout에서 패널의 위치를 조정할 수 있습니다.
  • 작업 디렉토리 설정
    • 작업 디렉토리 설정: Session -> Set Working Directory -> Choose Directory를 선택하여 작업 디렉토리를 설정합니다.
    • 단축키: Ctrl + Shift + H를 사용하여 작업 디렉토리를 설정할 수 있습니다.
  • 기본 패키지 설치
    • 자주 사용하는 패키지를 설치합니다. 예를 들어, tidyverse 패키지를 설치하려면 콘솔에서 다음 명령어를 실행합니다:


install.packages("tidyverse")


2.5 간단한 연산과 함수 사용법


2.5.1 기본 연산


R에서는 다양한 연산자를 사용하여 기본적인 산술 연산을 수행할 수 있습니다.


2.5.1.1 산술 연산자


# 덧셈: +

5 + 3  
## [1] 8
# 뺄셈: -

5 - 3  
## [1] 2
# 곱셈: *

5 * 3
## [1] 15
# 나눗셈: /

5 / 3  
## [1] 1.666667
# 나머지: %%

5 %% 3
## [1] 2
# 몫: %/%

5 %/% 3
## [1] 1
# 지수: ^ 또는 **

5 ^ 3  
## [1] 125


2.5.1.2 관계 연산자


# 크다: >

5 > 3  
## [1] TRUE
# 작다: <

5 < 3  
## [1] FALSE
# 같다: ==

5 == 3  
## [1] FALSE
# 다르다: !=

5 != 3  
## [1] TRUE


2.5.1.3 논리 연산자


# AND: &

(5 > 3) & (3 > 1)  
## [1] TRUE
# OR: |

(5 > 3) | (3 < 1)  
## [1] TRUE
# NOT: !

!(5 > 3)  
## [1] FALSE


2.5.2 함수 사용


2.5.2.1 데이터 요약 함수


# summary(): 데이터의 요약 통계를 제공합니다.

data <- mtcars$mpg
summary(data)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   10.40   15.43   19.20   20.09   22.80   33.90
# str(): 데이터 구조를 확인합니다.

str(mtcars)
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...


2.5.2.2 수학 함수


# sqrt(): 제곱근을 계산합니다.

sqrt(16) 
## [1] 4
# log(): 로그 값을 계산합니다.

log(10)
## [1] 2.302585
log10(10)
## [1] 1
log(4, base=2)
## [1] 2
# exp(): 지수 값을 계산합니다.

exp(10)  
## [1] 22026.47


2.5.2.3 통계 함수


data <- mtcars$mpg

# mean(): 평균을 계산합니다.

mean(data)  
## [1] 20.09062
# median(): 중앙값을 계산합니다.

median(data)  
## [1] 19.2
# sd(): 표준편차를 계산합니다.

sd(data)  
## [1] 6.026948


2.5.2.4 데이터 변환 함수


data <- mtcars$mpg

# sort(): 데이터를 정렬합니다.

sort(data, decreasing = T)
##  [1] 33.9 32.4 30.4 30.4 27.3 26.0 24.4 22.8 22.8 21.5 21.4 21.4 21.0 21.0 19.7
## [16] 19.2 19.2 18.7 18.1 17.8 17.3 16.4 15.8 15.5 15.2 15.2 15.0 14.7 14.3 13.3
## [31] 10.4 10.4
# unique(): 중복을 제거한 고유 값을 반환합니다.

unique(data)
##  [1] 21.0 22.8 21.4 18.7 18.1 14.3 24.4 19.2 17.8 16.4 17.3 15.2 10.4 14.7 32.4
## [16] 30.4 33.9 21.5 15.5 13.3 27.3 26.0 15.8 19.7 15.0
# scale(): 데이터를 표준화합니다.

head(scale(data))
##            [,1]
## [1,]  0.1508848
## [2,]  0.1508848
## [3,]  0.4495434
## [4,]  0.2172534
## [5,] -0.2307345
## [6,] -0.3302874


2.5.2.5 사용자 정의 함수


사용자 정의 함수: 특정 작업을 수행하는 함수를 직접 정의할 수 있습니다.


# 두 수의 합을 구하는 함수

add <- function(a, b) {
  return(a + b)
}

add(5, 3)  
## [1] 8
# 정규화 함수: 데이터를 0과 1 사이로 정규화하는 함수(백분위수화)

normalize <- function(x) {
  return((x - min(x)) / (max(x) - min(x)))
}

normalize(data)
##  [1] 0.4510638 0.4510638 0.5276596 0.4680851 0.3531915 0.3276596 0.1659574
##  [8] 0.5957447 0.5276596 0.3744681 0.3148936 0.2553191 0.2936170 0.2042553
## [15] 0.0000000 0.0000000 0.1829787 0.9361702 0.8510638 1.0000000 0.4723404
## [22] 0.2170213 0.2042553 0.1234043 0.3744681 0.7191489 0.6638298 0.8510638
## [29] 0.2297872 0.3957447 0.1957447 0.4680851


2.5.2.6 데이터 시각화 함수


data <- mtcars$mpg

# plot(): 기본적인 산점도를 그립니다.

plot(data)


3 데이터 관리 및 시각화 기초


3.1 데이터 구조와 유형 이해 (벡터, 리스트, 데이터 프레임)


3.1.1 벡터 (Vector)


벡터는 동일한 유형의 데이터를 저장하는 1차원 배열입니다. R에서 가장 기본적인 데이터 구조입니다.


# 벡터 생성: c() 함수를 사용하여 벡터를 생성합니다.

c(1, 2, 3, 4, 5)  # 숫자 벡터
## [1] 1 2 3 4 5
c("a", "b", "c")  # 문자 벡터
## [1] "a" "b" "c"
c(3>2, 2<1, 5>3)  # 논리 벡터
## [1]  TRUE FALSE  TRUE
# 벡터 연산: 벡터 간의 연산은 요소별로 수행됩니다.

numeric_vector <- c(1, 2, 3, 4, 5)
numeric_vector + 2  # 각 요소에 2를 더함
## [1] 3 4 5 6 7
# 벡터 접근: 인덱스를 사용하여 벡터의 요소에 접근합니다.

numeric_vector[1]  # 첫 번째 요소
## [1] 1


3.1.2 리스트 (List)


리스트는 서로 다른 유형의 데이터를 저장할 수 있는 1차원 배열입니다. 벡터와 달리 다양한 데이터 유형을 포함할 수 있습니다.


# 리스트 생성: list() 함수를 사용하여 리스트를 생성합니다.

my_list <- list(name = "John", age = 25, scores = c(90, 85, 88))

# 리스트 접근: $ 연산자 또는 인덱스를 사용하여 리스트의 요소에 접근합니다.

my_list$name  # name 서브 리스트 값을 보여준다 
## [1] "John"
my_list["age"] # age 서브 리스트를 보여준다 
## $age
## [1] 25
my_list[["age"]] # age 서브 리스트 값을 보여준다 
## [1] 25
my_list[3] # 세번째 서브 리스트를 보여준다 
## $scores
## [1] 90 85 88
my_list[[3]] # 세번째 서브 리스트의 값을 보여준다
## [1] 90 85 88


3.1.3 데이터 프레임 (Data Frame)


데이터 프레임은 행과 열로 구성된 2차원 데이터 구조로, 각 열은 서로 다른 유형의 데이터를 가질 수 있습니다. 데이터 분석에서 가장 많이 사용되는 구조입니다.


# 데이터 프레임 생성: data.frame() 함수를 사용하여 데이터 프레임을 생성합니다.

df <- data.frame(
  name = c("John", "Jane", "Doe"),
  age = c(25, 30, 22),
  scores = c(90, 85, 88)
)

# 데이터 프레임 접근: $ 연산자 또는 인덱스를 사용하여 데이터 프레임의 요소에 접근합니다.

names <- df$name  # "John", "Jane", "Doe"
first_row <- df[1, ]  # 첫 번째 행
first_column <- df[, 1]  # 첫 번째 열

# 데이터 프레임 요약: summary() 함수를 사용하여 데이터 프레임의 요약 통계를 확인합니다.

summary(df)
##      name                age            scores     
##  Length:3           Min.   :22.00   Min.   :85.00  
##  Class :character   1st Qu.:23.50   1st Qu.:86.50  
##  Mode  :character   Median :25.00   Median :88.00  
##                     Mean   :25.67   Mean   :87.67  
##                     3rd Qu.:27.50   3rd Qu.:89.00  
##                     Max.   :30.00   Max.   :90.00


3.2 데이터 입력, 정리, 기본 데이터 조작


3.2.1 데이터 입력


3.2.1.1 CSV 파일 읽기: read.csv() 함수를 사용합니다.


precip <- read.csv("precip.csv")
head(precip)
##   X names.precip. precip
## 1 1        Mobile   67.0
## 2 2        Juneau   54.7
## 3 3       Phoenix    7.0
## 4 4   Little Rock   48.5
## 5 5   Los Angeles   14.0
## 6 6    Sacramento   17.2


3.2.1.2 엑셀 파일 읽기: read.excel() 함수를 사용합니다.


# readxl 패키지 설치 및 로드 

# install.packages("readxl")
library(readxl)

# 엑셀 파일 읽기

bt <- read_excel("BreastTissue.xls", sheet="Data")
head(bt)
## # A tibble: 6 × 11
##   `Case #` Class    I0 PA500    HFS    DA   Area `A/DA` `Max IP`    DR     P
##      <dbl> <chr> <dbl> <dbl>  <dbl> <dbl>  <dbl>  <dbl>    <dbl> <dbl> <dbl>
## 1        1 car    525. 0.187 0.0321  229.  6844.   29.9     60.2 221.   557.
## 2        2 car    330  0.227 0.265   121.  3163.   26.1     69.7  99.1  400.
## 3        3 car    552. 0.232 0.0635  265. 11888.   44.9     77.8 254.   657.
## 4        4 car    380  0.241 0.286   138.  5402.   39.2     88.8 105.   494.
## 5        5 car    363. 0.201 0.244   125.  3290.   26.3     69.4 104.   425.
## 6        6 car    390. 0.150 0.0977  119.  2476.   20.9     49.8 108.   429.


3.2.1.3 직접 입력


# data.frame()함수로 데이터프레임 형태로 입력 
data <- data.frame(
  name = c("John", "Jane", "Doe"),
  age = c(25, 30, 22),
  scores = c(90, 85, 88)
)
data
##   name age scores
## 1 John  25     90
## 2 Jane  30     85
## 3  Doe  22     88


3.2.2 데이터 정리


데이터를 정리하는 데는 dplyr 패키지가 유용합니다. dplyr 패키지를 사용하면 데이터를 쉽게 필터링, 선택, 변환할 수 있습니다.


# 패키지 설치 및 로드:

# install.packages("dplyr")
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
# 데이터 필터링: 특정 조건에 맞는 데이터를 필터링할 수 있습니다.
# filter() 함수: 조건에 맞는 행을 선택합니다.
mt_mpg_ge_30 <- filter(mtcars, mpg >= 30)
mt_mpg_ge_30
##                 mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Fiat 128       32.4   4 78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic    30.4   4 75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla 33.9   4 71.1  65 4.22 1.835 19.90  1  1    4    1
## Lotus Europa   30.4   4 95.1 113 3.77 1.513 16.90  1  1    5    2
# 데이터 선택: 특정 열을 선택할 수 있습니다.
# select() 함수: 원하는 열만 선택합니다.


# 필요한 패키지 로드
library(tibble)

# 행 이름을 "car" 열로 변환하여 데이터프레임에 추가
mtcars <- rownames_to_column(mtcars, var = "car")

# 변경된 데이터셋 확인
select_mtcars <- select(mtcars, car, mpg)
head(select_mtcars)
##                 car  mpg
## 1         Mazda RX4 21.0
## 2     Mazda RX4 Wag 21.0
## 3        Datsun 710 22.8
## 4    Hornet 4 Drive 21.4
## 5 Hornet Sportabout 18.7
## 6           Valiant 18.1
# 데이터 변환: 데이터를 변환하거나 새로운 열을 추가할 수 있습니다.
# mutate() 함수: 새로운 열을 추가합니다.

transformed_data <- mutate(select_mtcars, mpg_category = ifelse(mpg > 20, "High", "Low"))
head(transformed_data)
##                 car  mpg mpg_category
## 1         Mazda RX4 21.0         High
## 2     Mazda RX4 Wag 21.0         High
## 3        Datsun 710 22.8         High
## 4    Hornet 4 Drive 21.4         High
## 5 Hornet Sportabout 18.7          Low
## 6           Valiant 18.1          Low


3.3 기술통계량 계산 및 요약 보고서 생성


mtcars data로 기술통계량을 계산하고 요약 보고서를 만들어보겠습니다.


3.3.1 기술통계량 계산


# mtcars 데이터셋 로드
data(mtcars)

# 데이터셋 구조 확인
str(mtcars)
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
# 기술통계량 계산
# summary() 함수를 사용한 기본 통계량 계산
summary(mtcars)
##       mpg             cyl             disp             hp       
##  Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  
##  1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  
##  Median :19.20   Median :6.000   Median :196.3   Median :123.0  
##  Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  
##  3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  
##  Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0  
##       drat             wt             qsec             vs        
##  Min.   :2.760   Min.   :1.513   Min.   :14.50   Min.   :0.0000  
##  1st Qu.:3.080   1st Qu.:2.581   1st Qu.:16.89   1st Qu.:0.0000  
##  Median :3.695   Median :3.325   Median :17.71   Median :0.0000  
##  Mean   :3.597   Mean   :3.217   Mean   :17.85   Mean   :0.4375  
##  3rd Qu.:3.920   3rd Qu.:3.610   3rd Qu.:18.90   3rd Qu.:1.0000  
##  Max.   :4.930   Max.   :5.424   Max.   :22.90   Max.   :1.0000  
##        am              gear            carb      
##  Min.   :0.0000   Min.   :3.000   Min.   :1.000  
##  1st Qu.:0.0000   1st Qu.:3.000   1st Qu.:2.000  
##  Median :0.0000   Median :4.000   Median :2.000  
##  Mean   :0.4062   Mean   :3.688   Mean   :2.812  
##  3rd Qu.:1.0000   3rd Qu.:4.000   3rd Qu.:4.000  
##  Max.   :1.0000   Max.   :5.000   Max.   :8.000
# mtcars 중 수치형 필드만 선택
mtcars1 <- mtcars[,c(1,3:7)]

# 각 열의 평균 계산
colMeans(mtcars1, na.rm = TRUE)
##        mpg       disp         hp       drat         wt       qsec 
##  20.090625 230.721875 146.687500   3.596563   3.217250  17.848750
# 각 열의 중앙값 계산
apply(mtcars1, 2, median, na.rm = TRUE)
##     mpg    disp      hp    drat      wt    qsec 
##  19.200 196.300 123.000   3.695   3.325  17.710
# 각 열의 표준편차 계산
apply(mtcars1, 2, sd, na.rm = TRUE)
##         mpg        disp          hp        drat          wt        qsec 
##   6.0269481 123.9386938  68.5628685   0.5346787   0.9784574   1.7869432


3.3.2 요약보고서 작성


# 필요한 패키지 설치 및 로드
# install.packages("psych")
library(psych)

# 기술통계량 요약 테이블 생성
describe(mtcars)
##      vars  n   mean     sd median trimmed    mad   min    max  range  skew
## mpg     1 32  20.09   6.03  19.20   19.70   5.41 10.40  33.90  23.50  0.61
## cyl     2 32   6.19   1.79   6.00    6.23   2.97  4.00   8.00   4.00 -0.17
## disp    3 32 230.72 123.94 196.30  222.52 140.48 71.10 472.00 400.90  0.38
## hp      4 32 146.69  68.56 123.00  141.19  77.10 52.00 335.00 283.00  0.73
## drat    5 32   3.60   0.53   3.70    3.58   0.70  2.76   4.93   2.17  0.27
## wt      6 32   3.22   0.98   3.33    3.15   0.77  1.51   5.42   3.91  0.42
## qsec    7 32  17.85   1.79  17.71   17.83   1.42 14.50  22.90   8.40  0.37
## vs      8 32   0.44   0.50   0.00    0.42   0.00  0.00   1.00   1.00  0.24
## am      9 32   0.41   0.50   0.00    0.38   0.00  0.00   1.00   1.00  0.36
## gear   10 32   3.69   0.74   4.00    3.62   1.48  3.00   5.00   2.00  0.53
## carb   11 32   2.81   1.62   2.00    2.65   1.48  1.00   8.00   7.00  1.05
##      kurtosis    se
## mpg     -0.37  1.07
## cyl     -1.76  0.32
## disp    -1.21 21.91
## hp      -0.14 12.12
## drat    -0.71  0.09
## wt      -0.02  0.17
## qsec     0.34  0.32
## vs      -2.00  0.09
## am      -1.92  0.09
## gear    -1.07  0.13
## carb     1.26  0.29


3.4 간단한 데이터 시각화 (히스토그램, 박스 플롯)


mtcars data의 mpg로 시각화하겠습니다.


# 시각화: 히스토그램
hist(mtcars$mpg)

# 상자 그림 생성
boxplot(mtcars$mpg)


3.5 ggplot2 패키지의 기본 구조와 사용법


  • ggplot2는 R 언어에서 데이터 시각화를 위한 강력한 패키지입니다.
  • 데이터 시각화를 체계적으로 구성할 수 있습니다.


3.5.1 ggplot2의 기본 구조


ggplot(data = , mapping = aes()) + ()


  • data: 시각화할 데이터 프레임
  • mapping: aes() 함수로 변수와 시각적 속성을 매핑
  • geom_function: 시각화 유형을 지정하는 함수 (예: geom_point(), geom_line())


3.5.2 mtcars 차량 무게와 연비 산점도


# ggplot2 패키지 설치 및 로드
# install.packages("ggplot2")
library(ggplot2)
## 
## 다음의 패키지를 부착합니다: 'ggplot2'
## The following objects are masked from 'package:psych':
## 
##     %+%, alpha
# 산점도 (Scatter Plot)

# 기본 산점도
ggplot(data = mtcars, mapping = aes(x = wt, y = mpg)) +
  geom_point()

# 레이어 추가: ggplot2는 여러 레이어를 추가하여 시각화를 풍부하게 할 수 있습니다.
ggplot(data = mtcars, mapping = aes(x = wt, y = mpg)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE)  # geom_smooth(): 회귀선을 추가하는 함수
## `geom_smooth()` using formula = 'y ~ x'

# 색상 및 테마 설정
ggplot(data = mtcars, mapping = aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point() +
  theme_minimal()

# color: 점의 색상을 실린더 수에 따라 다르게 설정
# theme_minimal(): 미니멀한 테마 적용

# 축 및 제목 설정
ggplot(data = mtcars, mapping = aes(x = wt, y = mpg)) +
  geom_point() +
  labs(title = "산점도 예제", x = "Weight", y = "Miles per Gallon")

# labs(): 제목과 축 레이블 설정


3.5.3 mpg데이터의 class별 고속도로 연비 분포 상자수염그림


# ggplot2 패키지 설치 및 로드
# install.packages("ggplot2")
library(ggplot2)

# mpg 데이터셋을 사용하여 boxplot 생성
ggplot(data = mpg, mapping = aes(x = class, y = hwy, color = factor(cyl))) +
  geom_boxplot() +
  labs(title = "Class별 연비 분포", x = "Class", y = "Highway Miles per Gallon") +
  theme_minimal()


3.6 다양한 유형의 그래프 생성


3.6.1 막대 그래프


막대그래프는 이산형 변수를 집계 내는 그래프로 막대 도표는 이산형 변수를 x축으로 두고, y축은 빈도(Counting)나 양을 표현하는 도표입니다.


# 빈도 시각화
library(gridExtra) # grid.arrange() 패키지 활성화
## 
## 다음의 패키지를 부착합니다: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library(carData) # TitanicSurvival 데이터가 있는 패키지 활성화

g1 <- ggplot(TitanicSurvival,aes(x=sex)) + geom_bar()
# x축에 sex 설정, y축은 설정하지 않음(자동집계; 빈도)
g2 <- ggplot(TitanicSurvival,aes(x=survived)) + geom_bar() 
g3 <- ggplot(TitanicSurvival,aes(x=passengerClass)) + geom_bar() 
g4 <- ggplot(TitanicSurvival,aes(x=age)) + geom_histogram(bins=10) 

grid.arrange(g1,g2,g3,g4,nrow=2,ncol=2)
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_bin()`).


3.6.1.1 막대 도표 – 색 변경


  • ggplot2에서는 col =, fill = 옵션을 줌으로써 그래프에 색을 더할 수가 있다.  
  • 점, 선과 처럼 면적이 없는 그래프는 col옵션을 통해 색을 바꿔주며, 면적이 있는 그래프들은 fill 옵션을 통해 색을 변경해준다.


ggplot(TitanicSurvival,aes(x=sex)) + geom_bar(fill = 'royalblue') # royalblue 색 채우기

g21 <- ggplot(TitanicSurvival,aes(x=sex)) + geom_bar(fill = "#1B9E77")  
g22 <- ggplot(TitanicSurvival,aes(x=survived)) + geom_bar(fill = "#D95F02") 
g23 <- ggplot(TitanicSurvival,aes(x=passengerClass)) + geom_bar(fill = "#7570B3") 
g24 <- ggplot(TitanicSurvival,aes(x=age)) + geom_histogram(fill = "#E7298A", bins=10) 

grid.arrange(g21,g22,g23,g24,nrow=2,ncol=2)
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_bin()`).


3.6.1.2 Survived 값에 따라 색 채우기


library(RColorBrewer)
# 그래프 여백 조정
par(cex = 0.7)  # 텍스트 크기를 70%로 설정
display.brewer.all(colorblindFriendly = TRUE)

brewer.pal(n = 4, name = "Dark2")
## [1] "#1B9E77" "#D95F02" "#7570B3" "#E7298A"
g31 <- ggplot(TitanicSurvival,aes(x=sex)) + geom_bar(aes(fill=survived)) + scale_fill_brewer(palette = "Dark2")  
g32 <- ggplot(TitanicSurvival,aes(x=passengerClass)) + geom_bar(aes(fill=survived)) + scale_fill_brewer(palette = "Dark2")
g33 <- ggplot(TitanicSurvival,aes(x=age)) + geom_histogram(aes(fill=survived),bins=10) + scale_fill_brewer(palette = "Dark2")
g34 <- ggplot(TitanicSurvival,aes(x=survived)) + geom_bar(aes(fill=passengerClass)) + scale_fill_brewer(palette = "Dark2")

grid.arrange(g31,g32,g33,g34,nrow=2,ncol=2)
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_bin()`).


3.6.1.3 막대 도표(Bar plot) - 범례


범례 이름 편집: labs(fill = )을 추가해줌으로써 색 구분 정보를 나타내는 label 제목을 바꿔줄 수 있다.


# 생존자 별 클래스 비율 시각화
ggplot(TitanicSurvival,aes(x=survived)) +  
  geom_bar(aes(fill=passengerClass)) +
  labs(fill = "Divided by passengerClass")

# 클래스별 생존자 비율 시각화
ggplot(TitanicSurvival,aes(x=passengerClass)) +  
  geom_bar(aes(fill=survived)) +
  labs(fill = "Divided by survived") 


3.6.1.4 범례 편집,위치 조정 텍스트 사이즈 10으로 조정


g41 <- g31 + labs(fill = "Divided by survived") + theme(text = element_text(size = 10), legend.position = "top")
g42 <- g32 + labs(fill = "Divided by survived") + theme(text = element_text(size = 10), legend.position = "top")
g43 <- g33 + labs(fill = "Divided by survived") + theme(text = element_text(size = 10), legend.position = "top")
g44 <- g34 + labs(fill = "Divided by passengerClass") + theme(text = element_text(size = 10), legend.position = "top")

grid.arrange(g41,g42,g43,g44,nrow=2,ncol=2)
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_bin()`).



geom_bar()에는 width=0.8이라고 기재하나 안하나 같은 그래프가 생성되지만, geom_text() 안에서는 반드시 width를 설정해줘야 label이 제대로 표시됨에 유의


ggplot(TitanicSurvival,aes(x=passengerClass, y=..count.., fill=survived)) +  
  geom_bar(position = "dodge", width=0.8) + 
  geom_text(stat = "count", aes(label=..count..),position = position_dodge(width=0.8), vjust=-0.5) + 
  scale_fill_brewer(palette = "Dark2") +
  labs(fill = "Divided by survived") + 
  theme(text = element_text(size = 10), legend.position = "top")
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.


누적막대그래프에서 막대 안쪽 가운데에 레이블을 위치. geom_text() 안의 position 항목을 position_stack()으로 설정. 그 안에서 vjust 값을 0.5로 설정


ggplot(data=TitanicSurvival, mapping = aes(x=passengerClass, y=..count.., fill=as.factor(survived))) + 
  geom_bar(position = "stack", width=0.8) + 
  geom_text(stat = "count", aes(label=..count..),position = position_stack(vjust=0.5)) + 
  scale_fill_brewer(palette = "Dark2") +
  labs(fill = "Divided by survived") + 
  theme(text = element_text(size = 10), legend.position = "top")


3.6.2 히스토그램


히스토그램은 연속형 변수를 일정 범위로 구간을 만들어 x축으로 설정, y축은 빈도(Counting)를 나타내는 그래프입니다.


# 구간 수정 및 색 입히기
ggplot(TitanicSurvival,aes(x=age)) +
  geom_histogram(binwidth = 5,col='red',fill='royalblue') 
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_bin()`).

# col은 테두리 색을, fill은 채워지는 색을 바꿔줍니다.


3.6.3 밀도 그래프 (Density Plot)


연속형 변수를 집계 내는 그래프: 밀도그래프는 연속형 변수를 일정 범위로 구간을 만들어, x축으로 설정하고 y축은 밀도(density)를 나타내는 그래프입니다.


ggplot(TitanicSurvival,aes(x=age)) + geom_density() # 기본
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_density()`).

ggplot(TitanicSurvival,aes(x=age))+
  geom_density(col='red',fill='royalblue') # col은 테두리, fill은 채우기 
## Warning: Removed 263 rows containing non-finite outside the scale range
## (`stat_density()`).


3.6.4 박스 플롯(Boxplot)


Box and Whisker(상자 수염)는 이산형 변수에 따라 연속형 변수의 분포 차이를 표현해주는 그래프로 데이터 탐색과정(EDA) 에서 매우 중요하게 쓰입니다.


mtcars$cyl<-as.factor(mtcars$cyl)
ggplot(mtcars,aes(x=cyl, y=mpg, group=cyl)) +
  geom_boxplot(aes(fill = cyl))  + 
  xlab("엔진형태") + 
  ylab("연비") + 
  ggtitle("Boxplot") + 
  labs(fill = "기통")


3.6.4.1 박스 플롯(Boxplot) – 아웃라이어 표시


# 투명도 조절 , 아웃라이어 표시
ggplot(mtcars,aes(x=cyl, y=mpg, group=cyl)) +
  geom_boxplot(aes(fill = cyl),alpha = I(0.4),outlier.colour = 'red') +
  xlab("엔진형태") + 
  ylab("연비") + 
  ggtitle("Boxplot") + 
  labs(fill = "기통")


3.6.5 산점도(Scatter Plot)


두 연속형 변수의 상관관계를 표현해주는 2차원 그래프, 모델링 전에 변수들 간의 관계를 파악하는데 있어 효과적입니다.


# scatter plot
h <- ggplot(mtcars,aes(x=qsec,y=mpg))+
  geom_point()
h


3.6.5.1 산점도(Scatter Plot); 점 색상 변경


# Change color of points
library(gridExtra)
h1 <- h + geom_point(color="red")  #모든 point를 red로
h2 <- h+ geom_point(aes(color=wt)) #mtc 데이터에서 wt는 continuous variable
h3 <- h + geom_point(aes(color=factor(am))) #am은 1 또는 0로 factor로 설정. continuous variable 아님.
grid.arrange(h1,h2,h3,nrow=3,ncol=1)


3.6.5.2 산점도(Scatter Plot); 기본 색상 변경


# Change default colors in color scale
h + geom_point(aes(color=factor(am))) + scale_color_manual(values = c("orange", "purple"))


3.6.5.3 산점도(Scatter Plot); 기본 점 모양 변경


# 색과 마찬가지로 기본으로 설정된 모양 역시 바꿀 수 있다
h + geom_point(aes(shape = factor(am))) + scale_shape_manual(values=c(0,2))


3.6.5.4 산점도(Scatter Plot); 점 모양, 크기 변경


# change points

h11 <- h + geom_point(size=5)
h12 <- h + geom_point(aes(size=wt))
h13 <- h + geom_point(aes(shape=factor(am)))
grid.arrange(h11, h12, h13, ncol=1)


3.6.5.5 산점도(Scatter Plot); 선 추가


# Add lines to scatterplot
h21 <- h + geom_point(color="blue") + geom_line()    #각 point를 선으로 연결
h22 <- h + geom_point(color="red") + geom_smooth(method="lm",se=TRUE)    #regression line을 추가(s.e.도 보여줌)
h23 <- h + geom_point() + geom_vline(xintercept=18,color="red")    #vertical line 추가

grid.arrange(h21,h22,h23,ncol=1)
## `geom_smooth()` using formula = 'y ~ x'


3.6.5.6 산점도(Scatter Plot); 선 굵기, 타입 변경


# line plot을 그릴수도 있으며 line의 크기와 색 또한 바꿀 수 있다.
h24 <- h + geom_point() + geom_line(size=0.9,aes(color=factor(vs)))
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
h25 <- h + geom_point() + geom_line(size=1.5,aes(color=factor(vs)),linetype="dotted")+ scale_color_manual(values = c("orange", "purple"))
 
grid.arrange(h24,h25,ncol=1)


3.6.5.7 산점도(Scatter Plot); 축 레이블 변경


# Change axis labels
h26 <- h1 + labs(x="1/4마일 도달 시간",y="Miles per Gallon")    #x,y축 label 추가
h27 <- h1 + 
  theme(axis.title.x=element_text(face="bold",size=20)) + #x축 label의 특성 추가
  labs(x="1/4마일 도달 시간",y="Miles per Gallon")    
h28 <- h1 + 
  scale_x_continuous("1/4마일 도달 시간",limits=c(10,25),breaks=seq(10,25,5))  
#x축 label과 x축의 범위를 바꿈

grid.arrange(h26,h27,h28,ncol=1)


3.6.5.8 선택 가능 점, 선 형태


선택 가능한 점 표현

Figure 3.1: 선택 가능한 점 표현


선택 가능한 선 표현

Figure 3.2: 선택 가능한 선 표현


3.7 그래픽스 조정 및 커스터마이징 방법


# 기본 산점도 생성
p <- ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point()
print(p)

# 축 및 제목 설정
# labs(): 그래프의 제목과 축 레이블을 설정합니다.
p <- p + labs(title = "산점도 예제", x = "Displacement", y = "Highway Miles per Gallon")
print(p) 

# 색상 및 테마 설정
# color: 점의 색상을 class 변수에 따라 다르게 설정합니다.
# theme_minimal(): 미니멀한 테마를 적용합니다.
p <- p + geom_point(aes(color = class)) +
  theme_minimal()
print(p)

# 축 범위 조정
# xlim(), ylim(): x축과 y축의 범위를 설정합니다.
p <- p + xlim(1, 7) + ylim(10, 50)
print(p)

# 레이블 및 텍스트 추가
# geom_text(): 각 점에 레이블을 추가합니다.
p1 <- p + geom_text(aes(label = model), vjust = -1, size = 3)
print(p1)

# 테마 커스터마이징
# theme(): 그래프의 다양한 요소를 커스터마이징합니다.
# plot.title: 그래프 제목의 위치, 크기, 스타일을 설정합니다.
# axis.title.x, axis.title.y: x축과 y축 제목의 크기를 설정합니다.
# legend.position: 범례의 위치를 설정합니다.
p1 <- p1 + theme(
  plot.title = element_text(hjust = 0.5, size = 20, face = "bold"),
  axis.title.x = element_text(size = 15),
  axis.title.y = element_text(size = 15),
  legend.position = "bottom"
)
print(p1)

# 패싯(Faceting)
# 여러개의 미니차트로 보여줍니다. 
p <- p + facet_wrap(~ class)
print(p)

3.7.1 화면 분할


  • 여러 개의 그래프를 하나에 그리기(Combining Graphs)  
  • R에서는 여러 개의 그래프를 합쳐서 하나로 그리는 것은 par() 또는 layout() 함수를 사용합니다.


3.7.1.1 par()함수


  • mfrow=c(nrows,ncols)를 사용하여 nrows*ncols개의 plot으로 분할하는데 그림이 그려지는 순서는 열(row)에 의해 채워집니다.
  • mfcol=c(nrows,ncols)를 사용해도 비슷한데 이때는 행(column)을 기준으로 채워집니다.


3.7.1.2 화면 분할 (2×2)


  • 네개의 그래프를 2*2로 배열하기
  • 예를 들어 다음의 코드는 네개의 plot을 만들고 두열과 두행으로 배열합니다. 내장 데이타인 mtcars를 사용합니다.


opar <- par(no.readonly = TRUE)  #현재 상태를 opar에 저장
par(mfrow = c(2, 2))  # 화면을 2*2로 나눈다
plot(mtcars$wt, mtcars$mpg, main = "Scatterplot of wt vs. mpg")
plot(mtcars$wt, mtcars$disp, main = "Scatterplot of wt vs disp")
hist(mtcars$wt, main = "Histogram of wt")
boxplot(mtcars$wt, main = "Boxplot of wt")

par(opar) # 원상태 복귀


3.8 시각적 인사이트를 통한 데이터 이해 강화


3.8.1 막대 그래프(Bar chart) 활용 비교


바 차트는 데이터를 비교하는 인사이트를 도출하는 데 매우 유용한 도구입니다. 예를 들어, 특정 제품의 월별 판매량을 비교하거나, 여러 카테고리 간의 수익을 비교할 때 사용할 수 있습니다.


3.8.1.1 mtcars의 실린더 개수별 평균 연비 비교 시각화


아래 막대 그래프 시각화를 통해 실린더 개수가 증가하면 평균 연비가 감소한다는 것을 알 수 있다.


# ggplot2 패키지 로드
library(ggplot2)

# 실린더 수에 따른 평균 연비 계산
avg_mpg <- aggregate(mpg ~ cyl, data = mtcars, mean)

# 바 차트 생성
ggplot(avg_mpg, aes(x = factor(cyl), y = mpg)) +
  geom_bar(stat = "identity", fill = "lightblue") +
  geom_text(aes(label = sprintf("%.2f",avg_mpg$mpg)), vjust = -0.5, color = "black") +
  theme_minimal() +
  labs(title = "Average Miles Per Gallon by Number of Cylinders",
       x = "Number of Cylinders",
       y = "Average Miles Per Gallon (mpg)") +
  theme(axis.text.x = element_text(angle = 0, hjust = 1))


3.8.2 선 그래프(line chart) 활용 비교


라인 차트는 시간에 따른 데이터의 변화를 시각화하는 데 매우 유용합니다. 예를 들어, 특정 기간 동안의 주식 가격 변동이나 월별 기온 변화를 분석할 때 사용할 수 있습니다.


3.8.2.1 airquality data 활용 월별 온도 변화 시각화


아래 라인 차트를 통해 8월이 가장 평균 기온이 높고, 9월이 5월보다 덥다는 것을 알 수 있다.


# ggplot2 패키지 로드
library(ggplot2)

# 월별 평균 기온 계산
avg_temp <- aggregate(Temp ~ Month, data = airquality, mean)

# 라인 차트 생성
ggplot(avg_temp, aes(x = Month, y = Temp)) +
  geom_line(color = "blue") +
  geom_point(color = "red") +
  geom_text(aes(label = sprintf("%.2f",avg_temp$Temp)), vjust = -1, color = "black") +
  theme_minimal() +
  ylim(0, max(airquality$Temp)) +
  labs(title = "Average Monthly Temperature",
       x = "Month",
       y = "Temperature (F)") +
  scale_x_continuous(breaks = 1:12, labels = month.abb)


3.8.3 산점도 (scatter plot) 활용 상관관계 파악


산점도는 두 변수 간의 관계를 시각화하는 데 매우 유용합니다. 예를 들어, 자동차의 마력과 연비 간의 관계를 분석할 때 사용할 수 있습니다.


3.8.3.1 mtcars data 활용 마력과 연비 상관관계 시각화


아래 산포도를 보면 마력과 연비는 반비례 관계라는 것을 알 수 있다.


# ggplot2 패키지 로드
library(ggplot2)

# 산점도 생성
ggplot(mtcars, aes(x = hp, y = mpg)) +
  geom_point(color = "blue") +
  theme_minimal() +
  labs(title = "Scatter Plot of Horsepower vs. Miles Per Gallon",
       x = "Horsepower (hp)",
       y = "Miles Per Gallon (mpg)")


4 R에서의 데이터 탐색


4.1 탐색적 데이터 분석(EDA) 기법 소개


  • 탐색적 데이터 분석(EDA)은 데이터 과학자가 데이터 세트를 분석 및 조사하고 주요 특성을 요약하는 데 사용하며, 종종 데이터 시각화 방법을 사용합니다.
  • EDA는 필요한 답변을 얻기 위해 데이터 소스를 가장 잘 조작하는 방법을 결정하는 데 도움이 되므로 데이터 과학자가 더 쉽게 패턴을 발견하고, 이상 징후를 발견하고, 가설을 테스트하고, 가정을 확인할 수 있습니다.


4.1.1 탐색적 데이터 분석의 유형


  • 일변량 비그래픽: 이는 분석되는 데이터가 단 하나의 변수로 구성되는 가장 간단한 형태의 데이터 분석입니다. 단일 변수이기 때문에 원인이나 관계를 다루지 않습니다. 단변량 분석의 주요 목적은 데이터를 설명하고 그 안에 존재하는 패턴을 찾는 것입니다.
  • 일변량 그래픽: 비그래픽 방법은 데이터에 대한 전체 그림을 제공하지 못합니다. 따라서 그래픽 방식이 필요합니다. 일변량 그래픽의 일반적인 유형은 다음과 같습니다.
    • 모든 데이터 값과 분포의 모양을 보여주는 줄기 및 잎 그림
    • 각 막대가 값 범위에 대한 케이스의 빈도(개수) 또는 비율(개수/총 개수)을 나타내는 막대 그래프인 히스토그램.
    • 상자 그림이 최소값, 제1사분위수, 중앙값, 제3사분위수, 최대값의 다섯 가지 숫자 요약을 그래픽으로 보여 줍니다.
  • 다변량 비그래픽: 다변량 데이터는 둘 이상의 변수에서 발생합니다. 다변량 비그래픽 EDA 기법은 일반적으로 교차표 또는 통계를 통해 데이터의 두 개 이상의 변수 간의 관계를 보여줍니다.
  • 다변량 그래픽: 다변량 데이터는 그래픽을 사용하여 둘 이상의 데이터 집합 간의 관계를 표시합니다.
    • 가장 많이 사용되는 그래픽은 그룹화된 막대 그림 또는 막대 차트로, 각 그룹은 변수 중 하나의 한 수준을 나타내고 그룹 내의 각 막대는 다른 변수의 수준을 나타냅니다.
    • 산점도는 한 변수가 다른 변수의 영향을 얼마나 많이 받는지 보여주기 위해 가로 및 세로 축에 데이터 포인트를 표시하는 데 사용됩니다.
    • 런 차트는 시간 경과에 따른 데이터의 선 그래프입니다.
    • 버블 차트는 2차원 그림에 여러 원(버블)을 표시하는 데이터 시각화입니다.
    • 히트 맵은 값이 색상으로 표시되는 데이터를 그래픽으로 표현한 것입니다.


4.2 결측치 및 이상치 처리 기법


4.2.1 결측치 처리


  • 결측치가 있는 record(행)는 데이터 수가 충분하다면 제거하고 분석하는게 가장 합리적이라고 생각합니다.
  • 하지만 데이터 수가 많지 않다면 해당 값을 평균값, 중앙값 등으로 대체하여 분석에 영향을 미치지 않도록 합니다.


head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
# 각 열의 평균 계산 (결측치를 제외한 값들로)
mean_values <- colMeans(airquality, na.rm = TRUE)

# 결측치를 각 열의 평균으로 대체
airquality_filled <- airquality
for (i in 1:ncol(airquality)) {
  airquality_filled[is.na(airquality_filled[, i]), i] <- mean_values[i]
}

head(airquality_filled)
##      Ozone  Solar.R Wind Temp Month Day
## 1 41.00000 190.0000  7.4   67     5   1
## 2 36.00000 118.0000  8.0   72     5   2
## 3 12.00000 149.0000 12.6   74     5   3
## 4 18.00000 313.0000 11.5   62     5   4
## 5 42.12931 185.9315 14.3   56     5   5
## 6 28.00000 185.9315 14.9   66     5   6


4.2.2 이상치 처리


  • 윈저화 (Winsorizing): 윈저화는 이상치를 특정 임계값으로 대체하는 방법입니다. 예를 들어, 상위 5%와 하위 5%의 값을 각각 95번째 백분위수와 5번째 백분위수 값으로 대체합니다.
  • 트리밍 (Trimming): 트리밍은 이상치를 제거하는 방법입니다. 예를 들어, 상위 5%와 하위 5%의 데이터를 제거합니다.
  • 변환 (Transformation): 데이터를 변환하여 이상치의 영향을 줄이는 방법입니다. 예를 들어, 로그 변환을 사용할 수 있습니다.


## 윈저화 

mtcars
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
mtcars_winsor <- mtcars

# 상위 5%와 하위 5% 임계값 계산
lower_bound <- quantile(mtcars$mpg, 0.05)
upper_bound <- quantile(mtcars$mpg, 0.95)

lower_bound
##     5% 
## 11.995
upper_bound
##  95% 
## 31.3
# 윈저화 적용
mtcars_winsor$mpg <- ifelse(mtcars_winsor$mpg < lower_bound, lower_bound, mtcars_winsor$mpg)
mtcars_winsor$mpg <- ifelse(mtcars_winsor$mpg > upper_bound, upper_bound, mtcars_winsor$mpg)

mtcars_winsor
##                        mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.000   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.000   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.800   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.400   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.700   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.100   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.300   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.400   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.800   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.200   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.800   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.400   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.300   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.200   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  11.995   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 11.995   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.700   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            31.300   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.400   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      31.300   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.500   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.500   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.200   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.300   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.200   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.300   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.000   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.400   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.800   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.700   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.000   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.400   4 121.0 109 4.11 2.780 18.60  1  1    4    2
# 트리밍 적용
mtcars_trimmed <- mtcars[mtcars$mpg >= lower_bound & mtcars$mpg <= upper_bound, ]

mtcars_trimmed
##                    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360        14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D         24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230          22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280          19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C         17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE        16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL        17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC       15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Chrysler Imperial 14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Honda Civic       30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corona     21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger  15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin       15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28        13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird  19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9         27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2     26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa      30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L    15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino      19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora     15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E        21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
# 로그 변환 적용
mtcars$log_mpg <- log(mtcars$mpg)

mtcars
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
##                      log_mpg
## Mazda RX4           3.044522
## Mazda RX4 Wag       3.044522
## Datsun 710          3.126761
## Hornet 4 Drive      3.063391
## Hornet Sportabout   2.928524
## Valiant             2.895912
## Duster 360          2.660260
## Merc 240D           3.194583
## Merc 230            3.126761
## Merc 280            2.954910
## Merc 280C           2.879198
## Merc 450SE          2.797281
## Merc 450SL          2.850707
## Merc 450SLC         2.721295
## Cadillac Fleetwood  2.341806
## Lincoln Continental 2.341806
## Chrysler Imperial   2.687847
## Fiat 128            3.478158
## Honda Civic         3.414443
## Toyota Corolla      3.523415
## Toyota Corona       3.068053
## Dodge Challenger    2.740840
## AMC Javelin         2.721295
## Camaro Z28          2.587764
## Pontiac Firebird    2.954910
## Fiat X1-9           3.306887
## Porsche 914-2       3.258097
## Lotus Europa        3.414443
## Ford Pantera L      2.760010
## Ferrari Dino        2.980619
## Maserati Bora       2.708050
## Volvo 142E          3.063391


4.3 복잡한 쿼리 작성과 데이터 집계


4.3.1 피벗 해제(unpivot)


tidyr 패키지의 pivot_longer()를 이용하여 피벗해제를 할 수 있다.


# 필요 패키지 활성화
library(dplyr)
library(tidyr)

# 예시 데이터셋 생성
relig_income <- data.frame(
  religion = c("Agnostic", "Atheist", "Buddhist", "Catholic"),
  `<$10k` = c(27, 12, 27, 418),
  `$10-20k` = c(34, 27, 21, 617),
  `$20-30k` = c(60, 37, 30, 732)
)

print("원본 데이터프레임:")
## [1] "원본 데이터프레임:"
print(relig_income)
##   religion X..10k X.10.20k X.20.30k
## 1 Agnostic     27       34       60
## 2  Atheist     12       27       37
## 3 Buddhist     27       21       30
## 4 Catholic    418      617      732
# 피벗해제 수행
relig_income_long <- relig_income %>%
  pivot_longer(
    cols = -religion,
    names_to = "income",
    values_to = "count"
  )

print("피벗해제 후 데이터프레임:")
## [1] "피벗해제 후 데이터프레임:"
print(relig_income_long)
## # A tibble: 12 × 3
##    religion income   count
##    <chr>    <chr>    <dbl>
##  1 Agnostic X..10k      27
##  2 Agnostic X.10.20k    34
##  3 Agnostic X.20.30k    60
##  4 Atheist  X..10k      12
##  5 Atheist  X.10.20k    27
##  6 Atheist  X.20.30k    37
##  7 Buddhist X..10k      27
##  8 Buddhist X.10.20k    21
##  9 Buddhist X.20.30k    30
## 10 Catholic X..10k     418
## 11 Catholic X.10.20k   617
## 12 Catholic X.20.30k   732


4.3.2 데이터 필터링


특정 조건에 맞는 데이터를 필터링합니다. 예를 들어, 연비(mpg)가 20 이상인 자동차만 선택합니다.


# 필요 패키지 활성화
library(dplyr)
library(tidyr)

# 필터링
filtered_data <- mtcars %>% filter(mpg >= 20)
print(filtered_data)
##                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb  log_mpg
## Mazda RX4      21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4 3.044522
## Mazda RX4 Wag  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4 3.044522
## Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1 3.126761
## Hornet 4 Drive 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1 3.063391
## Merc 240D      24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2 3.194583
## Merc 230       22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2 3.126761
## Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1 3.478158
## Honda Civic    30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2 3.414443
## Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1 3.523415
## Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1 3.068053
## Fiat X1-9      27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1 3.306887
## Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2 3.258097
## Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2 3.414443
## Volvo 142E     21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 3.063391


4.3.3 데이터 정렬


데이터를 특정 열을 기준으로 정렬합니다. 예를 들어, 연비(mpg)를 기준으로 내림차순 정렬합니다.


# 필요 패키지 활성화
library(dplyr)
library(tidyr)

# 정렬 
sorted_data <- mtcars %>% arrange(desc(mpg))
print(sorted_data)
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
##                      log_mpg
## Toyota Corolla      3.523415
## Fiat 128            3.478158
## Honda Civic         3.414443
## Lotus Europa        3.414443
## Fiat X1-9           3.306887
## Porsche 914-2       3.258097
## Merc 240D           3.194583
## Datsun 710          3.126761
## Merc 230            3.126761
## Toyota Corona       3.068053
## Hornet 4 Drive      3.063391
## Volvo 142E          3.063391
## Mazda RX4           3.044522
## Mazda RX4 Wag       3.044522
## Ferrari Dino        2.980619
## Merc 280            2.954910
## Pontiac Firebird    2.954910
## Hornet Sportabout   2.928524
## Valiant             2.895912
## Merc 280C           2.879198
## Merc 450SL          2.850707
## Merc 450SE          2.797281
## Ford Pantera L      2.760010
## Dodge Challenger    2.740840
## Merc 450SLC         2.721295
## AMC Javelin         2.721295
## Maserati Bora       2.708050
## Chrysler Imperial   2.687847
## Duster 360          2.660260
## Camaro Z28          2.587764
## Cadillac Fleetwood  2.341806
## Lincoln Continental 2.341806


4.3.4 새로운 열 추가


기존 데이터를 바탕으로 새로운 열을 추가합니다. 예를 들어, 무게(wt)를 kg 단위로 변환한 열을 추가합니다.


# 필요 패키지 활성화
library(dplyr)
library(tidyr)

# 새로운 열 추가  
mtcars <- mtcars %>% mutate(wt_kg = wt * 453.592)
print(head(mtcars))
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb  log_mpg
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 3.044522
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 3.044522
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 3.126761
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 3.063391
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 2.928524
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 2.895912
##                      wt_kg
## Mazda RX4         1188.411
## Mazda RX4 Wag     1304.077
## Datsun 710        1052.333
## Hornet 4 Drive    1458.298
## Hornet Sportabout 1560.356
## Valiant           1569.428


4.3.5 그룹화 및 요약


데이터를 그룹화하고 요약 통계를 계산합니다. 예를 들어, 실린더 수(cyl)별로 평균 연비(mpg)를 계산합니다.


# 필요 패키지 활성화
library(dplyr)
library(tidyr)

# 그룹화 및 요약 
grouped_data <- mtcars %>% group_by(cyl) %>% summarise(mean_mpg = mean(mpg))
print(grouped_data)
## # A tibble: 3 × 2
##   cyl   mean_mpg
##   <fct>    <dbl>
## 1 4         26.7
## 2 6         19.7
## 3 8         15.1


4.3.6 복잡한 쿼리 작성


여러 작업을 결합하여 복잡한 쿼리를 작성할 수 있습니다. 예를 들어, 실린더 수가 6인 자동차 중에서 연비가 20 이상인 자동차의 평균 마력을 계산합니다.


# 필요 패키지 활성화
library(dplyr)
library(tidyr)

# 실린더 수 6 이상, 연비 20 이상 자동차의 평균 마력 
complex_query <- mtcars %>%
  filter(cyl == 6, mpg >= 20) %>%
  summarise(mean_hp = mean(hp))
print(complex_query)
##   mean_hp
## 1     110


4.4 데이터의 패턴과 트렌드 분석


  • 패턴 분석: 데이터 내에서 반복되는 규칙이나 구조를 찾는 과정입니다.
  • 트렌드 분석: 시간에 따른 데이터의 변화를 분석하여 미래의 변화를 예측하는 과정입니다.


# 필요 패키지 활성화
# install.packages("tidyverse")
# install.packages("lubridate")
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats   1.0.0     ✔ readr     2.1.5
## ✔ lubridate 1.9.3     ✔ stringr   1.5.1
## ✔ purrr     1.0.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ ggplot2::%+%()       masks psych::%+%()
## ✖ ggplot2::alpha()     masks psych::alpha()
## ✖ gridExtra::combine() masks dplyr::combine()
## ✖ dplyr::filter()      masks stats::filter()
## ✖ dplyr::lag()         masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)

# 데이터 준비
data("airquality")
df <- airquality
print(head(df))
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
# 날짜 정보 생성
df <- df %>%
  mutate(Date = make_date(1973, Month, Day))

# 결측치 처리 (평균으로 대체)
df <- df %>%
  mutate(Ozone = ifelse(is.na(Ozone), mean(Ozone, na.rm = TRUE), Ozone),
         Solar.R = ifelse(is.na(Solar.R), mean(Solar.R, na.rm = TRUE), Solar.R))

print(head(df))
##      Ozone  Solar.R Wind Temp Month Day       Date
## 1 41.00000 190.0000  7.4   67     5   1 1973-05-01
## 2 36.00000 118.0000  8.0   72     5   2 1973-05-02
## 3 12.00000 149.0000 12.6   74     5   3 1973-05-03
## 4 18.00000 313.0000 11.5   62     5   4 1973-05-04
## 5 42.12931 185.9315 14.3   56     5   5 1973-05-05
## 6 28.00000 185.9315 14.9   66     5   6 1973-05-06
# Ozone 농도의 일별 변화
ggplot(df, aes(x = Date, y = Ozone)) +
  geom_line() +
  labs(title = "Time Series of Ozone Levels",
       x = "Date",
       y = "Ozone Level")

# 월별 평균 Ozone 농도 변화 
df %>%
  group_by(Month) %>%
  summarise(mean_ozone = mean(Ozone)) %>%
  ggplot(aes(x = Month, y = mean_ozone)) +
  geom_line() +
  geom_text(aes(label = sprintf("%.2f",mean_ozone)), vjust = -0.5, color = "black") +
  labs(title = "Monthly Average Ozone Levels",
       x = "Month",
       y = "Average Ozone Level") +
  ylim(0,max(airquality$Ozone)) 


5 기초 통계 분석


5.1 분석 가설 설정과 검정 절차


5.1.1 통계적 검정의 목적


주장하는 가설 입증


5.1.2 통계적 검정 프로세스


① 연구목적에 맞는 대립가설 설정
② 연구목적과 수집된 자료에 부합되는 적절한 통계적 검정 방법을 선택
③ 대립가설과 귀무가설 명시
④ 유의수준을 결정한 후 각 분포유형에 따라 역함수를 이용하여 임계치 구하고 기각역 설정
⑤ 통계적 검정유형에 필요한 통계량을 각 검정유형의 공식을 이용하여 계산
⑥ 임계치와 통계량을 비교하여 귀무가설 기각과 수용 결정
⑦ 검정 결과에 따라 대립가설 입증 여부 판단


5.1.3 상황별 통계적 분석 방법






5.1.4 모수 통계의 전제조건


아래 세 조건 중 하나라도 충족되지 않으면 비 모수 통계 사용

  • 표본의 모집단이 정규분포를 따른다
  • 집단내의 분산은 같다
  • 변수는 등간척도 또는 비율척도이다





5.1.4.1 정규성 검정(Normality Test)


많은 통계 분석 방법에서 자료가 정규분포를 따른다는 가정 하에 검정 통계량과 p-value를 계산합니다.
만약 실제 자료가 정규성 가정을 만족하지 않는다면 통계 분석 결과에 대한 타당성이 떨어지기 때문에 분석을 하기 전에 정규성 가정이 만족되는지 검토하는 것이 바람직합니다.

정규성 가정(Tests for Normality)을 검토하는 방법으로는 다음 세 가지가 있습니다.

  • Q-Q plot
  • 샤피로-윌크 검정 (Shapiro-Wilk test)
  • 콜모고로프-스미노프 검정 (Kolmogorov-Smirnov test)


5.1.4.1.1 Q-Q plot



그래프를 그려서 정규성 가정이 만족되는지 시각적으로 확인하는 방법입니다.
Q-Q plot은 아래와 같이 대각선 참조선을 따라서 값들이 분포하게 되면 정규성을 만족한다고 할 수 있습니다. 만약 한 쪽으로 치우치거나 직선과 차이가 많이 나는 모습이라면 정규성 가정에 위배되었다고 볼 수 있습니다.

R 내장 데이터인 Nile 데이터로 Q-Q plot을 그려본 결과 정규성을 다소 벗어나 보입니다.

qqnorm(Nile) # normal Q-Q plot
qqline(Nile,col=2) # Normal line



5.1.4.1.2 샤피로-윌크 검정 (Shapiro-Wilk test)



오차항이 정규분포를 따르는지 알아보는 검정으로, 회귀분석에서 모든 독립변수에 대해서 종속변수가 정규분포를 따르는지 알아보는 방법입니다.
귀무가설은 ’H0:정규분포를 따른다’는 것으로 p-value가 0.05보다 크면 정규성을 가정할 수 있습니다.

Nile 데이터의 결과는 p값이 0.05보다 작으므로 Nile 데이터는 정규분포를 따르지 않는다고 판단됩니다.

shapiro.test(Nile)
## 
##  Shapiro-Wilk normality test
## 
## data:  Nile
## W = 0.97343, p-value = 0.04072



5.1.4.1.3 콜모고로프-스미노프 검정 (Kolmogorov-Smirnov test)



EDF, 즉 Empirical distribution function에 기반한 적합도 검정 방법입니다.
자료의 평균/표준편차와 히스토그램을 표준정규분포와 비교하여 적합도를 검정합니다.
Shapiro-Wilk test와 마찬가지로 p-value가 0.05보다 크면 정규성을 가정하게 된다.

Nile 결과를 보면 p값이 0.05보다 작으므로 정규분포를 따르지 않는다.

library(nortest)
lillie.test(Nile)
## 
##  Lilliefors (Kolmogorov-Smirnov) normality test
## 
## data:  Nile
## D = 0.095957, p-value = 0.02399



5.1.4.2 두 집단간 등분산 검정: F-검정


F 검정은 두 실험군의 데이터 모집단 분산이 동일한지 여부를 검정하는 방법입니다.
두 실험군의 모집단은 정규 분포를 따라야 합니다.

  • H1 : 이분산
  • H0 : 등분산

p값 > 0.05이면 등분산으로 판단합니다.


학생들의 영어, 수학 점수 데이터인 ’em_score.xlsx’를 불러다가 정규성 검사와 등분산 검사를 수행하겠습니다.
shpiro test 결과를 보면 두 점수 데이터 모두 정규성을 따르고 있습니다.
F test 결과 p값이 0.05보다 작으므로 이분산이라고 보면 될 것 같습니다.


library(readxl)
em_score <- read_excel("em_score.xlsx", sheet = "Sheet2")
str(em_score)
## tibble [40 × 4] (S3: tbl_df/tbl/data.frame)
##  $ no     : num [1:40] 1 2 3 4 5 6 7 8 9 10 ...
##  $ math   : num [1:40] 67 75 74 76 90 72 62 77 59 64 ...
##  $ english: num [1:40] 77 84 77 83 78 90 75 86 76 80 ...
##  $ gender : num [1:40] 1 0 1 1 0 0 0 1 1 0 ...
shapiro.test(em_score$math)
## 
##  Shapiro-Wilk normality test
## 
## data:  em_score$math
## W = 0.98866, p-value = 0.9543
shapiro.test(em_score$english)
## 
##  Shapiro-Wilk normality test
## 
## data:  em_score$english
## W = 0.97934, p-value = 0.6649
var.test(em_score$math,em_score$english)
## 
##  F test to compare two variances
## 
## data:  em_score$math and em_score$english
## F = 3.476, num df = 39, denom df = 39, p-value = 0.0001761
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  1.838479 6.572228
## sample estimates:
## ratio of variances 
##           3.476047


5.2 p-값 해석 및 통계적 유의성 평가


5.2.1 유의수준 𝛼 , 임계치, 기각역




5.2.2 검정통계량, 임계치, 𝑝 값, 유의수준 𝛼




5.3 t-검정, 카이제곱 검정 등 기초 통계적 검정


5.3.1 상황별 두 표본 검정 선택




5.3.2 두표본 z-검정


\(𝑁(𝜇_1, 𝜎_1^2 ), 𝑁(𝜇_2, 𝜎_2^2 )\) 정규분포를 따르는 모집단에서 2개의 표본을 추출했을 때, ’\(𝜇_1\)\(𝜇_2\)와 같지않다/크다/작다’에 관한 모평균의 검정 \(𝐻_1:𝜇_1>𝜇_2\) or \(𝜇_1<𝜇_2\) or \(𝜇_1≠𝜇_2\)
\(𝐻_0:𝜇_1=𝜇_2\)

예시: 대한민국 50~54세 남자 50명, 19~24세 50명을 무작위로 표본추출했을 때 신뢰도 95%에서 50~54세 키의 평균이 19~24세 키의 평균 보다 작다고 할 수 있는지 판단하세요. (2017년 기준 50~54세 키 평균 170.2cm, 표준편차 5.78cm, 19~24세 키 평균 174.3cm, 표준편차 5.68cm)

library(BSDA)
## 필요한 패키지를 로딩중입니다: lattice
## 
## 다음의 패키지를 부착합니다: 'BSDA'
## The following objects are masked from 'package:carData':
## 
##     Vocab, Wool
## The following object is masked from 'package:datasets':
## 
##     Orange
library(lattice)

set.seed(55)
x <- rnorm(n=50, mean=170.2, sd=5.78)
y <- rnorm(n=50, mean=174.3, sd=5.68)

z.test(x,y,alternative="less",sigma.x=5.78,sigma.y=5.68,conf.level=.95)
## 
##  Two-sample z-Test
## 
## data:  x and y
## z = -2.7694, p-value = 0.002808
## alternative hypothesis: true difference in means is less than 0
## 95 percent confidence interval:
##         NA -1.288731
## sample estimates:
## mean of x mean of y 
##  170.4882  173.6620


p값이 0.05보다 작으므로 50~54세 키가 19~24세 키 보다 작다고 할 수 있습니다.

5.3.3 등분산 두 표본 t-검정


정규분포를 따르고 분산이 같은 두 집단에서 2개의 표본을 추출했을 때, ’\(𝜇_1\)\(𝜇_2\)와 같지않다/크다/작다’에 관한 모평균의 검정 (정규성, 등분산)

\(𝐻_1:𝜇_1>𝜇_2\) or \(𝜇_1<𝜇_2\) or \(𝜇_1≠𝜇_2\)
\(𝐻_0:𝜇_1=𝜇_2\)

예시: mtcars 데이터에서 기어의 형태(자동,수동)에 따른 연비를 찾고 자동 기어의 평균 연비가 수동 기어의 평균 연비에 비해 신뢰도 95%에서 낮은지 판단하세요.

str(mtcars)
## 'data.frame':    32 obs. of  13 variables:
##  $ mpg    : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl    : Factor w/ 3 levels "4","6","8": 2 2 1 2 3 2 3 1 1 2 ...
##  $ disp   : num  160 160 108 258 360 ...
##  $ hp     : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat   : num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt     : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec   : num  16.5 17 18.6 19.4 17 ...
##  $ vs     : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am     : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear   : num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb   : num  4 4 1 1 2 1 4 2 2 4 ...
##  $ log_mpg: num  3.04 3.04 3.13 3.06 2.93 ...
##  $ wt_kg  : num  1188 1304 1052 1458 1560 ...
summary(mtcars$mpg)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   10.40   15.43   19.20   20.09   22.80   33.90
x <- mtcars[mtcars$am==1,1]  # 수동
y <- mtcars[mtcars$am==0,1]  # 자동

length(x); length(y)
## [1] 13
## [1] 19
# 정규성 검정
shapiro.test(x); shapiro.test(y)
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.9458, p-value = 0.5363
## 
##  Shapiro-Wilk normality test
## 
## data:  y
## W = 0.97677, p-value = 0.8987
# 등분산 검정
var.test(x,y)
## 
##  F test to compare two variances
## 
## data:  x and y
## F = 2.5869, num df = 12, denom df = 18, p-value = 0.06691
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  0.934280 8.040391
## sample estimates:
## ratio of variances 
##           2.586911
# t-test
t.test(y,x, paired = FALSE, alternative="less", var.equal = TRUE, conf.level = 0.95)
## 
##  Two Sample t-test
## 
## data:  y and x
## t = -4.1061, df = 30, p-value = 0.0001425
## alternative hypothesis: true difference in means is less than 0
## 95 percent confidence interval:
##       -Inf -4.250255
## sample estimates:
## mean of x mean of y 
##  17.14737  24.39231


t-test p값이 0.05보다 작으므로 낮다고 할 수 있습니다.

5.3.4 이분산 두 표본 t-검정(Welch t-test)


정규분포를 따르고 분산이 같지 않은 두 집단에서 2개의 표본을 추출했을 때,
, ’\(𝜇_1\)\(𝜇_2\)와 같지않다/크다/작다’에 관한 모평균의 검정 (정규성, 이분산)

\(𝐻_1:𝜇_1>𝜇_2\) or \(𝜇_1<𝜇_2\) or \(𝜇_1≠𝜇_2\)
\(𝐻_0:𝜇_1=𝜇_2\)

예시: mtcars 데이터에서 엔진의 형태(V-shaped,straight)에 따른 마력을 찾고 V-shaped 엔진의 평균 마력이 straight 엔진의 평균 마력에 비해 신뢰도 95%에서 높은지 판단하세요.

x1 <- mtcars[mtcars$vs==1,4] # straight  
y1 <- mtcars[mtcars$vs==0,4] # V-shaped

shapiro.test(x1); shapiro.test(y1) # 정규성 검정
## 
##  Shapiro-Wilk normality test
## 
## data:  x1
## W = 0.89932, p-value = 0.1102
## 
##  Shapiro-Wilk normality test
## 
## data:  y1
## W = 0.9578, p-value = 0.5598
var.test(x1,y1) # 등분산 검정
## 
##  F test to compare two variances
## 
## data:  x1 and y1
## F = 0.16417, num df = 13, denom df = 17, p-value = 0.002002
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
##  0.0589191 0.4931365
## sample estimates:
## ratio of variances 
##          0.1641657
# t-test
t.test(y1, x1, paired = F, alternative="greater", var.equal = F, conf.level = 0.95)
## 
##  Welch Two Sample t-test
## 
## data:  y1 and x1
## t = 6.2908, df = 23.561, p-value = 9.099e-07
## alternative hypothesis: true difference in means is greater than 0
## 95 percent confidence interval:
##  71.5933     Inf
## sample estimates:
## mean of x mean of y 
## 189.72222  91.35714


t-test p값이 0.05보다 작으므로 높다고 할 수 있습니다.

5.3.5 두 표본 Wilcoxon Rank sum test


데이터가 정규성을 충족하지 않거나 서열형 데이터일 때 두 집단의 평균 ’\(𝜇_1\)\(𝜇_2\)와 같지않다/크다/작다’에 관한 모평균의 검정 (정규성, 이분산)

\(𝐻_1:𝜇_1>𝜇_2\) or \(𝜇_1<𝜇_2\) or \(𝜇_1≠𝜇_2\)
\(𝐻_0:𝜇_1=𝜇_2\)

예시: Cars93 데이터에서 생산지(미국산,비미국산)에 따른 가격 데이터를 근거로 생산지에 따른 가격 차이가 있는지 신뢰도 95%에서 판단하세요.


library(MASS)
## 
## 다음의 패키지를 부착합니다: 'MASS'
## The following object is masked from 'package:dplyr':
## 
##     select
# Cars93
a <- subset(Cars93$Price,Cars93$Origin=="USA")
b <- subset(Cars93$Price,Cars93$Origin=="non-USA")

shapiro.test(a)
## 
##  Shapiro-Wilk normality test
## 
## data:  a
## W = 0.88411, p-value = 0.0002006
shapiro.test(b)
## 
##  Shapiro-Wilk normality test
## 
## data:  b
## W = 0.87756, p-value = 0.0002036
summary(b)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    8.00   11.60   19.10   20.51   26.70   61.90
summary(a)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##    7.40   13.47   16.30   18.57   20.73   40.10
wilcox.test(a,b,exact = F, alternative = c("two.sided"), conf.int = T, conf.level = 0.95)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  a and b
## W = 1024.5, p-value = 0.6724
## alternative hypothesis: true location shift is not equal to 0
## 95 percent confidence interval:
##  -4.399986  2.599967
## sample estimates:
## difference in location 
##             -0.7000468


p값이 0.05보다 크므로 차이가 없다고 판단됩니다.

5.3.6 두 표본 Wilcoxon Rank sum test (서열 척도)



예시: 광고안 5개를 보여주고 순위를 매기는 조사를 시행했습니다. 이 때 광고A가 광고B 보다 95% 신뢰수준에서 좋은 순위를 받았다고 주장할 수 있는지 판단하세요.

library(readxl)
rank <- read_excel("rank.xlsx", sheet = "two")

shapiro.test(rank$A); shapiro.test(rank$B) # 정규성
## 
##  Shapiro-Wilk normality test
## 
## data:  rank$A
## W = 0.67936, p-value = 2.207e-05
## 
##  Shapiro-Wilk normality test
## 
## data:  rank$B
## W = 0.74089, p-value = 0.0001284
wilcox.test(rank$A, rank$B, alternative = "less", conf.int=T, conf.level=0.95,exact = F)
## 
##  Wilcoxon rank sum test with continuity correction
## 
## data:  rank$A and rank$B
## W = 130, p-value = 0.02041
## alternative hypothesis: true location shift is less than 0
## 95 percent confidence interval:
##           -Inf -9.477129e-07
## sample estimates:
## difference in location 
##             -0.9999886


p값이 0.05보다 작으므로 광고A가 좋은 평가를 받았다고 판단됩니다.

5.3.7 chi-square test for large samples (명목 척도)


자료가 명목 척도(nominal)인 경우, 각 셀 별 빈도가 모두 5 이상인 경우 두 집단의 분포가 같은지, 다른지를 검정해야 하는 경우 카이스퀘어 검정으로 판단할 수 있다.
\(𝐻_1\): 분포가 같지 않다
\(𝐻_0\): 분포가 같다


예시: Titanic data를 근거로 남녀 간 생존율의 차이가 있는지 확인하세요.

library(carData)
str(TitanicSurvival)
## 'data.frame':    1309 obs. of  4 variables:
##  $ survived      : Factor w/ 2 levels "no","yes": 2 2 1 1 1 2 2 1 2 1 ...
##  $ sex           : Factor w/ 2 levels "female","male": 1 2 1 2 1 2 1 2 1 2 ...
##  $ age           : num  29 0.917 2 30 25 ...
##  $ passengerClass: Factor w/ 3 levels "1st","2nd","3rd": 1 1 1 1 1 1 1 1 1 1 ...
table(TitanicSurvival$sex)
## 
## female   male 
##    466    843
table(TitanicSurvival$survived)
## 
##  no yes 
## 809 500
tab <- table(TitanicSurvival$sex,TitanicSurvival$survived)
chisq.test(tab)
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  tab
## X-squared = 363.62, df = 1, p-value < 2.2e-16


chisquare-test p값이 0.05보다 작으므로 남녀 생존률 차이가 있다고 판단됩니다.

5.3.8 Fisher’s test (명목 척도)


자료가 명목 척도(nominal)인 경우, 각 셀 별 빈도가 5 이하인 경우가 20%가 넘는 경우 두 집단의 분포가 같은지, 다른지를 검정해야 하는 경우 Fisher’s test 로 판단할 수 있다. Odds ration=1이면 두집단 분포 차이가 없다고 판단한다.

\(𝐻_1: 𝑂𝑑𝑑𝑠 𝑟𝑎𝑡𝑖𝑜 ≠1\)
\(𝐻_0: 𝑂𝑑𝑑𝑠 𝑟𝑎𝑡𝑖𝑜=1\)


예시: # 라면을 끓일 때 면 먼저 넣고 끓인 것과 스프 먼저 넣고 끓인 것의 맛 차이가 있다고 주장하는 사람이 있어 블라인드 테스트를 진행했습니다. 자기가 좋아하는 순서의 라면이 좋다고 한 경우를 Yes, 못 맞혔을 때 No일 때 구분 능력이 있는지 판단하세요.

library(readxl)
noodle_soup <- read_excel("noodle_soup.xlsx", sheet = "noodle_soup")

tab2 <- table(noodle_soup$fact,noodle_soup$guess_soup)

#Fisher's exact test
fisher.test(tab2, alternative = "two.sided")
## 
##  Fisher's Exact Test for Count Data
## 
## data:  tab2
## p-value = 0.04056
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##    0.9040436 953.3729037
## sample estimates:
## odds ratio 
##   13.95942


p값이 0.05보다 작으므로 구분능력이 없다고 판단됩니다.

5.3.9 쌍체비교 두 표본 t-검정(paired two sample t-test)


정규분포를 따르는 쌍체 비교에서, ’\(𝜇_1\)\(𝜇_2\)와 같지않다/크다/작다’에 관한 모평균의 검정

\(𝐻_1:𝜇_1>𝜇_2\) or \(𝜇_1<𝜇_2\) or \(𝜇_1≠𝜇_2\)
\(𝐻_0:𝜇_1=𝜇_2\)


예시: Membership 가입 전, 가입 후의 구매금액 데이터를 근거로 가입 후 구매금액이 가입 전 보다 높은지 95% 신뢰도에서 판단하세요.

library(readxl)
bf <- read_excel("before_after_sales.xlsx", sheet = "sales")
x <- bf$before
y <- bf$after
shapiro.test(x)
## 
##  Shapiro-Wilk normality test
## 
## data:  x
## W = 0.99236, p-value = 0.8466
shapiro.test(y)
## 
##  Shapiro-Wilk normality test
## 
## data:  y
## W = 0.99218, p-value = 0.8339
# t-test
t.test(x, y, paired = T, alternative="less", conf.level = 0.95)
## 
##  Paired t-test
## 
## data:  x and y
## t = -6.4554, df = 99, p-value = 2.014e-09
## alternative hypothesis: true mean difference is less than 0
## 95 percent confidence interval:
##       -Inf -6.734136
## sample estimates:
## mean difference 
##          -9.066


p값이 0.05보다 작으므로 가입후가 가입전 보다 구매금액이 크다고 판단됩니다.

5.3.10 쌍체비교 두 표본 Wilcoxon signed Rank test


쌍체 비교에서 정규성이 없는 경우\(𝜇_1\)\(𝜇_2\)와 같지않다/크다/작다’에 관한 모평균의 검정

\(𝐻_1:𝜇_1>𝜇_2\) or \(𝜇_1<𝜇_2\) or \(𝜇_1≠𝜇_2\)
\(𝐻_0:𝜇_1=𝜇_2\)


예시: # 신제품 A와 기존제품 B에 대한 선호도 36명의 타겟고객 대상으로 실시한 설문 데이터를 근거로 신제품 A가 기존제품 B 보다 선호도가 높다고 판단할 수 있는지 95% 신뢰도에서 판단하세요.

library(readxl)

p <- read_excel("newp_preference.xlsx", sheet = "Data")

shapiro.test(p$A)
## 
##  Shapiro-Wilk normality test
## 
## data:  p$A
## W = 0.87409, p-value = 0.0007187
shapiro.test(p$B)
## 
##  Shapiro-Wilk normality test
## 
## data:  p$B
## W = 0.90026, p-value = 0.003468
# wilcox signed rank test
wilcox.test(p$A, p$B, alternative = c("greater"), paired = TRUE, conf.level = 0.95, conf.int=T, exact=F)
## 
##  Wilcoxon signed rank test with continuity correction
## 
## data:  p$A and p$B
## V = 153, p-value = 0.9727
## alternative hypothesis: true location shift is greater than 0
## 95 percent confidence interval:
##  -1.000011       Inf
## sample estimates:
## (pseudo)median 
##      -0.999945


p값이 0.05보다 작으므로 신제품A의 선호도가 높다고 판단됩니다.

5.3.11 쌍체비교 명목 척도 검정(McNemar’s test)


명목 척도의 쌍체 비교에서, 비율 차이가 있는지 없는지에 대한 검정

\(𝐻_1:비율 차이가 있다\)
\(𝐻_0: 비율 차이가 없다\)


예시: 치료약 복용 전 후의 질병 유무를 100명의 자원자 대상 조사한 결과를 근거로 치료약의 효과가 있는지 95% 신뢰수준에서 판단하세요.

library(readxl)
dbf <- read_excel("before_after_comparision.xlsx", sheet = "bf_comp")
tab3 <- table(dbf$before,dbf$after); tab3
##          
##           absent present
##   absent      43      10
##   present     23      24
mcnemar.test(tab3)
## 
##  McNemar's Chi-squared test with continuity correction
## 
## data:  tab3
## McNemar's chi-squared = 4.3636, df = 1, p-value = 0.03671


p값이 0.05보다 작으므로 치료약의 효과가 있다고 판단됩니다.


6 회귀 분석 기초




6.1 선형 회귀 모델




6.2 회귀분석의 활용




6.3 회귀분석 활용 시 유의 사항




6.4 결정계수, 조정 결정계수




6.5 모델 예측의 실습과 검증: mtcars 연비 예측


# mtcars 데이터 로드
data(mtcars)

# 데이터 분할 (훈련 데이터: 70%, 테스트 데이터: 30%)
set.seed(123)  # 재현성을 위해 시드 설정
trainIndex <- sample(1:nrow(mtcars), 0.7 * nrow(mtcars))
trainData <- mtcars[trainIndex, ]
testData <- mtcars[-trainIndex, ]

# 스텝와이즈 회귀 분석
full_model <- lm(mpg ~ ., data = trainData)
step_model <- step(full_model, direction = "both")
## Start:  AIC=57.41
## mpg ~ cyl + disp + hp + drat + wt + qsec + vs + am + gear + carb
## 
##        Df Sum of Sq    RSS    AIC
## - drat  1     0.000 110.00 55.408
## - gear  1     0.183 110.18 55.444
## - vs    1     0.315 110.31 55.471
## - carb  1     2.477 112.48 55.898
## - cyl   1     2.980 112.98 55.996
## - hp    1     5.906 115.91 56.558
## - disp  1     7.265 117.27 56.815
## - am    1     8.874 118.88 57.115
## - qsec  1     8.892 118.89 57.118
## <none>              110.00 57.408
## - wt    1    31.836 141.84 61.000
## 
## Step:  AIC=55.41
## mpg ~ cyl + disp + hp + wt + qsec + vs + am + gear + carb
## 
##        Df Sum of Sq    RSS    AIC
## - gear  1     0.195 110.19 53.447
## - vs    1     0.337 110.34 53.475
## - carb  1     2.615 112.62 53.925
## - cyl   1     2.981 112.98 53.996
## - hp    1     6.463 116.46 54.664
## - disp  1     7.788 117.79 54.913
## - qsec  1     9.230 119.23 55.180
## - am    1    10.043 120.04 55.330
## <none>              110.00 55.408
## + drat  1     0.000 110.00 57.408
## - wt    1    33.477 143.48 59.253
## 
## Step:  AIC=53.45
## mpg ~ cyl + disp + hp + wt + qsec + vs + am + carb
## 
##        Df Sum of Sq    RSS    AIC
## - vs    1     0.406 110.60 51.528
## - carb  1     2.454 112.65 51.931
## - cyl   1     3.061 113.26 52.049
## - hp    1     7.178 117.37 52.835
## - disp  1     7.845 118.04 52.960
## - am    1     9.906 120.10 53.340
## - qsec  1    10.276 120.47 53.408
## <none>              110.19 53.447
## + gear  1     0.195 110.00 55.408
## + drat  1     0.012 110.18 55.444
## - wt    1    33.713 143.91 57.319
## 
## Step:  AIC=51.53
## mpg ~ cyl + disp + hp + wt + qsec + am + carb
## 
##        Df Sum of Sq    RSS    AIC
## - carb  1     2.389 112.99 49.998
## - cyl   1     3.787 114.39 50.268
## - hp    1     6.846 117.45 50.849
## - disp  1     7.442 118.04 50.960
## - am    1     9.599 120.20 51.359
## <none>              110.60 51.528
## - qsec  1    12.734 123.33 51.925
## + vs    1     0.406 110.19 53.447
## + gear  1     0.263 110.34 53.475
## + drat  1     0.000 110.60 53.527
## - wt    1    33.607 144.21 55.365
## 
## Step:  AIC=50
## mpg ~ cyl + disp + hp + wt + qsec + am
## 
##        Df Sum of Sq    RSS    AIC
## - cyl   1     4.112 117.10 48.784
## - hp    1     4.971 117.96 48.945
## - disp  1     5.670 118.66 49.075
## - am    1     8.060 121.05 49.514
## - qsec  1    10.359 123.35 49.927
## <none>              112.99 49.998
## + carb  1     2.389 110.60 51.528
## + vs    1     0.340 112.65 51.931
## + drat  1     0.262 112.73 51.946
## + gear  1     0.012 112.98 51.995
## - wt    1    40.704 153.69 54.766
## 
## Step:  AIC=48.78
## mpg ~ disp + hp + wt + qsec + am
## 
##        Df Sum of Sq    RSS    AIC
## - disp  1     2.477 119.58 47.244
## - hp    1    11.027 128.13 48.764
## <none>              117.10 48.784
## + cyl   1     4.112 112.99 49.998
## + carb  1     2.713 114.39 50.268
## - qsec  1    21.585 138.69 50.506
## + gear  1     1.190 115.91 50.559
## + vs    1     1.055 116.05 50.585
## + drat  1     0.812 116.29 50.631
## - am    1    25.778 142.88 51.161
## - wt    1    37.411 154.51 52.883
## 
## Step:  AIC=47.24
## mpg ~ hp + wt + qsec + am
## 
##        Df Sum of Sq    RSS    AIC
## - hp    1     9.126 128.70 46.862
## <none>              119.58 47.244
## - qsec  1    19.284 138.86 48.534
## + disp  1     2.477 117.10 48.784
## + cyl   1     0.918 118.66 49.075
## - am    1    23.311 142.89 49.163
## + drat  1     0.339 119.24 49.182
## + carb  1     0.086 119.49 49.229
## + vs    1     0.080 119.50 49.230
## + gear  1     0.001 119.58 49.244
## - wt    1    41.789 161.37 51.838
## 
## Step:  AIC=46.86
## mpg ~ wt + qsec + am
## 
##        Df Sum of Sq    RSS    AIC
## <none>              128.70 46.862
## + hp    1     9.126 119.58 47.244
## - am    1    17.940 146.64 47.733
## + cyl   1     5.052 123.65 47.981
## + carb  1     3.077 125.63 48.330
## + drat  1     0.586 128.12 48.762
## + disp  1     0.576 128.13 48.764
## + gear  1     0.538 128.17 48.770
## + vs    1     0.133 128.57 48.840
## - qsec  1   107.362 236.07 58.208
## - wt    1   138.020 266.72 60.894
# 모델 요약
summary(step_model)
## 
## Call:
## lm(formula = mpg ~ wt + qsec + am, data = trainData)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.8902 -1.6234 -0.6141  1.6720  5.2297 
## 
## Coefficients:
##             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)   7.8994     8.7564   0.902  0.37890    
## wt           -4.1677     0.9486  -4.394  0.00035 ***
## qsec          1.3689     0.3533   3.875  0.00111 ** 
## am            2.9837     1.8837   1.584  0.13061    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 2.674 on 18 degrees of freedom
## Multiple R-squared:  0.8622, Adjusted R-squared:  0.8392 
## F-statistic: 37.54 on 3 and 18 DF,  p-value: 5.916e-08
# 예측 수행
predictions <- predict(step_model, newdata = testData)

# 결과 비교
results <- data.frame(Actual = testData$mpg, Predicted = predictions)

# 결과 시각화
library(ggplot2)
ggplot(results, aes(x = Actual, y = Predicted)) +
  geom_point() +
  geom_abline(slope = 1, intercept = 0, color = "red") +
  labs(title = "Actual vs Predicted MPG",
       x = "Actual MPG",
       y = "Predicted MPG")

# RMSE 계산
rmse <- sqrt(mean((results$Actual - results$Predicted)^2))
print(paste("RMSE:", rmse))
## [1] "RMSE: 2.13100494386592"