2-2 데이터프레임 다루기
R에는 4가지 종류의 벡터가 있다. (character, factor, integer, numeric)
작은 데이터를 다룰 때는 숫자는 모두 numeric을 사용해도 괜찮다. 하지만 빅데이터를 다루게 되면 integer과 numeric을 반드시 구분하는 것이 좋다.
a1<-c(5,3,6,3,1)
a1
is(a1) # [1] "numeric" "vector"
a1<-c(1L,2L,3L)
is(a1) # [1] "integer" "double" "numeric" "vector"
# [5] "data.frameRowLabels"
a1<-as.integer(a1)
R
복사
b<-c(1.23, 6.63452, 4.34234)
b
is(b) # [1] "numeric" "vector"
a2 <-c("짬뽕","짜장면","짬뽕","짬뽕","짜장면")
a2
a3<-c(7,3,7,5,2,"짜장면")
a3
is(a3) # [1] "character" "vector" "data.frameRowLabels" "SuperClassMethod"
R
복사
벡터는 여러 개 종류가 섞이지 않는다.
명목형 변수를 만들어 보겠다. 문자열 벡터를 factor형으로 변환해줘야 한다. ( as 함수를 이용한다 )
a2<-as.factor(a2)
a2
#[1] 짬뽕 짜장면 짬뽕 짬뽕 짜장면
#Levels: 짜장면 짬뽕
is(a2)
#[1] "factor" "integer" "oldClass" "double"
#[5] "numeric" "vector" "data.frameRowLabels"
R
복사
명목형 변수는 통계학에서 계산 목적을 위해 정수값을 부여하기도 한다. (integer) 후에 계산이 필요할 때 정수로 변환하지 않아도 된다.
이제 순서형 변수를 만들어 보겠다. 순서형 변수는 factor()함수를 사용한다.
a2 <-c("짬뽕","짜장면","짬뽕","짬뽕","짜장면")
a2<-factor(a2,ordered=T)
a2
# [1] 짬뽕 짜장면 짬뽕 짬뽕 짜장면
# Levels: 짜장면 < 짬뽕
R
복사
순서형 변수로의 변환이 아니라 직접 변수를 새로 만들 수도 있다. 이렇게 직접 만들때는 levels를 직접 설정할 수 있다. ordered=T 를 추가하면 순서형 변수가 된다.
a5<-factor(c("남","여","여","남"),levels=c("남","여","소녀"))
a5
# [1] 남 여 여 남
# Levels: 남 여 소녀
R
복사
2-2-2 데이터프레임
벡터의 모음으로 만들어지는 데이터프레임. 데이터프레임을 만드는 방법과 데이터프레임을 핸들링하는 방법을 배워보자. ( data.frame () 함수 사용 )
# 벡터를 만든다.
a1 <- c(5,3,6,3,1)
a2 <- c("짬뽕","짜장면","짬뽕","짬뽕","짜장면")
a3 <- c(3.62, 5.45, 2.54, 3.67, 7.23)
DF<-data.frame(a1,a2,a3)
DF
# a1 a2 a3
#1 5 짬뽕 3.62
#2 3 짜장면 5.45
#3 6 짬뽕 2.54
#4 3 짬뽕 3.67
#5 1 짜장면 7.23
R
복사
data.frame 인자안에는 벡터들을 , 로 구분해서 넣어주면 된다. 이때, 유의할 점은 벡터들의 길이(원소 개수)가 반드시 같아야만 한다.
이제, 변수명을 바꿔보자.
DF<-data.frame(count=a1, food=a2, meanCount=a3)
DF
# count food meanCount
#1 5 짬뽕 3.62
#2 3 짜장면 5.45
#3 6 짬뽕 2.54
#4 3 짬뽕 3.67
#5 1 짜장면 7.23
R
복사
외부에서 가져오는 데이터표를 데이터프레임에 넣어 다루는 방법을 배워보자.
DF<-read.csv("R까기2_예제파일_전체/example_studentlist.csv")
R
복사
변수가 벡터인지 확인해보자.
is.vector(DF$height)
#[1] TRUE
R
복사
먼저, 데이터를 불러오면 제일 먼저 데이터 구조를 살펴본다. str() 함수를 이용한다.
str(DF)
#'data.frame': 17 obs. of 8 variables:
# $ name : chr "김길동" "이미린" "홍길동" "김철수" ...
# $ sex : chr "남자" "여자" "남자" "남자" ...
# $ age : int 23 22 24 23 20 21 22 23 23 22 ...
# $ grade : int 3 2 4 3 1 2 1 1 3 2 ...
# $ absence : chr "유" "무" "무" "무" ...
# $ bloodtype: chr "O" "AB" "B" "AB" ...
# $ height : num 165 170 175 182 168 ...
# $ weight : num 68.2 53 80.1 85.7 49.5 52 45.3 55 64.2 61.3 ...
R
복사
변수선택하기
DF$height # 이름으로 선택하거나
DF[[7]] # 변수의 열 위치로 선택하거나, 벡터로 가져오려면 [[]] 로 가져와야 한다.
#[1] 165.3 170.1 175.0 182.1 168.0 162.0 155.2 176.9 178.5 176.1 167.1 180.0 162.2 176.1 158.2
#[16] 168.6 169.2
R
복사
DF[7]
height
1 165.3
2 170.1
3 175.0
4 182.1
5 168.0
6 162.0
7 155.2
8 176.9
9 178.5
10 176.1
11 167.1
12 180.0
13 162.2
14 176.1
15 158.2
16 168.6
17 169.2
R
복사
DF[[7]] 과 DF[7] 의 차이를 좀 더 보자면 class() 함수를 보자.
class(DF[[[7]])
# [1] "numeric"
class(DF[7])
# [1] "data.frame"
R
복사
[[ ]] 를 사용하면서 한 단계 더 들어가 값 자체를 가져온다는 사실을 알 수 있다.
이번에는 여러 개 변수를 선택하는 방법을 배워보자.
DF<-read.csv("R까기2_예제파일_전체/example_studentlist.csv")
R
복사
변수의 열 위치 값으로 여러 변수 선택하기 (c() 사용)
DF[c(6,7)] # 데이터프레임으로
bloodtype height
1 O 165.3
2 AB 170.1
3 B 175.0
4 AB 182.1
5 A 168.0
6 O 162.0
7 O 155.2
8 A 176.9
9 B 178.5
10 B 176.1
11 O 167.1
12 AB 180.0
13 A 162.2
14 O 176.1
15 B 158.2
16 B 168.6
17 A 169.2
R
복사
물론 변수명으로도 여러 개 선택가능하다.
DF[c("bloodtype","height")]
bloodtype height
1 O 165.3
2 AB 170.1
3 B 175.0
4 AB 182.1
5 A 168.0
6 O 162.0
7 O 155.2
8 A 176.9
9 B 178.5
10 B 176.1
11 O 167.1
12 AB 180.0
13 A 162.2
14 O 176.1
15 B 158.2
16 B 168.6
17 A 169.2
R
복사
행렬 방식으로 선택할 수도 있다. (이때 반환값은 벡터다)
DF[,7] # 콤마 앞은 행, 콤마 뒤는 열
#[1] 165.3 170.1 175.0 182.1 168.0 162.0 155.2 176.9 178.5 176.1 167.1 180.0 162.2 176.1 158.2
#[16] 168.6 169.2
DF[2,] # 2행 전체 선택
# name sex age grade absence bloodtype height weight
#2 이미린 여자 22 2 무 AB 170.1 53
DF[2,1] # 한 데이터 값을 추출
# [1] "이미린"
R
복사
물론, 한 데이터값을 추출할 때 행렬방식에 이름을 넣어서도 가능하다.
DF[,"height"] # height 열 모두 추출
#[1] 165.3 170.1 175.0 182.1 168.0 162.0 155.2 176.9 178.5 176.1 167.1 180.0 162.2 176.1 158.2
#[16] 168.6 169.2
R
복사
참고로, 행렬로 추출할 때 하나가 아니라 여러 행이나 여러 열을 불러오게 되면 반환값이 벡터가 아니라 데이터프레임이 된다.
DF[,c(6,7)] # 6, 7 열 추출
bloodtype height
1 O 165.3
2 AB 170.1
3 B 175.0
4 AB 182.1
5 A 168.0
6 O 162.0
7 O 155.2
8 A 176.9
9 B 178.5
10 B 176.1
11 O 167.1
12 AB 180.0
13 A 162.2
14 O 176.1
15 B 158.2
16 B 168.6
17 A 169.2
class(DF[,c(6,7)])
# [1] "data.frame"
class(DF[,7])
# [1] "numeric"
R
복사
이번에는 좀 더 쉽게 변수를 선택하는 방법을 배우겠다. 매번 ‘DF$변수이름’ 보다 ‘변수이름’ 으로 다루는 것이 편할 것이다.
DF<-read.csv("R까기2_예제파일_전체/example_studentlist.csv")
attach(DF) # attach를 하게 되면 변수이름만 따로 이용할 수 있다.
R
복사
height
#[1] 165.3 170.1 175.0 182.1 168.0 162.0 155.2 176.9 178.5 176.1 167.1 180.0 162.2 176.1 158.2
#[16] 168.6 169.2
R
복사
이때, 유의할 점은 변수의 이름이 겹치는 다른 객체가 있는지 살펴봐야 한다. 또한, 이때 변수 height는 이제 DF와 상관없는 별도 객체가 된 것이다.
height[1]<-NA # height의 첫번째 값을 NA 로 변경했을 때
DF # DF 값에도 변화가 생기는지 확인
name sex age grade absence bloodtype height weight
1 김길동 남자 23 3 유 O 165.3 68.2
2 이미린 여자 22 2 무 AB 170.1 53.0
3 홍길동 남자 24 4 무 B 175.0 80.1
4 김철수 남자 23 3 무 AB 182.1 85.7
5 손세수 여자 20 1 유 A 168.0 49.5
6 박미희 여자 21 2 무 O 162.0 52.0
7 강수친 여자 22 1 무 O 155.2 45.3
8 이희수 여자 23 1 무 A 176.9 55.0
9 이철린 남자 23 3 무 B 178.5 64.2
10 방희철 남자 22 2 무 B 176.1 61.3
11 박수호 남자 24 4 유 O 167.1 62.0
12 임동민 남자 22 2 무 AB 180.0 75.8
13 김민수 남자 21 1 무 A 162.2 55.3
14 이희진 여자 23 3 무 O 176.1 53.1
15 김미진 여자 22 2 무 B 158.2 45.2
16 김동수 남자 24 4 유 B 168.6 70.2
17 여수근 남자 21 1 무 A 169.2 62.2
R
복사
attach 하고 난 뒤의 변수는 데이터프레임과 별개인 객체가 된다. 따라서 데이터프레임 내에서는 변화가 반영되지 않는다.
객체를 만들면 객체를 모아두는 .GlobalEnv 가 있다. 데이터프레임같은 객체를 만들게 되면 이름만 .GlobalEnv에 올려두고 Environment라는 공간에 그 데이터프레임의 벡터들을 따로 저장해둔다. 따라서 만약 DF$height라고 했을 때 DF는 Environment에 있는 height에 접근한 것이 된다. 즉 이때의 height는 .GlobalEnv가 아닌 별도의 공간에 있는 것이다.
ls() 함수에 Environment 객체를 넣어주면 그 공간에 있는 객체들의 목록을 보여준다.
ls(DF) # DF 라는 Environment 공간에 있는 객체 목록
#[1] "absence" "age" "bloodtype" "grade" "height" "name" "sex"
#[8] "weight"
R
복사
하지만, 매번 이렇게 부르기 귀찮아서 R은 ‘검색 목록’이라는 특이한 공간을 만들었다. 이 공간을 보려면 search() 함수를 사용한다.
search()
#[1] ".GlobalEnv" "DF" "tools:rstudio" "package:stats"
# [5] "package:graphics" "package:grDevices" "package:utils" "package:datasets"
# [9] "package:methods" "Autoloads" "package:base"
R
복사
이 검색목록에는 다운로드한 패키지들, attach() 하고 난 뒤 모두 이 공간에 오게 된다. 참고로, 같은 객체를 여러 번 넣을 수도 있고 같은 객체명이 있다면 이를 알려준다.
attach()의 반대는 detach()다.
detach(DF)
search()
#[1] ".GlobalEnv" "tools:rstudio" "package:stats" "package:graphics"
# [5] "package:grDevices" "package:utils" "package:datasets" "package:methods"
# [9] "Autoloads" "package:base"
R
복사
참고로, 특정 검색목록 위치에 위치시키고 싶다면 pos인자를 사용한다.
DF2<-DF
attach(DF2,pos=6)
#The following object is masked _by_ .GlobalEnv:
# height
#The following objects are masked from DF2:
# absence, age, bloodtype, grade, height, name, sex, weight
search()
#[1] ".GlobalEnv" "DF" "tools:rstudio" "package:stats"
# [5] "package:graphics" "package:grDevices" "DF2" "package:utils"
# [9] "package:datasets" "package:methods" "Autoloads" "package:base"
R
복사
물론 앞서 말했듯이, library() 혹은 require()로 패키지를 불러도 검색목록에 올라온다.
library(rgl)
search()
#[1] ".GlobalEnv" "package:rgl" "DF" "tools:rstudio"
# [5] "package:stats" "package:graphics" "package:grDevices" "DF2"
# [9] "package:utils" "package:datasets" "package:methods" "Autoloads"
#[13] "package:base"
R
복사
그렇다면 로드한 패키지를 언로드하려면
detach(package:rgl)
search()
#[1] ".GlobalEnv" "DF" "tools:rstudio" "package:stats"
# [5] "package:graphics" "package:grDevices" "DF2" "package:utils"
# [9] "package:datasets" "package:methods" "Autoloads" "package:base"
R
복사
detach()를 사용해서 DF와 DF2를 검색목록에서 지우자.
detach(DF)
detach(DF2)
R
복사
리스트 모든 항목에 동일한 함수 적용하기
•
split() : 명목형 변수 기준으로 데이터를 나눠준다. 결과는 리스트
split(데이터, 나눌 명목형 변수 기준)
HeightBySex<-split(DF$height,DF$sex)
HeightBySex
$남자
[1] 165.3 175.0 182.1 178.5 176.1 167.1 180.0 162.2 168.6 169.2
$여자
[1] 170.1 168.0 162.0 155.2 176.9 176.1 158.2
R
복사
이제, 리스트 항목별 평균을 구해보자.
mean(HeightBySex[[1]])
mean(HeightBySex[[2]])
# 귀찮으니까 한꺼번에
sapply(HeightBySex,mean)
남자 여자
172.4100 166.6429
sapply(HeightBySex,sd)
남자 여자
6.804647 8.487414
sapply(HeightBySex, range) #범위는 행렬로 바꿔서 반환해준다.
남자 여자
[1,] 162.2 155.2
[2,] 182.1 176.9
R
복사
sapply 는 어떤 리스트 객체에 동일한 함수를 실행할 수 있게 해주는 좋은 함수다.
명목형 변수로 ‘도수분포표’ 만들기
table함수를 사용하면 명목형 변수의 항목의 개수를 셀 수 있다. 결과는 table객체로 반환받는다.
# 먼저 빈도수를 구한다.
Freq<-table(DF$bloodtype)
Freq
#A AB B O
# 4 3 5 5
R
복사
상대도수는 비슷하게 prop.table() 를 사용한다. 단, 인자는 table 객체
RelativeFreq<-prop.table(Freq)
RelativeFreq
#A AB B O
#0.2352941 0.1764706 0.2941176 0.2941176
R
복사
Table<-rbind(Freq,RelativeFreq)
Table
#A AB B O
#Freq 4.0000000 3.0000000 5.0000000 5.0000000
#RelativeFreq 0.2352941 0.1764706 0.2941176 0.2941176
R
복사
합(SUM)이 없으니까 합을 붙여보겠다. addmargins() 함수를 사용한다.
Table<-addmargins(Table,margin=2)
Table
# A AB B O Sum
#Freq 4.0000000 3.0000000 5.0000000 5.0000000 17
#RelativeFreq 0.2352941 0.1764706 0.2941176 0.2941176 1
R
복사
•
addmargins() : 합을 구해주는 함수
addmargins(테이블객체, margin=합구하는방식)
margin을 생략 → 행과 열의 합 모두 계산
margin=1 → 열의 합 계산
margin=2 → 행의 합 계산
R에서 연속형 변수를 ‘도수분포표’로 만들기
연속형 변수를 도수분포표로 만들려면 계급이 필요하다. DF의 height변수에 대해서 구간을 나눠보겠다.
FactorOfHeight<-cut(DF$height,breaks=4) # 구간 나누기 4개로
FactorOfHeight
#[1] (162,169] (169,175] (169,175] (175,182] (162,169] (162,169] (155,162] (175,182] (175,182]
#[10] (175,182] (162,169] (175,182] (162,169] (175,182] (155,162] (162,169] (169,175]
#Levels: (155,162] (162,169] (169,175] (175,182]
R
복사
•
cut() : 수치형 데이터를 구간으로 나누는 함수
cut(나눌변수, breaks=나누고 싶은 구간의 개수, labels=나눈 구간의 이름)
구간을 나눴으니 이제 table함수를 사용해서 빈도를 구해보자.
FreqOfHeight<-table(FactorOfHeight)
FreqOfHeight
#(155,162] (162,169] (169,175] (175,182]
# 2 6 3 6
# 상대도수도 추가한다.
FreqOfHeight<-rbind(FreqOfHeight,prop.table(FreqOfHeight))
FreqOfHeight
# (155,162] (162,169] (169,175] (175,182]
#FreqOfHeight 2.0000000 6.0000000 3.0000000 6.0000000
# 0.1176471 0.3529412 0.1764706 0.3529412
# 상대도수에 이름 추가해주자.
rownames(FreqOfHeight)[2]<-"RelativeFreq"
FreqOfHeight
# (155,162] (162,169] (169,175] (175,182]
#FreqOfHeight 2.0000000 6.0000000 3.0000000 6.0000000
#RelativeFreq 0.1176471 0.3529412 0.1764706 0.3529412
# 연속형 변수니까 누적상대도수도 추가해주자. cumsum()함수를 사용한다.
CumuFreq<-cumsum(FreqOfHeight[2,])
CumuFreq
#(155,162] (162,169] (169,175] (175,182]
# 0.1176471 0.4705882 0.6470588 1.0000000
FreqOfHeight<-rbind(FreqOfHeight,CumuFreq)
# (155,162] (162,169] (169,175] (175,182]
#FreqOfHeight 2.0000000 6.0000000 3.0000000 6.0000000
#RelativeFreq 0.1176471 0.3529412 0.1764706 0.3529412
#CumuFreq 0.1176471 0.4705882 0.6470588 1.0000000
# 이름을 보기 좋게 한글로 바꿔보자.
rownames(FreqOfHeight)<-c("도수","상대도수","누적상대도수")
# (155,162] (162,169] (169,175] (175,182]
#도수 2.0000000 6.0000000 3.0000000 6.0000000
#상대도수 0.1176471 0.3529412 0.1764706 0.3529412
#누적상대도수 0.1176471 0.4705882 0.6470588 1.0000000
# 마지막으로 합을 구해 추가해준다.
FreqOfHeight<-addmargins(FreqOfHeight,margin=2)
FreqOfHeight
# (155,162] (162,169] (169,175] (175,182] Sum
#도수 2.0000000 6.0000000 3.0000000 6.0000000 17.000000
#상대도수 0.1176471 0.3529412 0.1764706 0.3529412 1.000000
#누적상대도수 0.1176471 0.4705882 0.6470588 1.0000000 2.235294
R
복사