dh_0e

[R Lang] R 데이터 구조 (Matrix, Array, List, Factor) 본문

R

[R Lang] R 데이터 구조 (Matrix, Array, List, Factor)

dh_0e 2025. 10. 17. 02:34

주요 데이터 구조

  • 벡터(Vector): 개별 데이터나 가중치 등 1차원의 동일한 자료형 데이터를 저장함
  • 행렬(Matrix): 선형대수 기반 모델 계산에 활용되는 2차원의 동일한 자료형 데이터를 직사각형 형태로 배열함
  • 배열(Array): 시계열, 이미지 등 다차원 데이터를 저장하며, 행렬의 2차원 이상 확장된 형태 (마찬가지로 동일한 자료형을 가짐)
  • 리스트(List): 모델 결과와 다양한 객체를 저장하며, 서로 다른 유형의 데이터 객체들을 한데 모을 수 있는 유연한 구조 (1차원)
  • 데이터프레임(Dataframe): 가장 일반적인 머신러닝 데이터셋 형식으로, 2차원 구조를 가지며 열마다 서로 다른 자료형을 포함할 수 있음 
  • 요인(Factor): 범주형 데이터를 표현하며 통계 분석과 머신러닝에서 중요한 역할을 함

 

행렬(Matrix)

  • 동일한 데이터 유형의 자료들로 구성된 2차원 형태의 자료 구조
  • 선형 변환: 행렬을 사용하여 회전, 확대, 축소 등의 선형 변환을 간결하게 나타낼 수 있음
  • matrix(매트릭스에 저장될 값, nrow=행의 수, ncol=열의 수) 함수를 사용하여 생성
M <- matrix(1:6, nrow=2, ncol=3) # 1부터 6까지 숫자로 2행 3열 행렬 생성
#     [,1] [,2] [,3]
# [1,]    1    3    5
# [2,]    2    4    6
  • byrow=TRUE 인수를 사용하면 값을 행 방향으로 채울 수 있음
z2 <- matrix(1:20, nrow=4, ncol=5, byrow=T)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]    1    2    3    4    5
# [2,]    6    7    8    9   10
# [3,]   11   12   13   14   15
# [4,]   16   17   18   19   20

matrix(c(20:40), ncol=4, nrow=9, byrow=T)    # 값이 초과되면 다시 범위 처음부터
#       [,1] [,2] [,3] [,4]
#  [1,]   20   21   22   23
#  [2,]   24   25   26   27
#  [3,]   28   29   30   31
#  [4,]   32   33   34   35
#  [5,]   36   37   38   39
#  [6,]   40   20   21   22
#  [7,]   23   24   25   26
#  [8,]   27   28   29   30
#  [9,]   31   32   33   34
  • 행렬 결합
    • cbind(): 열(column) 방향으로 벡터 또는 행렬 결합
    • rbind(): 행(row) 방향으로 벡터 또는 행렬 결합
x <- 1:4
y <- 5:8
m1 <- cbind(x,y) # x와 y를 열 방향으로 결합
#      x y
# [1,] 1 5
# [2,] 2 6
# [3,] 3 7
# [4,] 4 8
m2 <- rbind(x,y) # x와 y를 행 방향으로 결합
#   [,1] [,2] [,3] [,4]
# x    1    2    3    4
# y    5    6    7    8
  • 행렬값 추출
    • 인덱스 값을 이용하여 특정 위치의 값 추출 (2차원 인덱스 사용: [행, 열])
z <- matrix(1:20, nrow=4, ncol=5)
z[2,3]   # 2행 3열에 있는 값
z[2,]    # 2행에 있는 모든 값
z[,4]    # 4열에 있는 모든 값
z[2, 1:3] # 2행의 값 중 1~3열에 있는 값
z[1, c(1,2,4)] # 1행의 값 중 1, 2, 4열에 있는 값
  • 행과 열에 이름 지정 후 이름으로 값 추출 가능
score <- matrix(c(90,85,69,78, 85,96,49,95, 90,80,70,60), nrow=4, ncol=3)
rownames(score) <- c('John','Tom','Mark','Jane')
colnames(score) <- c('English','Math','Science')
score['John','Math'] # John의 수학 성적
score['Tom',c('Math','Science')] # Tom의 수학, 과학 성적

 

R 행렬 연산

  • 행렬 곱: A %*% B
  • 전치 행렬: t(A)
  • 역행렬: solve(A)
  • 행렬식: det(A)
A <- matrix(c(1,3,4,2,5,1,4,2,3), nrow=3)
# 전치 행렬
t(A)
# 역행렬
solve(A)
# 행렬식
det(A)
# A행렬 * 역행렬
A %*% solve(A) # 항등행렬

 

행렬의 중요성

  1. 데이터 표현의 효율성: 큰 데이터셋을 벡터화/행렬화하면 반복문보다 훨씬 빠름
  2. 수학적 기초: 회귀 분석, PCA, 딥러닝 등 대부분의 알고리즘은 선형대수 기반이므로 행렬 없이는 구현 불가능
  3. 연산 최적화: R은 BLAS/LAPACK 같은 고성능 선형대수 라이브러리를 이용하여 행렬 연산을 최적화하여 대규모 데이터 분석에 필수적임
  4. 이론과 실무의 연결고리: 머신러닝/통계 이론은 수학적으로, R 구현은 행렬 연산을 통해 직접적으로 연결

 

배열(Array)

  • 행렬과 동일하지만 2차원 이상의 항목을 가짐
    • 행렬은 2차원 배열의 특수한 형태 (2차원에 한정된 array지만 선형대수 연산 지원)
구분 matrix (행렬) array (배열)
차원 수 2차원 고정 1차원 ~ n차원 (2, 3, 4차원 가능)
저장 타입 하나의 자료형만 가능 하나의 자료형만 가능
생성 방식 matrix(data, nrow, ncol) array(data, dim=c(...))
구조 속성 dim 길이가 항상 2 dim 길이가 2 이상
사용 목적 행렬 연산 중심 고차원 데이터 저장 중심
특수성 “2차원 배열 중에서도 행렬 연산이 정의된 구조” 일반적 다차원 저장 구조
  • array(배열에 들어갈 수, dim=배열 크기)
array(1:5, c(5)) # 벡터
array(1:6, c(2,3)) # 행렬
array(1:12, c(2,3,2)) # 2×3 행렬 × 2층
array(1:24, c(2,3,2,2)) # 2×3 행렬 × 2층 × 2블록
array(1:48, c(2,3,2,2,2)) # 2×3 행렬 × 2층 × 2블록 × 2세트
  • 배열 속성에 대한 함수:
    • length(): 포함하고 있는 요소의 개수
    • mode(): 요소의 자료 형태
    • dim(): 각 차원의 벡터 크기
    • dimnames(): 각 차원의 리스트 이름
x <- c(10, 20, 30, 40, 50)
length(x)
# [1] 5

y <- c("apple", "banana", "pear")
mode(y)
# [1] "character"

m <- matrix(1:6, nrow = 2, ncol = 3)
dim(m)
# [1] 2 3

m <- matrix(1:6, nrow = 2, ncol = 3)
dimnames(m) <- list(c("Row1", "Row2"), c("Col1", "Col2", "Col3"))
m
#       Col1 Col2 Col3
# Row1     1    3    5
# Row2     2    4    6

 

리스트(List)

  • 서로 다른 기본 자료형을 갖는 자료 구조들(벡터, 배열, 행렬, 심지어 다른 리스트, 데이터프레임 등)을 하나의 이름으로 모아놓은 형태의 자료 구조 (1차원 컨테이너)
  • 유연성: 데이터 프레임과 달리 모든 속성의 크기가 같을 필요가 없고, 자료형이나 데이터 길이가 달라도 됨
    • 데이터 프레임보다 넓은 의미의 데이터 모임으로 데이터베이스와 비슷
  • list() 함수를 이용하여 생성
L <- list(name="홍길동", score=c(90, 85, 88))
L$name
# [1] "홍길동"

L$score
# [1] 90 85 88

 

 R에서 리스트 값 추출

  • 리스트의 원소에 대한 인덱스를 표기할 때 [ ]가 아닌 [[ ]]를 사용
  • 이름이 있는 경우 $ 기호를 사용 가능
ds <- c(90, 85, 70, 84)
my.info <- list(name='Tom', age=60, status=TRUE, score=ds)

my.info[[1]]    # 리스트의 첫 번째 값 출력
# [1] "Tom"
my.info[1]      # 리스트의 첫 번째 데이터 출력
# $name
# [1] "Tom"

my.info$name    # 리스트에서 이름이 name인 값 출력
# [1] "Tom"

my.info[[4]]    # 리스트의 네 번째 값 출력
# [1] 90, 85, 70, 84

 

리스트 관련 유용한 함수

  • lapply(): 리스트에 함수를 적용하고 결과를 리스트 형태로 반환
  • sapply(): 리스트에 함수를 적용하고 결과를 벡터 또는 행렬 형태로 반환
  • tapply(): 입력 벡터를 요인 수준에 따라 함수 적용
  • mapply(): 사용할 함수의 입력이 여러 개인 경우 사용하며, sapply와 유사하게 리스트에 적용하여 결과를 반환
함수 이름 역할 예시
apply 행렬, 배열, 데이터프레임에 사용. 행/열 방향 함수 일괄 적용 apply(x,1,mean)
lapply 리스트에 적용. 결과를 리스트 형태로 반환 lapply(x,mean)
sapply 리스트에 적용. 결과를 행렬 형태로 반환 sapply(x,mean)
tapply 입력 벡터를, 요인 수준에 따라 함수 적용 tapply(vec,fac,mean)
mapply 사용할 함수의 input이 여러 개인 경우 사용. sapply와 유사 mapply(rep,times=4,li)
ds <- c(90, 85, 70, 84)
my.info <- list(name='Tom', age=60, status=TRUE, score=ds)

lapply(my.info, mean)     # 모든 원소에 대하여 평균을 리스트로 출력
# $name
# [1] NA     # 문자기 때문에 평균 NA

# $age
# [1] 60

# $status
# [1] 1      # TRUE 값은 1

# $score
# [1] 82.25

lapply(my.info$score, mean)   # score의 각 요소들을 리스트로 따로 평균으로 출력
# [[1]]
# [1] 90

# [[2]]
# [1] 85

# [[3]]
# [1] 70

# [[4]]
# [1] 84

sapply(my.info$score, mean)   # 벡터로 출력
# [1] 90 85 70 84

sapply(my.info[4], mean)      # 이렇게 해야 평균 나옴
# score 
# 82.25

 

요인(Factor)

  • 범주형 데이터를 숫자 대신 범주(levels)로 코드화한 자료 구조
  • 성별(남/여), 학년(1, 2학년), 지역 등과 같이 값의 종류가 정해져 있는 범주형 자료의 저장에 사용
  • factor() 함수를 이용하여 생성하며, 범주의 레벨은 levels 인수로 지정
bt <- c('A', 'B', 'B', 'O', 'AB', 'A')
bt.new <- factor(bt) # 팩터 bt.new 정의

bt
# [1] "A"  "B"  "B"  "O"  "AB" "A"

bt.new
# [1] A  B  B  O  AB A 
# Levels: A AB B O

bt.new <- factor(bt, levels=c('A', 'B', 'O')) # AB를 인수에서 제거
bt.new
# [1] A    B    B    O    <NA> A   # AB가 Not Available로 바뀜
# Levels: A B O                    # AB가 인수에서 사라짐

summary(bt.new)      # 성별별 사람 수 출력
#   A    B    O NA's 
#   2    2    1    1
  • 요인은 실질적으로 문자형 자료들도(A, B, O 등) 내부적으로는 숫자 벡터로 인식
  • summary(factor): factor의 범주별 개수를 출력
gender <- c(rep("male",20), rep("female", 30))
# 예: 20명의 "male(남성)"과 30명 "female(여성)"을 가지는 gender라는 변수

gender <- factor(gender)
# R은 gender를 nominal 변수로 처리. (내부적으로 1=female, 2=male)

summary(gender)
# female male
# 30 20
  • 데이터 전처리에서 활용됨
    • 범주 변수를 처리하거나 레벨 순서를 지정할 수 있음
    • ordered=T를 통해서 level 순서를 활성화 (ordered=F >> 비활성화)
grade <- factor(c("B","A","C","B"), levels=c("A","B","C"), ordered=TRUE)
grade
# [1] B A C B
# Levels: A < B < C

grade[1] > grade[2]
# [1] TRUE       # B가 A보다 level이 높기 때문에 TRUE가 나옴
grade[1] > grade[3]
[1] FALSE        # B가 C보다 level이 낮기 때문에 FALSE가 나옴

summary(grade)
# A B C 
# 1 2 1 

df <- data.frame(name=c("지우", "태빈", "민준", "수아"), grade=grade)
df
#   name grade
# 1 지우     B
# 2 태빈     A
# 3 민준     C
# 4 수아     B

df[order(df$grade), ]    # grade의 level에 따라 정렬되어 출력
#   name grade
# 2 태빈     A
# 1 지우     B
# 4 수아     B
# 3 민준     C

 

Example of factor

bt <- c('A', 'B', 'B', 'O', 'AB', 'A') # 문자형 벡터 bt 정의
bt.new <- factor(bt) # 팩터 bt.new 정의

bt # 벡터 bt의 내용 출력
bt.new # 팩터 bt.new의 내용 출력

bt[5] # 벡터 bt의 5번째 값 출력
bt.new[5] # 팩터 bt.new의 5번째 값 출력levels(bt.new) # 팩터에 저장된 값의 종류를 출력

as.integer(bt.new)    # 팩터의 문자값을 숫자로 바꾸어 출력
# [1] 1 3 3 4 2 1     # 요인 순서대로 숫자로 바꾸어 출력

bt.new[7] <- 'B'      # 팩터 bt.new의 7번째에 'B' 저장
bt.new[8] <- 'C'      # 팩터 bt.new의 8번째에 'C' 저장 >> 경고 메시지 발생
bt.new # 팩터 bt.new의 내용 출력
# [1] A    B    B    O    AB   A    B    <NA>   # 요인에 없던 C가 들어갈 수 없어 NA로 들어감
# Levels: A AB B O

summary(bt.new)
 # A AB  B  O 
 # 2  1  2  1