잠시동안 배운 R
어쩌다 R 프로그래밍 언어를 배울 기회가 있었는데, 새로운 언어를 익히는 건 재미있었지만 너무 수학적인 언어라 다시 쓸일이 있을까 싶은 생각이 든다. 여하간 이번에 배운 R 프로그래밍 기본 문법을 블로그에 정리해 둘 생각이다.
1. 변수의 이름
변수의 이름에는 .
_
등이 올 수 있다. .
은 먼저 사용할 수 있지만 _
는 먼저올 수 없다.
a... = 0 (o)
a___ = 0 (o)
.a = 0 (o)
_a = 0 (x)
2. 대입 연산자
C언어에서는 변수에 값을 넣는 대입연산자로 =
을 사용한다. R에서도 =
을 사용하지만 추가적으로 <-
도 사용할 수 있다.
a = 1
b <- 1
3. 문자열
문자열은 파이썬과 문법이 매우 흡사하다. 따옴표는 작은따옴표 큰따옴표 구분하여 사용하지 않고 짝만 맞추면 된다.
a <- 'Hello World'
a <- "Hello World"
a <- "He said 'Hello World'"
4. 불리언
불리언 값은 TRUE
또는 T
, FALSE
또는 F
로 표시된다. 불리언 값과 같이 쓰이는 특수문자는 &(AND), |(OR), !(NOT) 등등이 있다.
> T & F
[1] FALSE
> T | F
[1] TRUE
> !TRUE
[1] FALSE
5. 벡터
R 프로그래밍에선 변수(?)는 스칼라, 배열(?)은 벡터로 불리운다. c()
함수를 통해서 스칼라값을 벡터로 묶을 수 있다.
> a = c(1,2,3)
[1] 1 2 3
> a = c(1,2,3,c(4,5,6))
[1] 1 2 3 4 5 6
> a = c(c(1,2,3),c(4,5,6))
[1] 1 2 3 4 5 6
벡터에 접근하는 방법은 벡터의 인덱스를 불러오는 것이다. 대부분의 프로그래밍 언어는 배열의 시작이 [0]부터지만 R 에서는 [1]부터 시작이다.
> a[1]
[1] 1
> a[c(1,3)]
[1] 1 3
6. 펙터
변주형 변수, 카테고리를 지정할 수 있는 요소다. 이것은 데이터 프레임을 다룰때 주로 사용되었다.
> sex <- factor(c("M","F"))
> levels(sex)
[1] "F" "M"
> print(sex)
[1] M F
Levels: F M
7. 벡터의 길이
벡터의 길이를 파악하는 함수는 nrow
, NROW
, length
가 있다. nrow
함수는 행렬의 길이만 알아낼 수 있다. 나머지 두개는 벡터도 가능.
> x <- c("a","b","c")
> length(x)
[1] 3
> nrow(x)
NULL
> NROW(x)
[1] 3
8-1. 조건 연산
스칼라 혹은 벡터에 대한 조건의 결과를 얻는 방법이다.
> x <- c(11,12,13,14,19,20)
> x > 15
[1] FALSE FALSE FALSE FALSE TRUE TRUE
벡터 x의 값과 15를 비교하여 하나의 벡터값이 만들어졌다. 이 벡터를 x의 인덱스 값으로 넣으면
> x[x>15]
[1] 19 20
벡터 x의 값에서 15보다 큰 값을 추출할 수 있다.
> which(x>15)
[1] 5 6
> which(x==9)
integer(0)
which
함수를 사용하면 조건을 충족하는 값의 위치를 알아낼 수 있다.
> x[which(x>15)]
[1] 19 20
> x[x>15]
[1] 19 20
이 처럼 같은 결과를 출력한다.
8-2. 조건 연산
벡터에서 같은 문자값이 있는지 확인하는 방법은 다음과 같다.
> "a" %in% c("a","b","c")
[1] TRUE
> "d" %in% c("a","b","c")
[1] FALSE
9. 시퀀스
1부터 100까지 들어간 혹은 규칙있는 벡터값을 생성하기 위해선 시퀀스라는 함수를 사용한다.
> seq(1,5)
[1] 1 2 3 4 5
> seq(1,5,2)
[1] 1 3 5
> seq(0,100,5)
[1] 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90
[20] 95 100
이처럼 작성되며 seq(시작 값, 종료 값, 순서)
로 표현한다.
> rep(1:2,5)
[1] 1 2 1 2 1 2 1 2 1 2
> rep(1:2,each=5)
[1] 1 1 1 1 1 2 2 2 2 2
rep
함수를 사용하면 시퀀스 함수와는 약간 다른 모양의 벡터 생성이 가능하다.
10. 행렬
행렬은 행의 갯수를 선택하여 생성하거나 열의 갯수를 선택하여 생성할 수 있다. 말로 쓰기 어려우니 다음 코드를 보자.
> matrix(c(0,1,2,3,4,5,6,7,8,9),nrow=2)
[,1] [,2] [,3] [,4] [,5]
[1,] 0 2 4 6 8
[2,] 1 3 5 7 9
> matrix(c(0,1,2,3,4,5,6,7,8,9),ncol=2)
[,1] [,2]
[1,] 0 5
[2,] 1 6
[3,] 2 7
[4,] 3 8
[5,] 4 9
이처럼 같은 값으로 만든 행렬이지만 행이 2개냐 열이 2개냐의 차이로 모양이 확연히 달라졌다.
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
> matrix(c(1,2,3,4,5,6,7,8,9),ncol=3, byrow=T)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
[3,] 7 8 9
또 기본은 세로(열) 우선으로 값이 채워져 나가지만 byrow
을 통해서 가로(행) 우선으로 값을 채울 수 있다.
> our.mat <- matrix(c(1,2,3,4,5,6,7,8,9),nrow=3,dimnames = list(c("item1","item2","item3"),c("feature1","feature2","feature3")))
> our.mat
feature1 feature2 feature3
item1 1 4 7
item2 2 5 8
item3 3 6 9
위와같이 각행렬의 이름을 지정해 줄 수도 있다.
행렬에 접근하는 방법은 벡터와 유사하며 2차원 배열에 접근하듯 하면된다. our.mat에 접근해 보도록 하자.
# our.mat[row,col]
> our.mat[1,]
feature1 feature2 feature3
1 4 7
> our.mat[1,c(1,2)]
feature1 feature2
1 4
> our.mat[!our.mat[,1]==2,]
feature1 feature2 feature3
item1 1 4 7
item3 3 6 9
> our.mat["item1",]
feature1 feature2 feature3
1 4 7
our.mat[!our.map[,1]==2],
의 경우 1열이 2가 아닌 행을 뽑아내므로 결과는 1,3행이 출력된다. 또한 our.mat["item1",]
처럼 행과 열의 이름으로 행열을 뽑아내는 것도 가능하다.
이번엔 행렬의 연산을 해보자.
> our.mat*our.mat
feature1 feature2 feature3
item1 1 16 49
item2 4 25 64
item3 9 36 81
> our.mat%*%our.mat
feature1 feature2 feature3
item1 30 66 102
item2 36 81 126
item3 42 96 150
기본적인 *
로 곱셈 연산을 실시하면 쓸데없이(?) 행렬의 각각의 자리에서 곱셈이 일어난다. 우리가 알고있는 일반적인 행렬의 곱셈을 실시하기 위해선 our.mat%*%our.mat
와 같이 작성해야 한다.
11. 데이터 프레임
R 프로그래밍에서 가장 중요한 데이터로 사용된다고 한다. 행렬은 숫자의 집합체임에 비해 데이터 프레임은 벡터, 펙터 등등이 모두 합쳐질 수 있기 때문인듯 하다.
> x=c(1,2,3,4,5)
> y=c(2,4,6,8,10)
> z=c('M','F','M','F','M')
> our.dataFrame <- data.frame(x,y,z)
colnames(our.dataFrame) <- c("number", "age", "gender")
rownames(our.dataFrame) <- c("a","b","c","d","e")
데이터 프레임의 생성은 위와같이 이루어지며 데이터 프레임의 구조를 확인하는 방법은 다음과 같다.
> str(our.dataFrame) #
'data.frame': 5 obs. of 3 variables:
$ x: num 1 2 3 4 5
$ y: num 2 4 6 8 10
$ z: Factor w/ 2 levels "F","M": 2 1 2 1 2
> head(our.dataFrame)
x y z
1 1 2 M
2 2 4 F
3 3 6 M
4 4 8 F
5 5 10 M
> View(our.dataFrame)
데이터 프레임의 접근 방법은 행렬과 비슷하지만 $ 특수문자를 통해서 벡터의 이름으로 열에 접근이 가능하다.
> our.dataFrame[1,]
x y z
1 1 2 M
> our.dataFrame$z
[1] M F M F M
Levels: F M
> our.dataFrame[our.dataFrame$z=="F",]
x y z
2 2 4 F
4 4 8 F
12. 합, 평균
R 프로그래밍에선 벡터의 합과 평균값을 구해주는 함수가 존재한다.
> sum(c(1,2,3))
[1] 6
> sum(c(1,2,3,NA))
[1] NA
> sum(c(1,2,3,NA),na.rm=T)
[1] 6
> mean(c(1,2,3))
[1] 2
> mean(c(1,2,3,NA),na.rm=T)
[1] 2
결측치(NA)가 있는 경우 원활한 계산이 불가하므로 na.rm
으로 결측치를 모두 제거해야 한다.
13. 조건문
조건문을 작성하는 방법은 C언어와 아주 유사하다.
x <- 1
if(x>3) {
print("TRUE")
} else {
print("FALSE")
}
하지만 유의해야 할 점은 if문의 닫히는 중괄호 바로 옆에 else가 (이어지도록)와야한다. 한줄씩 코드가 실행되서 그런것 같다.
14. 반복문
마지막으로 반복문은 for
, while
이 존재하며 문법은 자바스크립트 ES6
스럽다.
# [ FOR ]
for(i in 1:10) {
print(i)
}
# [ WHILE ]
i <- 0
while(i<10) {
print(i)
i <- i+1
}
R 프로그래밍에선 딱히 반복문을 사용할 일이 적었다. 단기간으로 배워서 그런지도 모르겠다. 유일하게 사용했던 이유는 벡터값을 전부 뒤집기 위해서였다.
a <- NULL
for(i in 1:length(airquality$Ozone)) {
a[i] <- airquality$Ozone[length(airquality$Ozone)-(i-1)]
}
for(i in 1:length(airquality$Ozone)) {
print(a[i])
}
Ghost