오늘의 포스팅에서는 IT에서 이야기하는 복잡한 <데이터 구조>의 기술적인 면을 이야기하고자 함이 아니다. 엑셀이든, csv 파일이든, 일반적으로 행렬형태의 데이터를 우리가 어떻게 바라보아야 하는지 개념을 잡는데 도움을 주고자 간단한 그림과 함께 글을 써 나가도록 한다.
여러개의 샘플에 대해서 어떤 측정이나 조사를 하려고 한다. 측정이나 조사에는 여러개의 수치화 가능한 항목이 있을 것이다. 갯수가 얼마 안되면 대충 수첩에 적어도 좋겠지만, 대부분의 경우는 엑셀과 같은 프로그램에서 입력을 하는 것이 수월할 것이다. 예를 들어서 전체 학생의 중간고사 성적표 일람을 생각해 보자. 하나의 행(row)은 개별적인 학생에 해당하고, 각 열(column)에는 국어, 영어, 수학 등의 시험 점수가 적힌다. 이를 90도 돌려서 개별 학생의 성적을 세로(열)로 배열하고 싶은 사람도 있을 것이다. 논리적으로는 문제가 없지만 영 어색하다. 각 학생은 하나의 샘플이라 간주할 수 있고, 수가 많은 샘플은 행 단위로 추가되는 것이 바람직하다. 따라서 아래 그림이 가장 보편적인 2차원 행렬 형태의 데이터 집합 구조라고 보면 된다.
첫 행과 첫 열부터 기록치를 써내려가는 사람은 없을 것이다. 첫 행과 첫 열에는 나머지 셀에 어떤 항목이 들어가는지 제목부터 달아 놓는 것이 자연스럽다. 특히 중요한 것은 각 열의 이름이다. 이를 R에서는 보통 variable이라고 이야기한다.
생명과학 분야에서 흔히 다루는 expression data의 구조는 이와 조금 다르다. 개개의 observation(chip 또는 RNA-seq 실험)이 열로 배치되고, 행은 유전자 ID로 삼는 것이 관례이다. 따라서 hierarchical clustering 등을 하려면 t() 함수를 사용하여 트랜스포즈를 해야 된다.
R에서 행과 열의 이름을 지정할 때에는 dimnames()라는 함수를 쓴다. dimname(data)라고 하면 data 오브젝트에 이미 설정된 행과 열의 이름을 반환한다. 조금 뒤에 살펴볼 row.names() 함수도 마찬가지로 작동한다. 먼저 dimnames() 함수의 사용법을 알아보자.
> countries = c("Austria", "France", "Germany")
> variables = c("GDP", "Population", "Inflation")
> dimnames(country.data) = list(countries, variable)
만약 세번째 컬럼을 쏙 빼서 row name으로 삼고 싶다면?
> row.names(country.data) = country.data[, 3]
> country.data = country.data[, -3] # 세번째 컬럼 제거
R이 훌륭한 점은 이렇게 행렬 형태로 구성된 데이터를 매우 자유롭게 다룰 수 있다는 점이다. 물론 어떤 사람은 엑셀이 더 편리하다고 말할 것이다. 마우스를 클릭해서 눈에 즉시 보이는 결과를 얻는다는 점에서는 엑셀이 낫다. 그러나 어떤 데이터를 임포트한 뒤 특정 컬럼이나 행을 없애고 계산을 하고 새로운 행과 열을 만들고... 이런 일을 하다보면 최종 결과물만 남을뿐 과정을 기억하기가 어렵다. 이런 점에서 스크립트 형식으로 작업하는 R은 훨씬 유연하고 정확하며 실수가 적다.
R은 다음과 같은 일을 하는데 정말 편리하다. 단, 반드시 유념할 것이 있다. for..와 같은 반복문을 쓰지 않는 것이 R의 기본 정신이다. 나는 최소한 그렇게 생각한다.
- 어떤 조건을 만족하는 행이나 열 제거하기
- 어떤 조건을 만족하는 행이나 열만 뽑아내기
- 행이나 열을 기준으로 계산하거나(예: 평균, 최대값, 최소값...) 조작하기(예: 정렬)
- 테이블 여러개를 합치기
인터넷을 참조해 보면 이러한 상황에 사용할 수 있는 정말로 아름다운 사례가 많다. 시간이 허락하는대로 포스팅해 보고자 한다. 아, [하루에 한 Perl]도 해야 되는데...
댓글 없음:
댓글 쓰기