[R 기초] 6. 데이터 구조 (행렬, 데이터프레임)

2026. 6. 28. 17:00·BI&Programming-Tools/R

행렬 (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
'BI&Programming-Tools/R' 카테고리의 다른 글
  • [R 기초] 8. 데이터 전처리
  • [R 기초] 7. 제어문과 함수
  • [R 기초] 5. 데이터 구조 (벡터, 팩터, 리스트)
  • [R 기초] 4. 논리형과 결측값
데이터로 읽는 생명
데이터로 읽는 생명
is-note 님의 블로그 입니다.
  • 데이터로 읽는 생명
    In Silico Note
    데이터로 읽는 생명
  • 전체
    오늘
    어제
    • 분류 전체보기 (190) N
      • Bio-Knowledge (16)
        • 분자생물학 & 유전학 기초 (0)
        • 전사체학 & 유전자 발현 (0)
        • 구조생물학 & 단백질 (0)
        • 싱글셀 & 다중오믹스 (0)
        • 임상유전학 & 질환 데이터 (0)
      • Programming (4)
        • API (4)
      • BI&Programming-Tools (111)
        • File Formats (14)
        • Linux & Bash Script (38)
        • Python (35)
        • R (11)
        • 통계 (8)
        • Pipeline Manager (0)
        • Etc (5)
      • Bio Data Analysis (28) N
        • 서열분석개론 (6)
        • WGS(Whole Genome Seq) (11)
        • WES(Whole Exome Seq) (2)
        • RNA-Seq (4) N
        • Metagenome (2)
        • Non-human Resequencing (1)
        • 임상유전체 분석 (1)
        • Multi-Omics (1)
      • Bio-Trends & Tech (1)
      • 코딩테스트 연습 (30)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    파이썬연습
    ngs
    리눅스
    R기초
    데이터분석
    코딩테스트
    유전체분석
    fasta
    파이썬기초
    분자생물학
    통계
    파이썬
    파일포맷
    bioinformatics
    GATK
    FASTQ
    R
    wgs
    생물정보학
    리눅스기초
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
데이터로 읽는 생명
[R 기초] 6. 데이터 구조 (행렬, 데이터프레임)
상단으로

티스토리툴바