행렬 (Matrix)
행렬은 같은 타입의 값으로 이루어진 2차원 구조입니다.
벡터를 행과 열로 배열한 것으로, 수치 계산이나 발현량 행렬처럼 동일한 타입의 데이터를 표 형태로 다룰 때 사용합니다.
행렬 생성
# matrix(): 벡터를 행렬로 변환
m <- matrix(1:12, nrow = 3, ncol = 4)
m
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
# [2,] 2 5 8 11
# [3,] 3 6 9 12
기본적으로 열 방향(column-wise)으로 값이 채워집니다. 행 방향으로 채우려면 byrow = TRUE를 지정합니다.
matrix(1:12, nrow = 3, byrow = TRUE)
# [,1] [,2] [,3] [,4]
# [1,] 1 2 3 4
# [2,] 5 6 7 8
# [3,] 9 10 11 12
rbind(), cbind()로 생성
row1 <- c(1, 2, 3)
row2 <- c(4, 5, 6)
rbind(row1, row2) # 행으로 묶기
# [,1] [,2] [,3]
# row1 1 2 3
# row2 4 5 6
cbind(row1, row2) # 열로 묶기
# row1 row2
# [1,] 1 4
# [2,] 2 5
# [3,] 3 6
행렬 인덱싱
[행, 열] 형태로 접근합니다.
m <- matrix(1:12, nrow = 3)
m[1, 2] # 1행 2열: 4
m[1, ] # 1행 전체: 1 4 7 10
m[, 2] # 2열 전체: 4 5 6
m[1:2, 3:4] # 1~2행, 3~4열
데이터프레임 (Data Frame)
데이터프레임은 각 열이 서로 다른 타입을 가질 수 있는 2차원 구조입니다.
실제 분석에서 가장 많이 다루는 자료구조이며, 엑셀 시트나 데이터베이스 테이블과 비슷한 형태입니다.
데이터프레임 생성
df <- data.frame(
sample_id = c("s01", "s02", "s03"),
coverage = c(30.5, 22.1, 45.8),
gc = c(0.51, 0.49, 0.52),
paired = c(TRUE, TRUE, FALSE)
)
df
# sample_id coverage gc paired
# 1 s01 30.5 0.51 TRUE
# 2 s02 22.1 0.49 TRUE
# 3 s03 45.8 0.52 FALSE
기본적으로 문자열이 팩터로 변환되지 않도록 stringsAsFactors = FALSE가 R 4.0 이상에서는 기본값이라고 합니다.
이전 버전을 사용하는 경우 명시적으로 지정하는 것이 좋습니다.
데이터 요약
df <- data.frame(
sample_id = c("s01", "s02", "s03", "s04"),
coverage = c(30.5, 22.1, 45.8, 18.3),
gc = c(0.51, 0.49, 0.52, 0.48)
)
dim(df) # 4 3 (행 수, 열 수)
nrow(df) # 4 (행 수)
ncol(df) # 3 (열 수)
str(df) # 구조 요약: 타입, 첫 몇 개 값 확인
summary(df) # 각 열의 기술 통계 (평균, 중앙값 등)
요소 확인 및 추출
head(), tail()
head(df) # 상위 6행 (기본값)
head(df, 3) # 상위 3행
tail(df, 2) # 하위 2행
[], [[]], $
# 열 추출
df["coverage"] # 데이터프레임 반환
df[["coverage"]] # 벡터 반환
df$coverage # 벡터 반환
# 행과 열 동시 지정 [행, 열]
df[1, ] # 1행 전체
df[, 2] # 2열 전체 (벡터)
df[1, 2] # 1행 2열 값
df[c(1, 3), "coverage"] # 1, 3행의 coverage 열
# 조건으로 필터링
df[df$coverage >= 30, ]
df[df$gc > 0.5 & df$coverage >= 20, ]
칼럼명 확인/변경
colnames(df) # 열 이름 확인
rownames(df) # 행 이름 확인
names(df) # 데이터프레임에서는 colnames()와 동일
# 전체 이름 변경
colnames(df) <- c("id", "cov", "gc_content")
# 특정 열 이름만 변경
colnames(df)[2] <- "depth"
names(df)[names(df) == "gc"] <- "gc_content"
행렬에서도 같은 함수를 사용할 수 있습니다.
m <- matrix(1:6, nrow = 2)
colnames(m) <- c("A", "B", "C")
rownames(m) <- c("row1", "row2")
행 추가와 열 추가
열 추가
df$log_cov <- log2(df$coverage) # 새 열 추가
df[["status"]] <- c("ok", "ok", "high", "low") # 동일한 방식
행 추가: rbind()
new_row <- data.frame(
sample_id = "s05",
coverage = 33.0,
gc = 0.50
)
df <- rbind(df, new_row)
rbind()로 행을 추가할 때 열 이름과 타입이 일치해야 합니다.
열 추가: cbind()
extra <- data.frame(tissue = c("blood", "liver", "lung", "kidney"))
df <- cbind(df, extra)
행 제거와 열 제거
행 제거
df[-1, ] # 1행 제거
df[-c(1, 3), ] # 1, 3행 제거
df[df$coverage >= 20, ] # 조건에 맞는 행만 유지 (나머지 제거)
열 제거
df[, -2] # 2열 제거
df[, !names(df) %in% c("gc", "paired")] # 특정 열 이름으로 제거
df$coverage <- NULL # NULL 할당으로 열 제거
데이터 합치기
rbind(): 행 방향으로 연결
열 구조가 동일한 두 데이터프레임을 위아래로 붙입니다.
df1 <- data.frame(id = c("s01", "s02"), cov = c(30, 25))
df2 <- data.frame(id = c("s03", "s04"), cov = c(40, 20))
rbind(df1, df2)
# id cov
# 1 s01 30
# 2 s02 25
# 3 s03 40
# 4 s04 20
cbind(): 열 방향으로 연결
행 수가 같은 두 데이터프레임을 좌우로 붙입니다.
df_a <- data.frame(id = c("s01", "s02"), cov = c(30, 25))
df_b <- data.frame(gc = c(0.51, 0.49), paired = c(TRUE, FALSE))
cbind(df_a, df_b)
merge(): 공통 열 기준으로 합치기
SQL의 JOIN과 유사합니다.
df1 <- data.frame(id = c("s01", "s02", "s03"), cov = c(30, 25, 40))
df2 <- data.frame(id = c("s01", "s02", "s04"), gc = c(0.51, 0.49, 0.52))
# inner join (기본): 두 데이터에 모두 있는 id만
merge(df1, df2, by = "id")
# id cov gc
# 1 s01 30 0.51
# 2 s02 25 0.49
# left join: df1 기준, df2에 없으면 NA
merge(df1, df2, by = "id", all.x = TRUE)
# outer join: 모두 포함, 없으면 NA
merge(df1, df2, by = "id", all = TRUE)
행렬, 데이터프레임 비교
| 항목 | 행렬(matrix) | 데이터프레임 |
| 원소 타입 | 모두 같아야 함 | 열마다 달라도 됨 |
| 주요 용도 | 수치 계산, 발현량 행렬 | 일반 데이터 분석 |
| 열 추출 ($) | 불가 | 가능 |
| 인덱싱 | [행, 열] | [행, 열], $열이름 |
'BI&Programming-Tools > R' 카테고리의 다른 글
| [R 기초] 8. 데이터 전처리 (0) | 2026.06.29 |
|---|---|
| [R 기초] 7. 제어문과 함수 (0) | 2026.06.29 |
| [R 기초] 5. 데이터 구조 (벡터, 팩터, 리스트) (0) | 2026.06.28 |
| [R 기초] 4. 논리형과 결측값 (0) | 2026.06.28 |
| [R 기초] 3. 수와 문자 다루기 (0) | 2026.06.27 |
