아이티윌_데이터 분석 55기/강의내용 필기_통계 및 분석

#8 8일차_dplyr, 시각화

ecosso 2026. 4. 9. 16:04

01. dplyr 패키지

02. 시각화

 -01 plot


01. dplyr 패키지

- SQL처럼 구조화 된 명령어 작성 가능( %>% 을 사용하여 명령어의 순차적 실행 전달)
- 다양한 DBMS에서 사용 가능한 데이터 처리 함수
- 다양한 데이터 처리 함수 제공(lag, lead, dense_rank, select, between)

 

 1) %>% 에서 함수 사용
emp %>% 
  mutate(LAG_SAL = lag(SAL), LEAD_SAL = lead(SAL)) %>% 
  filter(between(SAL, 1000, 3000))

> emp %>% 
+   mutate(LAG_SAL = lag(SAL), LEAD_SAL = lead(SAL)) %>% 
+   filter(between(SAL, 1000, 3000))
   EMPNO  ENAME      JOB  MGR        HIREDATE  SAL COMM DEPTNO LAG_SAL LEAD_SAL
1   7499  ALLEN SALESMAN 7698 1981-02-20 0:00 1600  300     30     800     1250
2   7521   WARD SALESMAN 7698 1982-02-22 0:00 1250  500     30    1600     2975
3   7566  JONES  MANAGER 7839 1981-04-02 0:00 2975   NA     20    1250     1250
4   7654 MARTIN SALESMAN 7698 1981-09-28 0:00 1250 1400     30    2975     2850
5   7698  BLAKE  MANAGER 7839 1981-05-01 0:00 2850   NA     30    1250     2450
6   7782  CLARK  MANAGER 7839 1981-06-09 0:00 2450   NA     10    2850     3000
7   7788  SCOTT  ANALYST 7566 1987-04-17 0:00 3000   NA     20    2450     5000
8   7844 TURNER SALESMAN 7698 1981-09-08 0:00 1500    0     30    5000     1100
9   7876  ADAMS    CLERK 7788 1987-05-23 0:00 1100   NA     20    1500      950
10  7902   FORD  ANALYST 7566 1981-12-03 0:00 3000   NA     20     950     1300
11  7934 MILLER    CLERK 7782 1982-01-23 0:00 1300   NA     10    3000       NA


 2) lag, lead 함수
emp[between(emp$SAL, 1000, 3000),]
lag(emp$SAL)
lead(emp$SAL)

> emp[between(emp$SAL, 1000, 3000),]
   EMPNO  ENAME      JOB  MGR        HIREDATE  SAL COMM DEPTNO
2   7499  ALLEN SALESMAN 7698 1981-02-20 0:00 1600  300     30
3   7521   WARD SALESMAN 7698 1982-02-22 0:00 1250  500     30
4   7566  JONES  MANAGER 7839 1981-04-02 0:00 2975   NA     20
5   7654 MARTIN SALESMAN 7698 1981-09-28 0:00 1250 1400     30
6   7698  BLAKE  MANAGER 7839 1981-05-01 0:00 2850   NA     30
7   7782  CLARK  MANAGER 7839 1981-06-09 0:00 2450   NA     10
8   7788  SCOTT  ANALYST 7566 1987-04-17 0:00 3000   NA     20
10  7844 TURNER SALESMAN 7698 1981-09-08 0:00 1500    0     30
11  7876  ADAMS    CLERK 7788 1987-05-23 0:00 1100   NA     20
13  7902   FORD  ANALYST 7566 1981-12-03 0:00 3000   NA     20
14  7934 MILLER    CLERK 7782 1982-01-23 0:00 1300   NA     10
> lag(emp$SAL)
 [1]   NA  800 1600 1250 2975 1250 2850 2450 3000 5000 1500 1100  950 3000
> lead(emp$SAL)
 [1] 1600 1250 2975 1250 2850 2450 3000 5000 1500 1100  950 3000 1300   NA


 3) 원하는 컬럼 선택
emp[, c('EMPNO', 'ENAME')]
select(emp, c(EMPNO, ENAME))
select(emp, -HIREDATE)
select(emp, JOB:DEPTNO)

> emp[, c('EMPNO', 'ENAME')]
   EMPNO  ENAME
1   7369  SMITH
2   7499  ALLEN
3   7521   WARD
4   7566  JONES
5   7654 MARTIN
6   7698  BLAKE
7   7782  CLARK
8   7788  SCOTT
9   7839   KING
10  7844 TURNER
11  7876  ADAMS
12  7900  JAMES
13  7902   FORD
14  7934 MILLER
> select(emp, c(EMPNO, ENAME))
   EMPNO  ENAME
1   7369  SMITH
2   7499  ALLEN
3   7521   WARD
4   7566  JONES
5   7654 MARTIN
6   7698  BLAKE
7   7782  CLARK
8   7788  SCOTT
9   7839   KING
10  7844 TURNER
11  7876  ADAMS
12  7900  JAMES
13  7902   FORD
14  7934 MILLER
> select(emp, -HIREDATE)
   EMPNO  ENAME       JOB  MGR  SAL COMM DEPTNO
1   7369  SMITH     CLERK 7902  800   NA     20
2   7499  ALLEN  SALESMAN 7698 1600  300     30
3   7521   WARD  SALESMAN 7698 1250  500     30
4   7566  JONES   MANAGER 7839 2975   NA     20
5   7654 MARTIN  SALESMAN 7698 1250 1400     30
6   7698  BLAKE   MANAGER 7839 2850   NA     30
7   7782  CLARK   MANAGER 7839 2450   NA     10
8   7788  SCOTT   ANALYST 7566 3000   NA     20
9   7839   KING PRESIDENT   NA 5000   NA     10
10  7844 TURNER  SALESMAN 7698 1500    0     30
11  7876  ADAMS     CLERK 7788 1100   NA     20
12  7900  JAMES     CLERK 7698  950   NA     30
13  7902   FORD   ANALYST 7566 3000   NA     20
14  7934 MILLER     CLERK 7782 1300   NA     10
> select(emp, JOB:DEPTNO)
         JOB  MGR        HIREDATE  SAL COMM DEPTNO
1      CLERK 7902 1980-12-17 0:00  800   NA     20
2   SALESMAN 7698 1981-02-20 0:00 1600  300     30
3   SALESMAN 7698 1982-02-22 0:00 1250  500     30
4    MANAGER 7839 1981-04-02 0:00 2975   NA     20
5   SALESMAN 7698 1981-09-28 0:00 1250 1400     30
6    MANAGER 7839 1981-05-01 0:00 2850   NA     30
7    MANAGER 7839 1981-06-09 0:00 2450   NA     10
8    ANALYST 7566 1987-04-17 0:00 3000   NA     20
9  PRESIDENT   NA 1981-11-17 0:00 5000   NA     10
10  SALESMAN 7698 1981-09-08 0:00 1500    0     30
11     CLERK 7788 1987-05-23 0:00 1100   NA     20
12     CLERK 7698 1981-12-03 0:00  950   NA     30
13   ANALYST 7566 1981-12-03 0:00 3000   NA     20
14     CLERK 7782 1982-01-23 0:00 1300   NA     10


 4) 원하는 행 선택
emp[emp$DEPTNO == 10, ]
filter(emp, DEPTNO == 10)     # dplyr 패키지 함수
subset(emp, DEPTNO == 10) # base 함수

> emp[emp$DEPTNO == 10, ]
   EMPNO  ENAME       JOB  MGR        HIREDATE  SAL COMM DEPTNO
7   7782  CLARK   MANAGER 7839 1981-06-09 0:00 2450   NA     10
9   7839   KING PRESIDENT   NA 1981-11-17 0:00 5000   NA     10
14  7934 MILLER     CLERK 7782 1982-01-23 0:00 1300   NA     10
> filter(emp, DEPTNO == 10) # dplyr 패키지 함수
  EMPNO  ENAME       JOB  MGR        HIREDATE  SAL COMM DEPTNO
1  7782  CLARK   MANAGER 7839 1981-06-09 0:00 2450   NA     10
2  7839   KING PRESIDENT   NA 1981-11-17 0:00 5000   NA     10
3  7934 MILLER     CLERK 7782 1982-01-23 0:00 1300   NA     10
> subset(emp, DEPTNO == 10) # base 함수
   EMPNO  ENAME       JOB  MGR        HIREDATE  SAL COMM DEPTNO
7   7782  CLARK   MANAGER 7839 1981-06-09 0:00 2450   NA     10
9   7839   KING PRESIDENT   NA 1981-11-17 0:00 5000   NA     10
14  7934 MILLER     CLERK 7782 1982-01-23 0:00 1300   NA     10

02. 시각화

 - 기본 시각화 함수(plot, lines, barplot, ...) + 외부패키지 함수 (ggplot2)

 

 -01 plot
 - 점, 선 그래프(기본)
 - 데이터프레임의 교차 산점도 출력 
 - 다양한 분석 결과 시각화

?plot

plot(x, 
       y = NULL, 
       type = "p",  # 그래프 타입 (p:산점도, l:선그래프프)
       xlim = NULL, # x축 범위
       ylim = NULL, # y축 범위
       log = "",    # log 출력
       main = NULL, # 메인제목
       sub = NULL,  # 서브제목
       xlab = NULL, # x축 이름
       ylab = NULL, # y축 이름
       ann = par("ann"), # 축 제목 출력 여부
       axes = TRUE, # 눈금 출력 여부(F로 설정하면 그래프 테두리가 모두 사라짐)
       cex = ,      # 점 크기
       pch = ,      # 점 모양
       lwd = ,      # 라인 두께
       col = ,      # 색
       lty = 1,     # 라인 스타일 (1:실선, 2:점선 ...)
       ) 

 

# 새로운 figure 출력
dev.new()

plot(v1, v2)

 


# 기본 plot 출력(산점도)
v1 <- c(1, 4, 10, 33, 23, 12, 50, 38, 33, 25)
v1 <- sort(v1)
v2 <- c(10, 2, 30, 45, 20, 33, 10, 34, 23, 50)
plot(v1, v2) # type = "p"

plot(v1, v2, type = "l")  # 선그래프 출력

plot(v1, v2, type = "o")  # 선과 점 그래프 출력

plot(v1, v2, type = "o", lty = 2) # 점선력력

plot(v1, v2, type = "o", lty = 2, pch = 10) # 점 모양

plot(v1, v2, type = "o", lty = 2, pch = 8, cex = 3) # 점 크기

plot(v1, v2, type = "o", lty = 2, pch = 8, lwd = 3) # 선 굵기

plot(v1, v2, type = "o", lty = 2, ylim = c(0,80)) # y축 범위 조절

plot(v1, v2, type = "o", 
     xlab = 'x축', ylab = 'y축', main = '선그래프', las = 1) # las : 눈금 회전(수평

plot(v1, v2, ann = F) # x축, y축 기본 이름 삭제

plot(v1, v2, axes = F) # 눈금 지우기

plot(v1, v2, type = 'o', lty = 2, col = 'red') # 색상 변경

plot(v1, v2, type = 'o', lty = 2, col = '#6495ED') # 색상 변경

# ** plot 함수를 사용한 데이터프레임의 교차 산점도 출력
iris

> iris
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
1            5.1         3.5          1.4         0.2     setosa
2            4.9         3.0          1.4         0.2     setosa
3            4.7         3.2          1.3         0.2     setosa
4            4.6         3.1          1.5         0.2     setosa
5            5.0         3.6          1.4         0.2     setosa
6            5.4         3.9          1.7         0.4     setosa
7            4.6         3.4          1.4         0.3     setosa
8            5.0         3.4          1.5         0.2     setosa
9            4.4         2.9          1.4         0.2     setosa
10           4.9         3.1          1.5         0.1     setosa

 

plot(iris[-5])

** plot 함수를 사용한 데이터프레임의 교차 산점도 출력

plot(iris[-5], col = iris$Species)

* col = 1 : BLACK, col =2 RED, col = 3 GREEN

* 각 factor가 서로 다른 색상으로 표현이 됨

  > factor 변수는 level 순서대로 1,2,3의 값을 가진다.

  > 따라서 col 옵션 역시 동일하게 해석된다.

 * 사용자 정의 팔레트 생성

p1 <- ifelse(iris$Species == 'setosa', '#2F4F4F',

             ifelse(iris$Species == 'versicolor', '#00BFFF', '#FF4500'))

plot(iris[-5], col = p1)

# * 외부 패키지 팔레트 사용
install.packages('colorspace')
library(colorspace)
colorspace::hcl_palettes() # 특정 팔레트 그룹 색 확인
colorspace::hcl_palettes(plot=T) # 팔레트 전체 색상 확인

 

hcl_palettes('Sequential', plot=T) # 특정 팔레트 그룹 색 확인

colorspace::sequential_hcl(3, # 색 개수
                           'plasma')  # 팔레트 이름

 

p2 <- colorspace::sequential_hcl(3, # 색 개수
                                'Terrain2')  # 팔레트 이름

 

또는


p1 <- ifelse(iris$Species == 'setosa', p2[1],
             ifelse(iris$Species == 'versicolor', p2[2], p2[3]))

plot(iris[-5], col = p2)

[ 여러 선 그래프 출력 ]

- plot 함수는 데이터프레임 전달 시 교차산점도 출력 -> 비교 선그래프 출력 불가
- 하나씩 선그래프 출력 or 외부패키지 사용(ggplot2)

- plot으로 메인설정 -> lines로 새 선그래프 추가

 

1) 눈금변경
axis(side,        # 방향(1:x축, 2:y축)
     at = ,       # 눈금좌표
     labels = )   # 눈금이름

 

예제 ) Fruits 데이터를 사용하여 과일별 연도별 sales의 증감추이 선그래프 출력
library(googleVis)
Fruits

Fruits2  <- dcast(Fruits, Year ~ Fruit, value.var = 'Sales')
rownames(Fruits2) <- Fruits2$Year
Fruits2$Year <- NULL

dev.new()
plot(Fruits2$Apples , type = 'o', col = p2[1], ylim = c(0,150), axes = F)
lines(Fruits2$Bananas, type = 'o', col = p2[2])
lines(Fruits2$Oranges, type = 'o', col = p2[3])


axis(1, at = c(1,2,3), labels = rownames(Fruits2))

* x축의 정보가 중첩되는 문제가 발생한다.

 

plot(Fruits2$Apples , type = 'o', col = p2[1], ylim = c(0,150), axes = F)
lines(Fruits2$Bananas, type = 'o', col = p2[2])
lines(Fruits2$Oranges, type = 'o', col = p2[3])
axis(1, at = c(1,2,3), labels = rownames(Fruits2))

 

* 따라서 axes=F 옵션을 통해 필요없는 정보를 제거한다.

 

axis(2) # y축 추가
box()   # 테두리 추가

plot(Fruits2$Apples , type = 'o', col = p2[1], ylim = c(0,150), axes = F,
     main = '과일별 판매량 변화 추이', xlab = '연도', ylab = '판매량')
lines(Fruits2$Bananas, type = 'o', col = p2[2])
lines(Fruits2$Oranges, type = 'o', col = p2[3])


axis(1, at = c(1,2,3), labels = rownames(Fruits2))
axis(2)
box()

 

 2) 범례 설정

legend(x,         # x축 좌표("bottomright","bottom"...)
            y,         # y축 좌표
            legend = , # 범례 이름(각 그래프 설명)
            lty = ,    # 선 스타일(실제 선그래프와 동일하게 적용)
           cex = ,    # 글자크기
            fill = ,   # 막대그래프용 색 전달
            title,     # 제목
            title.adj, # 제목 좌우 위치
            title.cold = ,
            title.cex = ,
            title.fond = ,
            box.lwd = ,# 테두리 굵기
            box.col = ,
            box.lty = ,
            bty = 'n', # 테두리 생략
            bg = )     # 배경색

 

legend('bottomright', legend = names(Fruits2), lty = 1, col = p2)

# 범례 위치 직접 지정

legend(2.1, 75, legend = names(Fruits2), lty = 1, col = p2,
       title = '과일 이름', title.col = 'red', bg =  '#F5F5F5')

 

 3) 제목 설정

title(main = ,      # 메인제목
       sub = ,       # 서브제목
       xlab = ,
       ylab = ,
       col.main = ,  # 메인색
       col.lab,      # x축, y축 색
       col.sub,      # 서브색
       font.main,
       font.lab,
       font.sub,
       cex.main,
       cex.lab,
       cex.sub)

 

 4) 여백에 텍스트 표시

mtext("y축 좌표", 
      side = 2,         # 위치(1:아래, 2:왼, 3:위, 4:오른쪽)
      line = 1,         # 라인에서 떨어짐 정도
      las = 1,          # 회전(0:수직, 1:수평)
      at = 12000)       # 위치(실제 눈금) 

 

# y축 이름 설정
mtext("판매량",
      side = 2,# 위치 (1: 아래, 2 : 왼, 3 : 위, 4 : 오른쪽)
      line = 1,
      las = 1,
      at = 180) 

 

 

 5) 텍스트 전달

text(x,            # x 위치
     y = NULL,     # y 위치
     labels = ,    # 텍스트
     pos = ,       # 기준점 대비 위치(1:아래, 2:왼, 3:위, 4:오른)
     offset = 0.5, # pos 거리 조절
     xpd = F,      # 그래프 밖 출력 여부
     srt = 0       # 글자회전 각도
     ...)

 

 6) 여백 조절

par('mar')                      # 현재 여백 확인(순서대로 하, 좌, 상, 우) *** 수정필요
par(mar = c(6, 4, 4, 2))        # 현재 여백 확인(순서대로 하, 좌, 상, 우)

 

 7) 현재 그래프 범위 확인

par('usr')                      # 좌, 우, 상, 하 순서

 

 8) 파라미터 변경

par(bg = '#F2F4FC')

 

 

# [ 예제 ]

# 승차 총합 기준으로 top5 역 확인,
# 해당역의 시간대별 승차 변화 시각화

sub <- read.csv('subway2.csv', fileEncoding = 'cp949', skip = 1)
sub2 <- dplyr::filter(sub, 구분 == '승차')
sub2$구분 <- NULL

sub2 <- melt(sub2, id.vars = '전체', variable.name = '시간대', value.name = '승차수')

sub2$시간대 <- as.numeric(str_sub(sub2$시간대, 2, 3))

# 역별 승차 총합
sub3 <- ddply(sub2, .(전체), summarise, 승차총합 = sum(승차수)) |> arrange(-승차총합)

# top 5 확인
sname <- sub3[1:5,'전체']

 

# 시각화
dev.new()
par(bg = '#F8F9F8')

windowsFonts(
  gugi = windowsFont("Gugi 보통")
)

par(family = 'gugi')
my_col1 <- c('#FF6666', '#66FFB2', '#3399FF','#CC99FF','#FF007F')

plot(total$'강 남'/1000, type = 'o', lty = 2, col = my_col1[1],
     ylim = c(0,400), axes = F,
     xlab = '시간대', ylab = '')
lines(total$'강 변'/1000, type = 'o', lty = 2, col = my_col1[2])
lines(total$'삼 성'/1000, type = 'o', lty = 2, col = my_col1[3])
lines(total$'신 림'/1000, type = 'o', lty = 2, col = my_col1[4])
lines(total$'잠 실'/1000, type = 'o', lty = 2, col = my_col1[5])

axis(1, at = 1:nrow(total), rownames(total))
axis(2)
box()

title('역별 시간대별 승차 추이', col.main = 'red')
mtext('시간대(천)', side = 2, las = 1, at = 450)

legend(18.5, 400, legend = names(total), col = my_col1,
       lty = 2, title = '역이름', bg = '#EEF2EF')