자료 구조

(1)

(2)


스칼라(scalar)

스칼라는 하나의 값만 포함하는 변수를 말합니다. 이전 글에서 생성 및 변수 할당 등을 다뤘으니 이름만 알고 갑시다.



벡터 (vector)

벡터(vector)는 1차원의 자료 구조로 하나의 데이터 타입만 허용합니다. 벡터를 생성하면서 데이터 타입 관련해서도 봅시다.

  1. 벡터의 생성
v1 <- c(1,2,3) ; v1
[1] 1 2 3
v2 <- c('a',1) ; v2
[1] "a" "1"
v3 <- 1:10 ; v3
[1]  1  2  3  4  5  6  7  8  9 10

벡터 ​v2를 만드는 것을 보면 두 번째에 넣은 1이 앞에 넣은 ‘a’ 때문에 문자로 바뀐 것을 알 수 있습니다.


  1. 벡터의 확장

c를 이용하면 벡터의 맨 앞자리나 뒷 자리에 추가가 가능합니다.

> c(v1,4)
[1] 1 2 3 4
> c(4,v1)
[1] 4 1 2 3

그리고 append 함수를 쓰면 양 끝 외에 원하는 위치에 원소를 추가가 가능합니다.

append(x = v1 , values = 4, after = 2)
[1] 1 2 4 3


  1. 벡터의 연산

3-1) 산술 연산

R에서는 벡터끼리 연산을 할 때 각 원소끼리의 연산이 이루어집니다. 즉, Python과는 달리 연산자 만으로 간단하게 벡터 연산이 가능합니다.

> v1 + 1
[1] 2 3 4

> v4 <- c(10,20,30)
> v5 <- c(10,20,30,40)
> v1 + v4
[1] 11 22 33
# 크기가 달라도 연산 가능
> v1 + v5
[1] 11 22 33 41
경고메시지(): 
In v1 + v5 :  객체의 길이가 서로 배수관계에 있지 않습니다

결과문을 보면 v5는 길이가 4인데 마지막 40에 1이 더해진 것을 볼 수 있습니다. 길이가 다른 벡터끼리 연산하는 경우 길이가 짧은 쪽의 원소를 반복시킴으로서 해결합니다. 이 경우에는 v1이 1, 2, 3 까지 모든 원소가 사용되었기 때문에 다시 첫 번째 원소인 1이 재사용된것입니다.


3-2) 논리 연산

# 1. and 연산자 : &
> T & T
[1] TRUE
> T & F
[1] FALSE
> F & F
[1] FALSE

# 2. or 연산자 : |
> T | T
[1] TRUE
> T | F
[1] TRUE
> F | F
[1] FALSE

# 3. not 연산자 : !
> !(v1 > 1)
    a     b     c 
 TRUE FALSE FALSE 
> v1 !=1
    a     b     c 
FALSE  TRUE  TRUE 


3-3) 집합 연산자

t1 <- c('a','b','c','d')
t2 <- c('a','e','f')
t3 <- c('a','e','e','f')

# 1) 합집합 : union
union(t1,t2)
[1] "a" "b" "c" "d" "e" "f"

# 2) 교집합 : intersect
intersect(t1,t2)
[1] "a"

# 3) 차집합 : setdiff
setdiff(t1,t2)
[1] "b" "c" "d"

# 4) 동등비교 : identical, setequal
# identical : 구성하는 원소, 크기가 모두 같은지 확인
identical(t2,t3)
[1] FALSE

# setequal : 구성하는 원소가 같은지 확인(크기 상관x)
setequal(t2,t3)
[1] TRUE
  1. 백터의 색인 (indexing, 추출)

벡터에서의 색인은 변수옆에 대괄호를 입력 후 원하는 위치값(인덱스)을 입력하면 됩니다. 대괄호 내에서 콤마(,)는 차원을 구분하기 때문에 색인 시에도 여러 원소를 출력하고 싶을 때는 c로 위치값들을 묶어줘야합니다. ​ 4-1) 위치값(숫자)

> v1[2]    
[1] 2
> v1[1,3] 
Error in v1[1, 3] : incorrect number of dimensions
> v1[c(1,3)]
[1] 1 3
> v1[-1] 
[1] 2 3

위치값으로 색인 시 주의해야 할 점이 있습니다. 대부분의 프로그래밍 언어들은 시작 위치값이 0인데 R의 경우 1부터 시작합니다. 그래서 2번째 값을 출력하고 싶을때는 v1[1]이 아니라 v1[2]가 됩니다.


4-2) 인덱스 이름

벡터에 각 원소별로 이름을 부여할 수 있습니다. 이름을 부여하면 위치값 대신에 이름을 입력하면 해당 위치의 값을 출력할 수 있습니다.

> names(v1)
NULL
> names(v1) <- c('a','b','c')
> v1
a b c 
1 2 3 

> v1[c('a','b')]
a b 
1 2 

4-3) 슬라이스 색인(연속추출)

# 숫자 색인
> v5[1:2]
[1] 10 20

# 이름으로 색인
> v1['b':'c']
Error in "b":"c" : 인자의 값이 NA/NaN 입니다.
추가정보: 경고메시지(): 
1: 강제형변환에 의해 생성된 NA 입니다 
2: 강제형변환에 의해 생성된 NA 입니다

슬라이스 색인에서도 인덱스 이름은 문자이기 떄문에 사용이 불가능합니다. 그리고 또 조심해야할 부분이 있는데 python의 경우 1:3일때 2번째부터 3번째까지를 의미하지만 R에서는 1번째부터 3번째까지를 의미합니다. 프로그래밍에 익숙한 사람은 R을 다룰 때 헷갈릴 수 있습니다.

  1. 벡터 수정
> v1[2] <- 20; v1
 a  b  c 
 1 20  3
 
> v2[2:5] <- seq(20,50,10);v2
[1] "a"  "20" "30" "40" "50"

# [참고] 벡터의 원소에 NULL 할당 불가
v1[2] <- NULL
Error in v1[2] <- NULL : replacement has length zero
  1. 벡터 크기 확인
# 1차원인 벡터의 크기 확인
length(v1)

# 행의 개수, 1차원일경우에는 원소의 갯수
NROW(v1) 



리스트(list))

리스트(List)는 layer(층)을 가지는 자료 구조입니다. key-value 구조이며 value 내부는 벡터로 구성되어 있고, 동일한 데이터 타입만 가능합니다.

1. 리스트 생성

> list('a' = 1, 'b' = 2, 'c' = 3)
$a
[1] 1

$b
[1] 2

$c
[1] 3

l2<-list('a' = c(1,2), 'b' = c(2,3,4), 'c' = 'a') ; l2
$a
[1] 1 2

$b
[1] 2 3 4

$c
[1] "a"

2. 색인

# 키 색인, 벡터로 리턴
l2$a  
[1] 1 2

# 리스트로 리턴
l2['a']
$a
[1] 1 2

# 1층 추출, 리스트로 리턴
l2[1]
$a
[1] 1 2

# 1층 추출, 벡터로 리턴
l2[[1]] 
[1] 1 2

3. 수정

#  key 추가
l2$d <- c(1,5,7); l2
$a
[1] 1 2

$b
[1] 2 3 4

$c
[1] "a"

$d
[1] 1 5 7

# key 제거
l2$d <- NULL; l2   
$a
[1] 1 2

$b
[1] 2 3 4

$c
[1] "a"

# key 내용 수정
l2$b[l2$b == 3] <- 40; 2$b
[1]  2 40  4