@@@ 데이터분석/데이터 분석의 모든 것

Chapter 2. R 프로그래밍 - 2.5 R을 이용한 데이터 조작 방법

HTG 2021. 10. 8. 01:46
728x90

키워드 : head() 함수, tail() 함수, str() 함수, summary() 함수, dim() 함수, read.csv() 함수, read.xlsx() 함수, fread() 함수

더보기

head() 함수 : 첫 번째 행부터 6번째 행까지 추출.

tail() 함수 : 마지막 행부터 6개의 행까지 추출.

str() 함수 : 데이터의 구조를 파악.

summary() 함수 : 숫자 데이터의 각 열별 최소값, 1사분위수, 중앙값, 3사분위수, 최대값, 평균을 구함.

dim() 함수 : 데이터의 차원을 확인.

read.csv() 함수 : csv 파일을 불러옴.

read.xlsx() 함수 : 이용하여 엑셀 파일을 읽어옴.

fread() 함수 : 빠른 속도로 데이터를 읽어올 수 있어 빅데이터 파일을 읽을 때 매우 유용.

2.5.1 데이터의 대략적인 특징 파악에 유용한 함수

분석할 데이터셋이 준비되면 데이터셋의 대략적인 특징을 파악할 필요가 있음.

R에 기본적으로 내장되어 있는 몇 개의 데이터 셋 중 Orange 데이터 셋 사용.

이 데이터 셋에는 오렌지 나무의 종류, 수령, 둘레 등 오렌지 나무에 대한 데이터셋이며 데이터프레임 구조로 되어 있음.

 

2.5.1.1 head() 함수

head() 함수는 첫 번째 행부터 6번째 행까지 추출.

> head(Orange)
  Tree  age circumference
1    1  118            30
2    1  484            58
3    1  664            87
4    1 1004           115
5    1 1231           120
6    1 1372           142

Orange 데이터셋의 Tree열은 factor 데이터 타입으로 오렌지 나무의 종류를 의미.

age 변수는 숫자 데이터 타입이며 나무의 나이 데이터.

circumference 변수는 숫자 데이터 타입이며 나무의 둘레 데이터.

 

head()의 두 번째 매개인자로 추출할 행 개수를 지정할 수 있음.

> head(Orange,3)
  Tree age circumference
1    1 118            30
2    1 484            58
3    1 664            87

 

2.5.1.2 tail() 함수

tail() 함수는 마지막 행부터 6개의 행까지 추출.

> tail(Orange)
   Tree  age circumference
30    5  484            49
31    5  664            81
32    5 1004           125
33    5 1231           142
34    5 1372           174
35    5 1582           177

 

tail()의 두 번째 매개인자로 추출할 행 개수를 지정할 수 있음.

> tail(Orange,3)
   Tree  age circumference
33    5 1231           142
34    5 1372           174
35    5 1582           177

 

2.5.1.3 str() 함수

str() 함수로 데이터의 구조를 파악할 수 있음.

> str(Orange)
Classes ‘nfnGroupedData’, ‘nfGroupedData’, ‘groupedData’ and 'data.frame':	35 obs. of  3 variables:
 $ Tree         : Ord.factor w/ 5 levels "3"<"1"<"5"<"2"<..: 2 2 2 2 2 2 2 4 4 4 ...
 $ age          : num  118 484 664 1004 1231 ...
 $ circumference: num  30 58 87 115 120 142 145 33 69 111 ...
 - attr(*, "formula")=Class 'formula'  language circumference ~ age | Tree
  .. ..- attr(*, ".Environment")=<environment: R_EmptyEnv> 
 - attr(*, "labels")=List of 2
  ..$ x: chr "Time since December 31, 1968"
  ..$ y: chr "Trunk circumference"
 - attr(*, "units")=List of 2
  ..$ x: chr "(days)"
  ..$ y: chr "(mm)"

출력 결과

35 obs. of  3 variables : Orange 데이터는 총 '35개의 관측값과 3개의 열이 존재'라는 의미.

$ Tree         : Ord.factor w/ 5 levels : Tree 변수는 'Ordered factor 데이터 타입이며 총 5개의 범주를 가짐'라는 의미.

그 다음 라인의 출력 결과로 age 변수와 circumference 변수는 각각 number 데이터 타입임을 알 수 있음.

 

2.5.1.4 summary() 함수

summary() 함수로 숫자 데이터의 각 열별 최소값(Min), 1사분위수(1st Qu), 중앙값(Median), 3사분위수(3rd Qu), 최대값(Max), 평균(Mean)을 구할 수 있음.

factor 데이터의 경우는 각 범주별로 관측값 개수를 구할 수 있음.

> summary(Orange)
 Tree       age         circumference  
 3:7   Min.   : 118.0   Min.   : 30.0  
 1:7   1st Qu.: 484.0   1st Qu.: 65.5  
 5:7   Median :1004.0   Median :115.0  
 2:7   Mean   : 922.1   Mean   :115.9  
 4:7   3rd Qu.:1372.0   3rd Qu.:161.5  
       Max.   :1582.0   Max.   :214.0

age 변수와 circumference 변수 각각의 최소값, 1사분위수, 중앙값, 평균, 3사분위수, 최대값이 출력.

Tree 변수는 범주별로 관측값 개수가 출력. 범주는 3, 1, 5, 2, 4가 있고 범주별로 각각 7건의 관측값이 있는 것을 알 수 있음.

 

2.5.1.5 dim() 함수

dim() 함수로 데이터의 차원을 확인할 수 있음.

> dim(Orange)
[1] 35  3     # 35행, 2열의 데이터임을 확인.

 

2.5.2 외부 파일 읽기

데이터셋은 여러 파일 형식으로 저장.

외부 파일을 R로 읽어오는 방법.

 

2.5.2.1 CSV 파일 불러오기

read.csv() 함수로 csv 파일을 불러올 수 있음.

> nhis <- read.csv("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.csv",fileEncoding = "EUC-KR")
> head(nhis)
  성별코드 신장 체중 허리둘레 공복혈당
1        F  160   60     79.5       96
2        M  170   55     69.3       79
3        M  165   70     85.0       80
4        F  150   45     71.5      100
5        F  145   50     77.0      124
6        F  155   50     75.0       97

(파일 만드는 게 힘들었다...)

 

getwd()로 현재 작업 디렉토리를 확인할 수 있음.

> getwd()
[1] "C:/Users/user/Documents"

 

문자를 factor 타입으로 읽으려면 stringsAsFactor = TRUE 옵션을 사용.

문자타입으로 읽으려면 stringsAsFactor = FALSE 옵션을 사용.

 

read.csv()는 읽어온 데이터프레임에 담아 리턴.

str()로 데이터프레임의 구조로 확인 가능.

 

> nhis <- read.csv("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.csv",fileEncoding = "EUC-KR",stringsAsFactors = TRUE)
> str(nhis)
'data.frame':	10 obs. of  5 variables:
 $ 성별코드: Factor w/ 2 levels "F","M": 1 2 2 1 1 1 2 2 1 1
 $ 신장    : int  160 170 165 150 145 155 175 165 155 140
 $ 체중    : int  60 55 70 45 50 50 65 85 55 45
 $ 허리둘레: num  79.5 69.3 85 71.5 77 75 80 98 69 72
 $ 공복혈당: int  96 79 80 100 124 97 80 122 85 111

 

csv 파일의 첫 행인 "성별코드, 신장, 체중, 허리둘레, 공복혈당"이 각각 열 이름으로 읽혔음을 알 수 있음.

만약, csv 파일에 열 이름이 없어 첫 행부터 데이터로 읽어야 한다면 header = F 옵션을 사용.

"신장", "체중", "공복혈당"은 int, "허리둘레"는 num, "성별코드"는 factor 타입으로 읽혔음.

 

read.table()을 이용하여 csv 파일을 불러올 수 있음.

> nhis <- read.table("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.csv",header = T,sep = ",")

 

열의 구분자를 지정하는 sep=","와 첫 행을 열 이름으로 읽는 header = T가 read.csv()에서 디폴트인 것과 다르게 read.table()는 디폴트가 아니므로 필요한 경우 반드시 작성.

 

txt 파일도 비슷한 방법으로 불러올 수 있음.

nhis <- read.table("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.txt",header = T,sep = ",")

 

2.5.2.2 엑셀 파일 불러오기

엑셀 파일을 읽으려면 패키지를 설치해야 함.

엑셀 파일을 다루는 여러가지 패키지 중 openxlsx 패키지의 read.xlsx().

먼저, openxlsx 패키지를 설치한 후 로드.

> nhis <- read.xlsx("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.xlsx")
> head(nhis)
  성별코드 신장 체중 허리둘레 공복혈당
1        F  160   60     79.5       96
2        M  170   55     69.3       79
3        M  165   70     85.0       80
4        F  150   45     71.5      100
5        F  145   50     77.0      124
6        F  155   50     75.0       97

엑셀 파일의 시트 번호를 지정해서 읽을 수 있음.

> nhis <- read.xlsx("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.xlsx", sheet = 2

 

2.5.2.3 빅데이터 파일 불러오기

data.table 패키지의 fread()는 빠른 속도로 데이터를 읽을 수 있어 빅데이터 파일을 읽을 때 유용.

 

data.table 패키지를 설치한 후 로드.

install.packages("data.table")
library(data.table)

 

nhis <- fread("C:/Users/user/Desktop/NHIS_OPEN_GJ2_EUC-KR.csv", encoding = "UTF-8")

 

2.5.3 데이터 추출

데이터프레임의 전체 데이터가 아닌 일부만 추출하여 분석해야 하는 경우가 종종 있음.

데이터프레임의 일부 행 또는 일부 열만 추출하는 방법.

 

2.5.3.1 행 제한

- 행 인덱스를 이용하여 행 제한

Orange[1,]는 1행만 추출.

Orange[-1,]은 1행을 제외하고 모든 행 추출.

이 외에도 다양한 방법으로 추출할 행을 제외할 수 있음.

> Orange[1,]
  Tree age circumference
1    1 118            30
> 
> Orange[1:5,]
  Tree  age circumference
1    1  118            30
2    1  484            58
3    1  664            87
4    1 1004           115
5    1 1231           120
> 
> Orange[6:10,]
   Tree  age circumference
6     1 1372           142
7     1 1582           145
8     2  118            33
9     2  484            69
10    2  664           111
> 
> Orange[c(1,5),]
  Tree  age circumference
1    1  118            30
5    1 1231           120
> 
> Orange[-c(1:29),]
   Tree  age circumference
30    5  484            49
31    5  664            81
32    5 1004           125
33    5 1231           142
34    5 1372           174
35    5 1582           177

 

- 데이터를 비교하여 행 제한

데이터프레임 대괄호 안에서 데이터를 비교하여 추출할 행을 제한하는 코드를 작성할 수 있음.

> Orange[Orange$age == 118,]
   Tree age circumference
1     1 118            30
8     2 118            33
15    3 118            30
22    4 118            32
29    5 118            30
> 
> Orange[Orange$age %in% c(118,484),]
   Tree age circumference
1     1 118            30
2     1 484            58
8     2 118            33
9     2 484            69
15    3 118            30
16    3 484            51
22    4 118            32
23    4 484            62
29    5 118            30
30    5 484            49
> 
> Orange[Orange$age >= 1372,]
   Tree  age circumference
6     1 1372           142
7     1 1582           145
13    2 1372           203
14    2 1582           203
20    3 1372           139
21    3 1582           140
27    4 1372           209
28    4 1582           214
34    5 1372           174
35    5 1582           177

 

- subset() 함수를 이용한 행 제한.

subset()으로 데이터 프레임의 일부 데이터를 추출할 수 있음.

subset()의 첫 번째 매개인자로 데이터프레임을, 두 번째 매개인자로 행을 제한할 비교 연산을 작성.

> subset(Orange, Tree == 1)
  Tree  age circumference
1    1  118            30
2    1  484            58
3    1  664            87
4    1 1004           115
5    1 1231           120
6    1 1372           142
7    1 1582           145
> 
> subset(Orange, age >= 1500 | Tree == 1)
   Tree  age circumference
1     1  118            30
2     1  484            58
3     1  664            87
4     1 1004           115
5     1 1231           120
6     1 1372           142
7     1 1582           145
14    2 1582           203
21    3 1582           140
28    4 1582           214
35    5 1582           177
> 
> subset(Orange, Tree %in% c(3,2) & age >= 1000)
   Tree  age circumference
11    2 1004           156
12    2 1231           172
13    2 1372           203
14    2 1582           203
18    3 1004           108
19    3 1231           115
20    3 1372           139
21    3 1582           140

 

2.5.3.2 열 제한

- 열 이름을 이용하여 열 제한

추출할 열 이름을 대괄호 안 콤마 뒤에 작성.

Orange[, "circumference"]는 모든 행의 circumference열만 추출.

Orange[, c("Tree", "circumference")]는 모든 행의 Tree열, circumference열만을 추출

특정행의 해당열을 뽑으려면 앞에 봤던 행 제한 처럼 Orange[1, c("Tree", "circumference")] 콤마 앞에 행을 설정.

즉, 콤마 앞은 행, 콤마 뒤는 열을 나타내는 자리이다.

> Orange[, "circumference"]
 [1]  30  58  87 115 120 142 145  33  69 111 156 172 203 203  30  51  75 108 115 139
[21] 140  32  62 112 167 179 209 214  30  49  81 125 142 174 177
> 
> Orange[1, c("Tree", "circumference")]
  Tree circumference
1    1            30

 

- 열 인덱스를 이용하여 열 제한

추출한 열 인덱스를 대괄호 안 콤마 뒤에 작성.

> Orange[,1]      # 1열만 추출
 [1] 1 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3 3 3 3 4 4 4 4 4 4 4 5 5 5 5 5 5 5
Levels: 3 < 1 < 5 < 2 < 4

> Orange[,c(1,3)]      # 1열, 3열 추출
   Tree circumference
1     1            30
2     1            58
3     1            87
4     1           115
5     1           120
6     1           142
7     1           145
8     2            33
... 생략

> Orange[,c(1:3)]      # 1열 ~ 3열 추출
   Tree  age circumference
1     1  118            30
2     1  484            58
3     1  664            87
4     1 1004           115
5     1 1231           120
6     1 1372           142
... 생략

> Orange[,-c(1,3)]      # 1열, 3열을 제외한 모든 열 추출
 [1]  118  484  664 1004 1231 1372 1582  118  484  664 1004 1231 1372 1582  118  484
[17]  664 1004 1231 1372 1582  118  484  664 1004 1231 1372 1582  118  484  664 1004
[33] 1231 1372 1582

 

- subset() 함수를 이용한 열 제한

subset() 함수로 데이터프레임의 일부 데이터를 추출할 수 있음.

subset()의 첫 번째 매개인자로 데이터프레임을 담고, 세 번째 매개인자로 추출한 열 이름 또는 열 인덱스를 작성.

> subset(Orange, , c("age","Tree"))
    age Tree
1   118    1
2   484    1
3   664    1
4  1004    1
5  1231    1
6  1372    1
7  1582    1
8   118    2
9   484    2
... 생략

> subset(Orange, , c(1,2))
   Tree  age
1     1  118
2     1  484
3     1  664
4     1 1004
5     1 1231
6     1 1372
7     1 1582
8     2  118
9     2  484
... 생략

 

2.5.3.3 행과 열 제한

행과 열을 모두 제한하여 추출하는 예.

데이터프레임의 대괄호 안에 행 인덱스나 비교연산자를 이용하여 행을 제한하고 콤마 뒤에 추출할 열 이름이나 열 인덱스 작성.

> Orange[1:5, "circumference"]
[1]  30  58  87 115 120

> Orange[Orange$Tree %in% c(3,2), c("Tree","circumference")]
   Tree circumference
8     2            33
9     2            69
10    2           111
11    2           156
12    2           172
13    2           203
14    2           203
15    3            30
16    3            51
17    3            75
18    3           108
19    3           115
20    3           139
21    3           140

 

subset()으로 데이터프레임의 행과 열을 제한하여 데이터를 추출.

subset()의 첫 번째 매개인자로 데이터프레임을 담고, 두 번째 매개인자로 행을 제한할 비교 연산, 세 번째 매개인자로 추출할 열 이름 또는 열 인덱스를 작성.

> subset(Orange, Tree == 1, "age")
   age
1  118
2  484
3  664
4 1004
5 1231
6 1372
7 1582

 

2.5.3.4 정렬

데이터를 추출한 후 정렬.

order()는 데이터를 오름차순으로 정렬한 후 정렬 결과 데이터의 인덱스를 순서대로 반환.

order()가 반환한 인덱스 순서대로 데이터를 추출하면 정렬된 데이터가 추출.

> # 1) 먼저, circumference가 50보다 적은 행만 추출하여 OrangeT1에 담음
> OrangeT1 <- Orange[Orange$circumference < 50, ]
> OrangeT1
   Tree age circumference
1     1 118            30
8     2 118            33
15    3 118            30
22    4 118            32
29    5 118            30
30    5 484            49

> # 2) circumference 데이터의 오름차순으로 인덱스를 리턴
> order(OrangeT1$circumference)
[1] 1 3 5 4 2 6

> # 3) order()를 이용하여 OrangeT의 circumference 값 기준으로 오름차순 정렬한 후,
> # 추출하려면 다음과 같이 작성.
> OrangeT1[order(OrangeT1$circumference),]
   Tree age circumference
1     1 118            30
15    3 118            30
29    5 118            30
22    4 118            32
8     2 118            33
30    5 484            49

> # 4) 내림차순 정렬은 order() 안에 마이너스 기호를 사용.
> OrangeT1[order(-OrangeT1$circumference),]
   Tree age circumference
30    5 484            49
8     2 118            33
22    4 118            32
1     1 118            30
15    3 118            30
29    5 118            30

 

2.5.3.5 그룹별 집계

aggregate()를 이용하여 데이터프레임의 그룹별 집계를 할 수 있음.

첫 번째 매개인자의 ~ 뒤에 그룹핑할 기준 열 이름을 쓰고, ~ 앞에 집계할 데이터가 있는 열 이름을 씀.

Tree열의 값이 같은 행끼리 묶은 후, circumference 값의 평균을 구함.

> # Tree별 circumference 평균
> aggregate(circumference ~ Tree, Orange, mean)
  Tree circumference
1    3      94.00000
2    1      99.57143
3    5     111.14286
4    2     135.28571
5    4     139.28571

> # Tree별 age 평균
> aggregate(age ~ Tree, Orange, mean)
  Tree      age
1    3 922.1429
2    1 922.1429
3    5 922.1429
4    2 922.1429
5    4 922.1429

 

2.5.3.6 plyr 패키지

ply() 함수는 두개 문자 접두어를 가짐.

접두어의 첫 문자는 입력 데이터 타입을 나타내고, 두 번째 문자는 출력 데이터 타입을 나타냄.

접두어 문자 설명
a 배열
d 데이터프레임
| 리스트
_ 출력 용도로만 사용이 가능. 아무 출력이 없을 때 사용.

 

예를 들어, ddply()는 첫 번재 문자와 두 번째 문자가 모두 d이므로 입력과 출력 데이터 타입이 모두 데이터프레임인 함수. 다른 예로, adply()는 첫 번째 문자는 a이므로 입력은 배열이고, 두 번째 문자는 d이므로 출력은 데이터프레임인 함수.

단, 배열이 아니더라도 숫자 인덱스로 처리가 가능한 경우는 데이터프레임 등 다른 데이터 타입도 입력이 가능.

 

각 함수는 데이터를 입력받아 분할하고, 함수를 적용하여 처리한 후, 결과를 재조합하는 과정을 거침.

install.packages("plyr")
library(plyr)

 

다음은 ddply()를 활용하여 Orange 데이터프레임의 Tree열의 값이 같은 것끼리 분할한 후 summarize()를 적용하여 circumference 평균을 구하고, 새로운 변수 m에 저장한 후 반환하는 예.

> ddply(Orange, .(Tree), summarise, m = mean(circumference))
  Tree         m
1    3  94.00000
2    1  99.57143
3    5 111.14286
4    2 135.28571
5    4 139.28571

 

ddply()를 활용하여 Orange 데이터 중 age > 1300인 행만 추출한 후 Tree열의 값이 같은 것 끼리 분할 후, circumference 평균을 구하여 새로운 변수 m에 저장.

단, transform()를 적용하여 반환. transform()는 입력 데이터프레임에 결과 변수 m열을 추가하여 반환.

> ddply(Orange[Orange$age > 1300, ], .(Tree), transform, m = mean(circumference))
   Tree  age circumference     m
1     3 1372           139 139.5
2     3 1582           140 139.5
3     1 1372           142 143.5
4     1 1582           145 143.5
5     5 1372           174 175.5
6     5 1582           177 175.5
7     2 1372           203 203.0
8     2 1582           203 203.0
9     4 1372           209 211.5
10    4 1582           214 211.5

 

2.5.3.7 dplyr 패키지

dplyr 패키지는 %>% 기호와 select(), filter() 등의 함수로 데이터프레임에서 데이터를 추출할 수 있도록 해줌.

install.packages("dplyr")
library(dplyr)

 

다음은 %>% 기호를 이용하여 Orange 데이터프레임에서 데이터를 추출.

> # 1) 행 제한
> Orange %>% filter(age >= 200) # age >= 200인 행, 모든 열 추출
   Tree  age circumference
1     1  484            58
2     1  664            87
3     1 1004           115
4     1 1231           120
5     1 1372           142
6     1 1582           145
생략 ...


# 2) 열 제한
Orange %>% select(circumference)       # 모든 행, circumference 열 추출
Orange %>% select(Tree, circumference) # 모든 행, Tree, circumference 열 추출
Orange %>% select(-age)                # 모든 행, age열 제외 추출
Orange %>% select(-age) %>% head       # age열 제외한 모든 열, 첫 행부터 6개 행 추출


# 3) 행과 열 제한
# age >= 200인 행, age, circumference열, 첫 행부터 6개 행 추출
Orange %>% filter(age >= 200) %>% select(age, circumference) %>% head
# Tree == 1인 행, age, circumference열 추출
Orange %>% filter(age >= 200) %>% select(age, circumference) %>% head
# Tree가 1 또는 2 인 행, age, circumference열 추출
Orange %>% filter(Tree %in% c(1,2)) %>% select(age, circumference)


# 4) 정렬
Orange %>% arrange(age) # age열 데이터를 기준으로 오름차순 정렬하여 추출
Orange %>% arrange(-age) # age열 데이터를 기준으로 내림차순 정렬하여 추출

# age열 데이터를 기준으로 오름차순 정렬, age열 데이터가 같은 경우
# circumference열 데이터를 기준으로 오름차순 정렬하여 추출
Orange %>% arrange(age, circumference)

# 행 제한 조건 : age >= 200
# 정렬 조건 : age열 데이터를 기준으로 오름차순 정렬
# 열 제한 조건 : Tree열, age열
Orange %>% filter(age >= 200) %>% arrange(age) %>% select(Tree, age)


# 5) 그룹별 집계
# Tree열 데이터가 같은 행끼리 그룹핑한 후 각 그룹별 행 개수 추출
Orange %>% group_by(Tree) %>% summarise(n())

# Tree열 데이터가 같은 행끼리 그룹핑한 후 각 그룹별 행 개수와 circumference 평균 추출
Orange %>% group_by(Tree) %>% summarise(n(), mean(circumference))

# Tree열 데이터가 같은 행끼리 그룹핑한 후 각 그룹별 행 개수와 circumference 평균과
# age 합과 age 평균 추출
Orange %>% group_by(Tree) %>% summarise(n(), mean(circumference), sum(age), mean(age))


# 6) 파생 열 생성
# Tree열 데이터가 같은 행끼리 그룹핑한 후 각 그룹별 행 개수 추출하고,
# tot라는 파생 열 생성. tot는 각 그룹별 행 개수 저장
Orange %>% group_by(Tree) %>% summarise(n = n()) %>% mutate(tot = sum(n))

 

2.5.3.8 sqldf 패키지

sqldf()는 SQL에 익숙한 사용자에게 유용한 함수.

sqldf()는 SQL을 이용하여 데이터를 조회할 수 있게 해줌.

install.packages("spldf")
library(spldf)

 

sqldf()와 SQL을 이용한 데이터 조회

# 대상 데이터 : Orange 데이터프레임
# 행 제한 : age > 1500
# 열 제한 : 모든 열
# 정렬 : age열 데이터를 기준으로 오름차순 정렬
# age열 데이터가 같은 경우 circumference열 데이터 기준으로 내림차순
sqldf("select * from Orange where age > 1500 order by age, circumference desc")

# 대상 데이터 : Orange 데이터프레임
# 행 제한 : age > 1200이고 Tree = 1인 행
# 열 제한 : Tree열과 age열
# 정렬 : age열 데이터를 기준으로 내림차순 정렬
sqldf("select Tree, age from Orange where age > 1200 and Tree = 1 order by age desc")

# 대상 데이터 : Orange 데이터프레임
# 그룹핑 : Tree 값을 기준으로 그룹핑
# 열 제한 : 그룹별 circumference 데이터의 평균 추출
# 정렬 : age열 데이터를 기준으로 내림차순 정렬
sqldf("select avg(circumference) from Orange group by Tree")

 

2.5.4 데이터 구조 변경

데이터 구조를 변경하는 병합과 변환.

 

2.5.4.1 데이터 병합

열 방향으로 두 데이터프레임을 병합할 때 merge() 또는 cbind()를 사용.

3개의 데이터프레임 준비

> stu1 <- data.frame(no = c(1, 2, 3), midterm = c(100, 90, 80))
> stu2 <- data.frame(no = c(1, 2, 3), finalterm = c(100, 90, 80))
> stu3 <- data.frame(no = c(1, 4, 5), quiz = c(99, 88, 77))

 

merge()는 병합 대상 데이터프레임들에 있는 동일 열 이름의 동일 데이터 행끼리 병합.
stu1과 stu2을 merge()로 병합. stu1와 stu2의 동일 열은 no이므로 no 열의 데이터가 같은 행끼리 병합.

> stu1
  no midterm
1  1     100
2  2      90
3  3      80
> 
> stu2
  no finalterm
1  1       100
2  2        90
3  3        80
> 
> merge(stu1,stu2)
  no midterm finalterm
1  1     100       100
2  2      90        90
3  3      80        80

 

다음은 merge()로 병합할 때 일부 행이 포함 되지 않는 예.

stu1과 stu3은 no라는 동일한 열이 있음.

stu1의 no열의 값은 1, 2, 3이고, stu3의 no열의 값은 1, 4, 5.

이때 no 열의 값이 같은 행인 1행은 병합 결과에 포함. 나머지 행은 제외.

> stu1
  no midterm
1  1     100
2  2      90
3  3      80
> 
> stu3
  no quiz
1  1   99
2  4   88
3  5   77
> 
> merge(stu1,stu3)
  no midterm quiz
1  1     100   99

 

merge() 함수에서 all = TRUE 옵션을 사용하면 동일 열끼리 값이 일치하지 않는 행도 병합 결과에 포함.

SQL의 외부 조인과 유사.

> merge(stu1,stu3, all = TRUE)
  no midterm quiz
1  1     100   99
2  2      90   NA
3  3      80   NA
4  4      NA   88
5  5      NA   77

 

merge() 함수에서 all.x = TRUE 옵션을 사용하면 두 데이터프레임의 동일 열인 no열의 값이 일치하는 것이 없어도 왼쪽 데이터프레임의 행은 무조건 병합 결과에 포함.

SQL의 왼쪽 외부 조인과 유사.

> merge(stu1,stu3, all.x = TRUE)
  no midterm quiz
1  1     100   99
2  2      90   NA
3  3      80   NA

 

merge() 함수에서 all.y = TRUE 옵션을 사용하면 두 데이터프레임의 동일 열인 no열의 값이 일치하는 것이 없어도 오른쪽 데이터프레임의 행은 무조건 병합 결과에 포함.

SQL의 오른쪽 외부 조인과 유사.

> merge(stu1,stu3, all.y = TRUE)
  no midterm quiz
1  1     100   99
2  4      NA   88
3  5      NA   77

 

cbind()는 단순히 열을 합침.

> cbind(stu1, stu2)
  no midterm no finalterm
1  1     100  1       100
2  2      90  2        90
3  3      80  3        80
> 
> cbind(stu1, stu3)
  no midterm no quiz
1  1     100  1   99
2  2      90  4   88
3  3      80  5   77

 

rbind()는 행을 합침. 이때 두 데이터프레임의 열 이름이 동일.

> stu4 <- data.frame(no = c(4, 5, 6), midterm = c(99, 88 ,77))
> 
> rbind(stu1,stu4)
  no midterm
1  1     100
2  2      90
3  3      80
4  4      99
5  5      88
6  6      77

 

2.5.4.2 데이터 구조 변환

reshape2 패키지의 melt(), cast()로 데이터의 구조를 변환할 수 있음.

melt()는 식별자, 변수, 값, 3개열로 변환하는 함수. cast()는 melt()를 통해 변환한 데이터 구조를 원래대로 돌려놓을 수 있음.

> product_info = data.frame(product_no = c("1", "2", "3"), seoul_qty = c(3, 5, 6), busan_qty = c(10, 20, 30))
> product_info
  product_no seoul_qty busan_qty
1          1         3        10
2          2         5        20
3          3         6        30

product_info와 같은 데이터 구조는 지역별로 데이터를 집계하여 분석하기 불편할 수 있음.

melt()를 이용하여 구조를 변환하는 예.

install.packages("reshape2")
library(reshape2)

melt()는 식별자 열, 변수 열, 값 열로 데이터 구조를 변환.

식별자는 id.vars 매개인자로 지정.

> m_prod <- melt(product_info, id.vars = "product_no")
> 
> m_prod
  product_no  variable value
1          1 seoul_qty     3
2          2 seoul_qty     5
3          3 seoul_qty     6
4          1 busan_qty    10
5          2 busan_qty    20
6          3 busan_qty    30

melt()로 변환한 데이터 구조를 cast()를 통해 원상 복귀시킬 수 있음.

cast()는 변환 결과 데이터 타입이 데이터프레임이어야 하는 경우 dcast(), 벡터나 행렬, 배열을 반환해야 하는 경우는 acast()를 사용.

> dcast(m_prod, product_no ~ variable)
  product_no seoul_qty busan_qty
1          1         3        10
2          2         5        20
3          3         6        30