10.1 데이터 프레임의 생성

data.frame() 함수를 사용하여 데이터 프레임을 만들 수 있습니다.

data.frame() 함수의 형식은 다음과 같습니다.

data.frame(..., row.names = NULL, check.rows = FALSE, check.names = TRUE, fix.empty.names = TRUE, stringsAsFactors = default.stringsAsFactors())

  • ... : 이 인수는 폼 값이나 tag = value 형태이다. 구성 요소명(컬럼 명)은 tag 이름으로 또는 deparsed 인수 자체로 생성됩니다.
  • row.names = : NULL, 단일 정수, 또는 행 이름으로 사용될 컬럼을 지정하는 문자열, 또는 데이터 프레임을 위한 행 이름을 주는 문자 또는 정수 벡터입니다.
  • check.rows = : FALSE 값이 디폴트 값. TRUE이면, 행들에 대한 길이와 이름에 대한 일관성 검토하고 위배되면 데이터 프레임을 생성하지 않습니다.
  • check.names = : 논리값. TRUE이면 데이터 프레임에 있는 변수 이름들이 문법적으로 타당하고 증복이 없는 변수 이름들인지 검토합니다. 필요하면 (make.names에 의해) 조정됩니다.
  • fix.empty.names = : 논리값 이름이 붙여지지 않은 컬럼(someName = arg 형태로 지정되지 않으면)이 자동으로 생성된 이름이나 name”.”을 가지고 있는지를 나타내는 논리값으로, “” 이름이 유지되어야 하지만 check.names가 false일 때에도 FALSE로 설정되어야 합니다.
  • stringsAsFactors = default.stringsAsFactors() : 버전 4.0.0 이후로 기능이 없어짐. 이전 버전의 경우, 디폴트로 문자 벡터 컬럼의 경우 factor 형으로 생성되었음.

예를 들어, 앞에서 예를 든 데이터 프레임은 data.frame() 함수를 사용하여 다음과 같이 생성할 수 있습니다.

# 4개 열, 5개 행으로 구성된 데이터 프레임을 생성합니다.
emp.data <- data.frame(emp_id = c(1:5),                                      # 1번쨰 컬럼 : emp_id
                       emp_name = c("Rick","Dan","Michelle","Ryan","Gary"),  # 2번째 컬럼 : emp_name
                       salary = c(623.3,515.2,611.0,729.0,843.25),           # 3번쨰 컬럼 : salary
                       start_date = as.Date(c("2012-01-01", "2013-09-23", "2014-11-15", 
                                              "2014-05-11", "2015-03-27")),  # 4번째 컬럼 : start_date
                       stringsAsFactors = FALSE                              # R 4.0 이후 기본값입니다.
)
str(emp.data)                         # emp.data 데이터 프레임의 구조를 반환합니다.
## 'data.frame':    5 obs. of  4 variables:
##  $ emp_id    : int  1 2 3 4 5
##  $ emp_name  : chr  "Rick" "Dan" "Michelle" "Ryan" ...
##  $ salary    : num  623 515 611 729 843
##  $ start_date: Date, format: "2012-01-01" "2013-09-23" ...

위의 예에서 emp.data는 각각 5 개의 요소를 갖는(5개 행) 4 개의 벡터(emp_id, emp_name, salary, start_date)로 구성된(4개 열) 리스트로 볼 수 있 수 있습니다.

그런데 마지막에 있는 stringsAsFactors = 인수는 컬럼에 있는 문자형 벡터를 요인(factor)로 변환할 것인지를 설정하는 옵션입니다. R 버전이 4.0 이전에는 이 인수의 기본값이 TRUE로 되어 있었지만, R 버전 4.0 이후에는 FALSE를 기본값으로 하고 있습니다.

10.1.1 열 이름을 지정하지 않으면

그런데 데이터 프레임을 생성할 때 컬럼 명을 지정하지 않으면 어떻게 될까요? 예를 들어, df1 데이터 프레임이 두 개의 컬럼으로 구성되어 있는데 이름을 지정하지 않고 싶다면 다음과 같이 컬럼의 이름을 지정하지 않고 데이터만 지정해 주면 됩니다.

df1 <- data.frame(letters[1:5], 
                  LETTERS[11:15])            # 컬럼 명을 지정하지 않고 데이터 프레임을 생성합니다.
str(df1)                                     # 컬럼 명을 데이터 부분을 반영하여 자동생성함을 알 수 있습니다.
## 'data.frame':    5 obs. of  2 variables:
##  $ letters.1.5.  : chr  "a" "b" "c" "d" ...
##  $ LETTERS.11.15.: chr  "K" "L" "M" "N" ...
df1                                          # df1의 데이터를 확인합니다.
##   letters.1.5. LETTERS.11.15.
## 1            a              K
## 2            b              L
## 3            c              M
## 4            d              N
## 5            e              O

데이터 프레임의 각 구성 요소(컬럼)의 이름을 지정하지 않으면 각 구성 요소의 데이터가 하나의 변수로 변환됨을 알 수 있습니다. 따라서 이러한 일이 일어나지 않게 각 구성요소(컬럼)에 대한 이름을 지정해 주는 것이 좋습니다.

혹시 컬럼의 이름을 그래도 지정하고 싶지 않은 경우에는 fix.empty.names = FALSE 옵션을 지정해 주면, 컬럼명이 자동생성되지 않고 공란(“”)으로 남게 할 수 있습니다.

df2 <- data.frame(letters[1:5], LETTERS[11:15], fix.empty.names = FALSE)           
str(df2)                                        # 컬럼 명을 데이터 부분을 반영하여 자동생성함을 알 수 있습니다.
## 'data.frame':    5 obs. of  2 variables:
##  $ : chr  "a" "b" "c" "d" ...
##  $ : chr  "K" "L" "M" "N" ...
df2 
##      
## 1 a K
## 2 b L
## 3 c M
## 4 d N
## 5 e O
# 컬럼 이름을 지정하려면 colnames() 함수를 이용합니다.
colnames(df2) <- c("No", "Char")                # 컬럼 이름을 설정합니다.
str(df2)
## 'data.frame':    5 obs. of  2 variables:
##  $ No  : chr  "a" "b" "c" "d" ...
##  $ Char: chr  "K" "L" "M" "N" ...

colnames() 함수를 이용하면 각 컬럼의 이름을 설정할 수 있습니다.

10.1.2 같은 컬럼명이 있는 경우

만일 다음의 예에서와 같이 데이터 프레임을 생성할 때 컬럼의 이름이 같은 것이 있는 경우는 어떻게 될까요? R의 data.frame() 함수는 데이터 프레임의 컬럼명이 같은 것이 있는 경우 컬럼명을 자동으로 수정합니다.

# df3의 컬럼이 모두 a로 설정되어 있습니다. 
df3 <- data.frame(a = letters[1:5], 
                  a = LETTERS[11:15])
str(df3)                      # 두 번째 컬럼명이 a.1으로 자동변경되어 있씁니다.
## 'data.frame':    5 obs. of  2 variables:
##  $ a  : chr  "a" "b" "c" "d" ...
##  $ a.1: chr  "K" "L" "M" "N" ...
df3
##   a a.1
## 1 a   K
## 2 b   L
## 3 c   M
## 4 d   N
## 5 e   O

즉, 데이터 프레임을 생성할 때 data.frame() 함수는 컬럼의 이름을 확인해 보고 같은 이름이 있으면 그 이름을 자동으로 변경해 줍니다.

그럼에도 만일 컬럼 이름을 그대로 같은 이름으로 남기고 싶다면 check.names = 인수를 FALSE로 설정해 주면 됩니다.

# df4의 컬럼이 모두 a로 설정하고 싶습니다.
df4 <- data.frame(a = letters[1:5], 
                  a = LETTERS[11:15],
                  check.names = TRUE)     # 컬럼 이름을 지정한 대로 설정합니다.
str(df4)                                  # 두 번째 컬럼명도 a로 남아 있습니다.
## 'data.frame':    5 obs. of  2 variables:
##  $ a  : chr  "a" "b" "c" "d" ...
##  $ a.1: chr  "K" "L" "M" "N" ...
df4
##   a a.1
## 1 a   K
## 2 b   L
## 3 c   M
## 4 d   N
## 5 e   O

10.1.3 행의 이름을 지정하기

데이터 프레임은 열을 구성 요소로 하고 각 열의 요소 값들이 결합하여 하나의 행을 이루게 됩니다. 데이터 프레임을 생성할 때 열의 이름과 함께 행의 이름도 설정할 수 있습니다. 이 때 사용하는 인수는 row.names = 입니다.

df5 <- data.frame(a = letters[1:5], 
                  b = LETTERS[11:15], 
                  row.names = "a")       # 구성 요소 a는 컬럼이 아닌 행의 이름에 이용됩니다.
str(df5)
## 'data.frame':    5 obs. of  1 variable:
##  $ b: chr  "K" "L" "M" "N" ...
df5
##   b
## a K
## b L
## c M
## d N
## e O

df5row.names = “a”를 인수로 하고 있습니다.

즉, a 구성 요소는 열이 아닌 행 이름으로 활용되도록 지정하고 있는 것입니다. 따라서 df5의 구조를 보면 열이 b 하나인 데이터 프레임임을 알 수 있습니다.

데이터를 확인해 보면 a의 요소들이 행 번호 대신에 출력되어 있음을 알 수 있습니다.

위의 예에서 row.names = 인수의 값을 “b”로 변경해서 실행을 해 보기 바랍니다.

10.1.4 컬럼의 길이가 다른 경우

데이터 프레임은 기본적으로 생김새가 사각형 형태여야 합니다. 열을 구성하는 각 요소의 길이가 같아야 한다는 것이 전제되어 있습니다. 따라서 각 열의 길이가 다른 데이터 프레임은 data.frame() 함수로 생성할 수 없습니다.

다음과 같이 a컬럼은 요소가 6개, b컬럼은 요소가 5개로 지정되는 경우 data.frame() 함수는 error를 발생시킵니다.

# 다음과 같이 각 열의 길이가 다른 경우 error가 발생합니다.
df6 <- data.frame(a = 1:6,                # a 컬럼의 길이가 6입니다.
                  b = letters[1:5])       # b 컬럼의 길이는 5입니다.
## Error in data.frame(a = 1:6, b = letters[1:5]): arguments imply differing number of rows: 6, 5

이러한 데이터 구조를 만들고 싶다면, 리스트 구조를 이용해야 한다.

read.table(), read.csv(), read.delim(), read.fwf()와 같은 R의 많은 데이터 입력 함수는 데이터 프레임으로 데이터를 읽습니다.12


  1. 제3부 제1장에서 자세히 살펴보겠습니다↩︎