다양한 스토리를 담고 있는 연재를 만나보세요.
[초심자를 위한 생물학+정보학] R의 자료 형태와 구조 3 - 55
Bio통신원(고주온)
_55_
- R의 자료 형태와 구조 3 -
우선, 리스트와 데이터프레임에 대하여 기본적인 사항을 짚어 보자. 앞서 알아 본 벡터와 행렬은 이들을 이루고 있는 원소들이 모두 동일한 자료형이어야 했지만, 이번에 알아 볼 리스트와 데이터프레임은 내부의 원소들이 같은 자료형이 아니어도 된다. 리스트는 각 요소마다, 데이터프레임은 각 열 (column)마다 일정한 자료형만 받을 수 있으며, 리스트는 심지어 데이터프레임과 같이 구조화된 객체도 자료로 포함할 수 있다. 따라서, 리스트는 R의 자료형 가운데 가장 융통성이 크다고 볼 수도 있다. 여기서 데이터프레임이 각 열마다 일정한 자료형만 받을 수 있다는 뜻은 각각의 열에 속하는 원소들이 해당 열에 대해서는 동일한 자료형이어야 한다는 것이다. 예컨대, 수치가 들어 있는 데이터프레임의 열에 문자형 자료를 추가하게 되면 해당 열의 모든 요소가 문자형으로 전환된다.
리스트와 데이터프레임에 관한 이야기를 좀더 쉽게 하기 위해서 지난 52회차 연재에서 사용했던 mortality_50.tsv 파일을 다시 사용해 보자. 혹시 해당 내용을 보지 않은 독자는 아래 링크에서 R 작업 디렉터리에 내려 받아 사용하면 된다. 파일의 위치는 현재 R이 실행되는 디렉터리이다.
https://biostring.org/files/mortality_50.tsv
------
> df0 <- read.delim('mortality_50.tsv') <-- (1)
> head(df0) <-- (2)
Gender Age
1 Male 69
2 Female 88
3 Female 83
4 Male 63
5 Male 84
6 Male 74
> class(df0) <-- (3)
[1] "data.frame"
> mode(df0) <-- (4)
[1] "list"
> typeof(df0) <-- (5)
[1] "list"
> str(df0) <-- (6)
'data.frame': 50 obs. of 2 variables:
$ Gender: Factor w/ 2 levels "Female","Male": 2 1 1 2 2 2 2 2 2 2 ...
$ Age : int 69 88 83 63 84 74 79 57 47 71 ...
------
내려 받은 mortality_50.tsv 파일을 변수 df0로 읽어 들이고 (1), head() 함수로 변수 df0에 적재된 내용의 앞 부분을 확인한다 (2). 변수 df0의 고수준 자료형은 데이터프레임, 저수준 자료형은 리스트임을 확인하고 (3-5), str() 함수로 그 구조를 확인한다 (6). 출력에서 볼 수 있듯이 객체 df0는 2개의 변수 (variable)에 대하여 50개씩의 자료가 들어 있는 데이터프레임이라는 것을 알 수 있다. 이상의 내용으로부터 알 수 있는 점은 데이터프레임이 리스트를 기반으로 하는 자료형이라는 것이다. 즉, 특정 조건에 부합되는 리스트의 집합이 데이터프레임이라고 보면 된다. 이에 대해서는 다음의 내용을 보자.
------
> df1 <- list(Gender = c("Male", "Female", "Female", "Male"), Age = c(69, 88, 83, 63)) <-- (1)
> head(df1) <-- (2)
$Gender
[1] "Male" "Female" "Female" "Male"
$Age
[1] 69 88 83 63
> str(df1) <-- (3)
List of 2
$ Gender: chr [1:4] "Male" "Female" "Female" "Male"
$ Age : num [1:4] 69 88 83 63
> df2 <- rbind(df0, df1) <-- (4)
> str(df2) <-- (5)
'data.frame': 54 obs. of 2 variables:
$ Gender: Factor w/ 2 levels "Female","Male": 2 1 1 2 2 2 2 2 2 2 ...
$ Age : num 69 88 83 63 84 74 79 57 47 71 ...
> class(df2) <-- (6)
[1] "data.frame"
> typeof(df2) <-- (7)
[1] "list"
>
------
변수 df1에 리스트를 생성하는 함수 list()를 사용하여 자료를 담고 (1), 내용과 그 구조를 확인한다 (2, 3). 출력 내용을 보면, 변수 df1는 원소 4개씩 들어 있는 2개의 리스트 (Gender, Age)로 이루어져 있음을 알 수 있다. 이제 행 결합 함수 rbind()를 사용하여 새로운 변수 df2에 앞서 생성한 df0와 df1, 두 객체를 결합한 후 (4), 그 구조를 보면 (5), 객체 df2는 각각 54개의 원소를 갖고 있는 두 리스트로 이루어진 데이터프레임인 것을 알 수 있다 (6, 7). 이때, 결합하려는 두 데이터 집합을 구성하는 열의 수와 이름, 그리고 속성이 동일해야만 한다. 하나라도 다르면 오류가 발생한다.
이번에는 리스트와 데이터프레임의 관계를 알아 보자.
------
> dframe <- data.frame(Gender = c("Male", "Female", "Female"), Age = c(68, 87, 82)) <-- (1)
> dframe <-- (2)
Gender Age
1 Male 68
2 Female 87
3 Female 82
> class(dframe) <-- (3)
[1] "data.frame"
> typeof(dframe) <-- (4)
[1] "list"
> lframe <- list(Gender = c("Male", "Female"), Age = c(86, 83)) <-- (5)
> lframe <-- (6)
$Gender
[1] "Male" "Female"
$Age
[1] 86 83
> class(lframe) <-- (7)
[1] "list"
> typeof(lframe) <-- (8)
[1] "list"
> df3 <- rbind(df2, dframe) <-- (9)
> class(df3) <-- (10)
[1] "data.frame"
> str(df3) <-- (11)
'data.frame': 57 obs. of 2 variables:
$ Gender: Factor w/ 2 levels "Female","Male": 2 1 1 2 2 2 2 2 2 2 ...
$ Age : num 69 88 83 63 84 74 79 57 47 71 ...
> df4 <- rbind(df2, lframe) <-- (12)
> class(df4) <-- (13)
[1] "data.frame"
> str(df4) <-- (14)
'data.frame': 56 obs. of 2 variables:
$ Gender: Factor w/ 2 levels "Female","Male": 2 1 1 2 2 2 2 2 2 2 ...
$ Age : num 69 88 83 63 84 74 79 57 47 71 ...
>
------
먼저, Gender와 Age의 두 항목에 대하여 3개씩의 자료로 이루어진 자료군을 데이터프레임 생성 함수인 data.frame()을 사용하여 변수 dframe에 적한 후 (1), 그 내용을 확인하고 (2) 자료형을 확인한다. 이때, 출력의 자료 맨 앞의 숫자 1, 2, 3 등은 대괄호 없이 출력된다. 이것은 데이터프레임의 특징이다. 출력 내용으로 알 수 있듯이 변수 dframe의 고수준 자료형은 데이터프레임이지만 (3) 저수준 자료형은 리스트이다 (4). 이번에는 동일한 Gender와 Age의 두 항목에 대하여 2개씩의 자료로 이루어진 자료군을 리스트 생성 함수인 list()를 사용하여 변수 lframe에 입력한 다음 (5), 출력해 본다 (6). 이 객체 lframe의 자료형은 리스트임을 확인할 수 있다 (7, 8). 이제, 행 결합 함수 rbind()를 사용하여 df2 및 dframe 두 객체를 결합해 새로운 변수 df3에 적재하고 (9), 그 자료형과 구조를 확인한다 (10, 11). 객체 df3의 자료형은 데이터프레임임을 알 수 있다. 또다른 변수 df4에는 리스트 자료형인 객체 lframe을 rbind() 함수로 결합하여 적재한다 (12). 이렇게 생성된 객체 df4도 자료형이 df3와 동일한 데이터프레임임을 볼 수 있다. 이처럼, 리스트가 특정 조건에 맞게 자료 내용을 구성하게 되면 데이터프레임이 될 수 있다. 데이터프레임은 R을 이용한 자료의 분석에서 가장 흔하게 사용되는 표 (table) 형태의 자료형이다.
이 자료의 그래프 출력에 대해서도 간단히 알아 보자.
------
> plot(df3$Gender, df3$Age) <-- (1)
> plot(df3$Age) <-- (2)
> barplot(df3$Age) <-- (3)
>
------
그림 1. 자료의 boxplot.
그림 2. 자료의 dot plot.
그림 3. 자료의 bar plot.
Gender와 Age 각 항목 당 57개의 자료로 이루어져 있는 객체 df3에 대하여 plot() 함수로 상자 그림 (box plot)을 출력한다 (1, 그림 1). 동일한 자료에 대하여 Age 항목 (열, column)만을 대상으로 하여 plot() 함수를 적용하면 점 그래프 (dot plot)을 볼 수 있다 (2, 그림 2). 또한, 같은 Age 항목에 대하여 barplot() 함수를 적용하면, 이에 대한 막대 그래프 (bar plot)가 출력되는 것을 확인할 수 있다 (3, 그림 3).
그리고, 본 회차의 첫 단락에서 수치가 들어 있는 데이터프레임의 열에 문자형 자료를 추가하게 되면 해당 열의 모든 요소가 문자형으로 전환된다고 했는데, 이에 대해서도 간단히 확인해 보자.
------
> xframe <- list(Gender = c("Male", "Female"), Age = c(87, "82")) <-- (1)
> xframe <-- (2)
$Gender
[1] "Male" "Female"
$Age
[1] "87" "82"
> df5 <- rbind(df2, xframe) <-- (3)
> str(df5) <-- (4)
'data.frame': 56 obs. of 2 variables:
$ Gender: Factor w/ 2 levels "Female","Male": 2 1 1 2 2 2 2 2 2 2 ...
$ Age : chr "69" "88" "83" "63" ...
>
------
결합 대상인 객체와 동일하게 항목 Gender와 Age에 대하여 각각 2개 씩의 자료를 포함한 객체를 만들기 위하여, 변수 xframe에 list() 함수를 사용하여 자료를 적재한다 (1). 다만, 이때 항목 Age의 2번째 자료를 수치가 아닌 문자형 ("82")으로 입력하고 (1), 그 내용을 확인해 본다 (2). 출력에서 볼 수 있듯이 xframe의 Age 항목의 자료형이 모두 문자형으로 바뀌어 있다. 이 상태에서 rbind() 함수로 객체 df2와 xframe을 결합하면 (3), 그 결과 구조는 데이터프레임이지만 Age 항목의 자료는 모두 문자형으로 변환되어 있음을 볼 수 있다 (4). 따라서 데이터프레임의 사용에 있어서 자료의 추가 등의 경우에는 이러한 내용을 고려하지 않으면 이후에 이어지는 연산에서 문제가 생길 수 있다.
이상으로 R에서 사용되는 기본적인 자료형에 대하여 간략히 알아 보았다.
끝으로, R에는 경우에 따라서 NULL과 NA로 표시되는 자료가 있다. NULL은 값이 정해지지 않은 (undefined) 객체, 즉 NULL 객체를 의미하며, 해당 변수가 초기화되지 않은 상태의 경우이다. 이는 해당 자료의 값이 없는 NA (Not Available)와는 다르다. NA는 자료의 값이 빠져 있는 경우, 즉 결측치 (缺測値)를 말한다. 따라서, NULL과 NA의 가장 확실한 차이는 갱신 가능 여부이다. NA는 해당 자료의 값을 갱신 (update)할 수 있으나, NULL의 경우에는 이를 강제할 수 없다. 또 다른 차이는 NULL의 경우, 값 자체가 없다. 이에 대해서는 기회가 될 때 다시 확인해 보기로 하자.
- "초심자를 위한 생물학+정보학"은 아래 PDF 다운 받으셔서 읽는 것도 가능합니다. -
본 기사는 네티즌에 의해 작성되었거나 기관에서 작성된 보도자료로, BRIC의 입장이 아님을 밝힙니다. 또한 내용 중 개인에게 중요하다고 생각되는 부분은 사실확인을 꼭 하시기 바랍니다.
[기사 오류 신고하기]
(http://bioprofiler.tistory.com) IBM-XT시절부터 개인용 컴퓨터를 사용하였으나, 강산이 변한 지금도 어제 코딩한 내용을 오늘 기억하지 못하는 자유인. 박사학위는 분자유전학 분야로 받았으며, 물리학과 화학에 관심만 있음. 현재 대학 교수로 재직 중.
다른 연재기사 보기
전체 보기