Source file ⇒ 세미나_1_.Rmd
데이터 분석을 어렵게 하는 이유 중 기술 부채라는 개념이 있다. 실제 데이터 분석의 약 80% 이상의 시간이 데이터 수집, 전처리 그리고 정제에 사용된다. 이러한 시간과 비용을 데이터 부채라고 일컫는다.
데이터 부채가 쌓이는 것을 처음부터 막을 수 있도록 데이터가 저장되는 방식에 대해 제안된 개념이 tidy data이다. 이 개념은 standford의 현직 교수 Hadley Wickham에 의해 제안되었다.
Tidy Data라는 개념은 애초에 컴퓨터가 데이터를 ‘잘’ 인식할 수 있도록 하기 위함이 목적이기 때문에 사람의 눈으로 이해하기에는 적절하지 않을 수 있다. 예시를 통해 개념을 이해하기 앞서, Tidy Data의 조건을 살펴보자.
Tidy Data의 조건
Each variable must have its own column.
각 변수는 개별의 열(column)으로 존재한다.
Each observation must have its own row.
각 관측치는 행(row)를 구성한다.
Each value mush have its own cell.
각 테이블은 단 하나의 관측기준에 의해서 조직된 데이터를 저장한다.
아래의 그림이 각각의 조건을 시각적으로 보여준다.
2번 조건은 하나의 데이터가 한 줄(행)을 구성해야 함을 말하고 있다. 즉, 설문지를 예로 들자면 한 명의 설문 결과가 한 줄로 저장되어야 한다는 것이다. 행(row)이 경우 조건으로 데이터를 filter할 수 있는 공간이다.
1번 조건은 변수를 값으로 이해하는 것이 도움이 된다. 그래서 column의 이름은 해당 변수명이며 column의 cell에는 변수명에 해당하는 값이 들어가야 한다. 예를 들면, column의 이름이 날짜인 경우 각 cell에는 컬럼에 속하는 날짜(month, day, year)이 들어가는 것이 tidy data의 조건을 충족하는 것이다.
3번 조건에 대한 자세한 내용은 dplyr 패키지를 공부하며 다루기로 한다.
Tidy data의 예시:
데이터 셋에 name, trt, result의 세 개의 변수가 있다고 하자.
name 은 세 개의 값을 가진다: (John, Mary, and Jane)
trt 은 두 개의 값을 가진다: (a and b)
result 은 여섯개의 값을 가진다: (-, 16,3,2,11,1)
데이터 셋을 표현할 때, column이 변수이며 row가 각각의 observation을 나타내도록 구성된 경우를 data table 혹은 data frame이라고 부른다. Data tables 은 데이터를 분석하거나 시각화하기에 용의하며 이러한 이유로 인해 data table 형식으로 구성된 데이터를 tidy data라고 한다.
예시:
위의 data table 속 데이터는 tidy 하다고 할 수 있다. 왜냐하면 다음의 규칙을 따라 정렬되어 있기 때문이다:
각 관측치는 개별의 row를 구성하고 있다. treatment와 result는 각각의 환자에 대한 unique한 값이기 때문이다.
변수인 각 column은 각 row에 대하여 같은 종류의(the same sort) 값을 기록하고 있다. 예를들어, trt 는 categorical (a or b) 이며 result 는 일관적으로 numerical하다.
하지만 tidy data 라고하여 항상 간결명료한 것은 아니다. 아래와 같은 경우를 더욱 간결명료하다고 생각할 수 있을 것이다.
하지만 이는 data table이 아니다. (i.e the data isn’t tidy).
위 예시에서 각 column 명에 해당하는 (person, treatmenta, treatmentb)는 적절한 변수명이 아니다. treatmenta 와 treatmentb 는 trt변수의 값일 뿐 그들 스스로 변수이지 않기 때문이다.
데이터가 tidy할 때 우리는 데이터에 손쉽게 벡터 연산을 가할 수 있다. 예를들어 우리가 새로운 변수를 생성하고자 할 때, 데이터가 tidy하다면 별 다른 조작없이 변수를 생성할 수 있다. 자세한 내용은 dplyr을 직접 사용하며 배우기로 한다.
Chaining Syntax
DataComputing 패키지에 있는 BabyNames 데이터 테이블로 파이핑을 해보자.
#to install
install.packages("devtools")
devtools::install_github("DataComputing/DataComputing")
#to load
library(DataComputing)
To look at data in DataComputing:
data(package="DataComputing")
| Item | Title |
|---|---|
| BabyNames | Names of children as recorded by the US Social Security Administration. |
| CountryCentroids | Geographic locations of countries |
| CountryData | Many variables on countries from the CIA factbook, 2014. |
| CountryGroups | Membership in Country Groups |
| DirectRecoveryGroups | Descriptions of the Direct Recovery Groups (DRGs) in the Medicare data. |
| HappinessIndex | World Happiness Report Data |
| MedicareCharges | Charges to and Payments from Medicare |
| MedicareProviders | Medicare Providers |
| MigrationFlows | Human Migration between Countries |
| Minneapolis2013 | Ballots in the 2013 Mayoral election in Minneapolis |
| NCHS | Health Statistics Data 1999-2004 |
| NCI60 | Gene expression in cancer. |
| NCI60cells | Cell Line descriptions in the NCI-60 dataset |
| OrdwayBirds | Birds captured and released at Ordway, complete and uncleaned |
| OrdwaySpeciesNames | Corrected Species Names for the Ordway Birds |
| RegisteredVoters | A sample of the voter registration list for Wake County, North Carolina in Fall 2010. |
| WorldCities | Cities and their populations |
| ZipDemography | Demographic information for most US ZIP Codes (Postal Codes) |
| ZipGeography | Geographic information by US Zip Codes (Postal Codes) |
to look at codebook:
help(Baby Names)
#or
?BabyNames
help(BabyNames)
| BabyNames | R Documentation |
The US Social Security Administration provides yearly lists of names given to babies. These data combine the yearly lists.
BabyNames is the raw data from the SSA. The case is a year-name-sex, for example: Jane F 1922. The count is the number of children of that sex given that name in that year. Names assigned to fewer than five children of one sex in any year are not listed, presumably out of privacy concerns.
data(BabyNames)
BabyNames consists of 1,792,091 entries, each of which has four variables:
name
The given name (character string)
sex
F or M (character string)
count
The number of babies given that name and of that sex. (integer)
year
Year of birth (integer)
The data were compiled from the Social Security Administration web site: http://www.ssa.gov/oact/babynames/names.zip.
BabyNames
data(BabyNames) str(BabyNames)
일반적인 파이핑 syntax:
#Object_Name <-
#Data_Table %>%
#function_name(arguments) %>%
#function_name(arguments)
예시 1:
MyBabies<-
BabyNames %>%
head(3)
MyBabies
| name | sex | count | year |
|---|---|---|---|
| Mary | F | 7065 | 1880 |
| Anna | F | 2604 | 1880 |
| Emma | F | 2003 | 1880 |
this is equivalent to:
MyBabies <-
head(BabyNames,3)
MyBabies
| name | sex | count | year |
|---|---|---|---|
| Mary | F | 7065 | 1880 |
| Anna | F | 2604 | 1880 |
| Emma | F | 2003 | 1880 |
예시 2:
Princes <-
BabyNames %>%
filter(name=="Prince") %>%
group_by(year,sex) %>%
summarise(sum(count))
Princes
## # A tibble: 194 x 3
## # Groups: year [?]
## year sex `sum(count)`
## <int> <chr> <int>
## 1 1880 M 16
## 2 1881 M 17
## 3 1882 M 18
## 4 1883 M 18
## 5 1884 M 17
## 6 1885 M 21
## 7 1886 M 22
## 8 1887 M 18
## 9 1888 M 19
## 10 1889 M 14
## # ... with 184 more rows
equivalent to:
Princes <- summarise(group_by(filter(BabyNames,name=="Prince"),year,sex),sum(count))
Princes
## # A tibble: 194 x 3
## # Groups: year [?]
## year sex `sum(count)`
## <int> <chr> <int>
## 1 1880 M 16
## 2 1881 M 17
## 3 1882 M 18
## 4 1883 M 18
## 5 1884 M 17
## 6 1885 M 21
## 7 1886 M 22
## 8 1887 M 18
## 9 1888 M 19
## 10 1889 M 14
## # ... with 184 more rows
R에서 사용하는 가장 기본적인 데이터 셋은
벡터(vector)
R은 같은 종류의 데이터를 여러개 묶는 벡터 형식을 다룬다. 벡터를 가장 간단하게 만드는 방법은 c()함수를 이용하는 방법이다. 함수 c()의 인수 값으로 벡터에 넣고 싶은 값들을 열거하면 벡터를 생성할 수 있다.
v <- c("abc", 12, 0.567, TRUE)
v
## [1] "abc" "12" "0.567" "TRUE"
벡터의 원소에 숫자와 문자가 함께 포함되는 경우, 벡터의 원소들은 모두 문자(character)로 변환됨을 주의.
#함수 is.vector()를 이용하여 벡터인지 아닌지 확인
is.vector(v)
## [1] TRUE
#벡터의 길이를 구할 때 length()
length(v)
## [1] 4
함수 c() 이외에도 연속된 값을 생성하는 seq(), 일정한 패턴의 반복에 의해 벡터를 생성하는 rep() 함수도 벡터 생성에 유용하게 사용된다.
#1부터 5까지 1씩 증가하는 벡터
1:5
## [1] 1 2 3 4 5
#5부터 -5까지 -1씩 감소하는 벡터
5:-5
## [1] 5 4 3 2 1 0 -1 -2 -3 -4 -5
#벡터 (1, 2, 3)을 길이 10이 될때까지 반복
rep(1:3, length=10)
## [1] 1 2 3 1 2 3 1 2 3 1
#벡터 (1, 2, 3, 4, 5)를 두번 반복
rep(1:5, times=2)
## [1] 1 2 3 4 5 1 2 3 4 5
#1부터 10까지를 7등분한 벡터
seq(1, 10, length=7)
## [1] 1.0 2.5 4.0 5.5 7.0 8.5 10.0
#1부터 10까지 2씩 증가하는 벡터
seq(1, 10, by=2)
## [1] 1 3 5 7 9
#패턴을 가지는 벡터
sequence(c(3, 6, 5))
## [1] 1 2 3 1 2 3 4 5 6 1 2 3 4 5
#중복된 값을 제외한 벡터
unique(rep(1:3, length=10))
## [1] 1 2 3
#0을 10개 늘어놓은 벡터
numeric(10)
## [1] 0 0 0 0 0 0 0 0 0 0
벡터 연산의 결과는 벡터이다.
# -5부터 5까지 1씩 증가하는 정수 백터를 작성
x <- -5:5
(x + 2)
## [1] -3 -2 -1 0 1 2 3 4 5 6 7
(x * 2)
## [1] -10 -8 -6 -4 -2 0 2 4 6 8 10
행렬(matrix)
행렬은 함수 matrix()를 이용해 생성할 수 있다.
v <- seq(5, 60, by = 5) #5부터 60까지 5씩 증가하는 정수벡터 작성
matrix(v, ncol = 4) #열의 수가 4인 행렬
| 5 | 20 | 35 | 50 |
| 10 | 25 | 40 | 55 |
| 15 | 30 | 45 | 60 |
matrix(v, nrow = 4) #행의 수가 4인 행렬
| 5 | 25 | 45 |
| 10 | 30 | 50 |
| 15 | 35 | 55 |
| 20 | 40 | 60 |
리스트(list)
리스트는 벡터나 행렬을 한꺼번에 취급할 수 있는 형식이다. 복수의 관련된 벡터나 행렬을 하나의 리스트에 정리하여 보존할 수 있으며 list()를 이용하여 작성한다. 함수의 인수 값은 리스트에 포함되는 벡터나 행렬을 지정하거나, 데이터의 이름을 refer하여 사용할 수 있다.
#(3,2,1)을 3번 반복하는 벡터 작성
myvector <- rep(c(3, 2, 1), 3)
mymatrix <- matrix(1:12, ncol = 4)
mynumber <- 7
my_list <- list(myvector, mymatrix, mynumber)
my_list
## [[1]]
## [1] 3 2 1 3 2 1 3 2 1
##
## [[2]]
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
##
## [[3]]
## [1] 7
리스트에 이름을 주고 싶다면, 다음과 같이 이름을 부여할 수 있다.
names(my_list) <- c("vector", "matirx", "number")
my_list
## $vector
## [1] 3 2 1 3 2 1 3 2 1
##
## $matirx
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
##
## $number
## [1] 7
리스트에서 “myvector” 인자를 고르고 싶다면:
my_list[[1]]
## [1] 3 2 1 3 2 1 3 2 1
혹은
my_list[["vector"]]
## [1] 3 2 1 3 2 1 3 2 1
“myvector”의 세 번째 수를 고르고 싶다면:
my_list[[1]][3] #or my_list[["vector"]][3]
## [1] 1
데이터프레임(data frame)
데이터 프레임은 R에서 분석시 가장 빈번히 사용되는 형식이다. 외부파일을 R으로 불러올 때 사용하는 함수 군은 불러들인 데이터를 모두 데이터프레임으로 변환시키기 때문이다. 데이터 프레임은 리스트의 한 종류로 리스트에 포함된 모든 값이 길이가 같은 벡터일 때, 혹은 행의 수, 열의 수가 같은 행렬에 한해 그 리스트를 data.frame()을 이용하여 변환시킬 수 있다.
v1 <- 1:5
v2 <- 6:10
my_list <- list(dataA = v1, dataB = v2)
my_list
## $dataA
## [1] 1 2 3 4 5
##
## $dataB
## [1] 6 7 8 9 10
data.frame(my_list)
| dataA | dataB |
|---|---|
| 1 | 6 |
| 2 | 7 |
| 3 | 8 |
| 4 | 9 |
| 5 | 10 |
a <- c(10,30,15)
b <- c("Bob","John","Ben")
df <- data.frame(a,b, stringsAsFactors = FALSE) #want strings to be characters not factors
df
| a | b |
|---|---|
| 10 | Bob |
| 30 | John |
| 15 | Ben |
열의 이름은 리스트의 참조용 이름이 사용되며 행의 이름은 함수 rownames(), 열의 이름은 함수 colnames()로 확인할 수 있다. 자유롭게 변경 가능하다.
rownames(df) # 행 이름 확인
## [1] "1" "2" "3"
colnames(df) # 열 이름 확인
## [1] "a" "b"
rownames(df) <- c("one", "two", "three") # 행 이름 변경
df
| a | b | |
|---|---|---|
| one | 10 | Bob |
| two | 30 | John |
| three | 15 | Ben |
names(df) <- c("age","friend") # 열 이름 변경
df
| age | friend | |
|---|---|---|
| one | 10 | Bob |
| two | 30 | John |
| three | 15 | Ben |
factor와 level
벡터의 특수한 형태로 설문조사의 선택문항 등 카테고리를 저장할 수 있는 벡터를 factor라고 부른다. factor는 벡터를 기본으로 하여 factor()를 이용하여 작성할 수 있다.
xv <- c("A", "C", "B", "A", "A", "C", "B")
x <- factor(xv, levels = c("A", "B", "C"))
xv
## [1] "A" "C" "B" "A" "A" "C" "B"
x
## [1] A C B A A C B
## Levels: A B C
factor()에서는 벡터와 levels을 인수로 받는다. level은 factor에 포함된 카테고리의 목록이라고 볼 수 있다. 그렇기 때문에 R에서 레벨 정보를 이용하여 카테고리별 단순 집계나 그래프를 만들어야 하는 경우 카테고리 변수를 벡터가 아닌 factor화 해두는 것이 좋다. factor와 벡터는 외형상 큰 차이가 없어 보이지만 R은 이 둘을 매우 다르게 취급한다. factor은 레벨의 순서에 따라 그 값이 numerically 존재하지만, 문자형 벡터는 그렇지 않다.
as.numeric(x)
## [1] 1 3 2 1 1 3 2
as.numeric(xv)
## Warning: NAs introduced by coercion
## [1] NA NA NA NA NA NA NA
Soln: The answer is b. See below.
x<-1:4
x
## [1] 1 2 3 4
names(x) <- letters[1:4]
x
## a b c d
## 1 2 3 4
x[1:2] <- 2:1
x
## a b c d
## 2 1 3 4
x["a"] <- 100
x[x==100] <- NA
x
## a b c d
## NA 1 3 4
solution: the answer is d.
rep(seq(0,6,by=2),each=5)
## [1] 0 0 0 0 0 2 2 2 2 2 4 4 4 4 4 6 6 6 6 6
rep(1:5, times=4)
## [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
rep(1:5, times=4) + rep(0:3, each=5)
## [1] 1 2 3 4 5 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8
file path는 원하는 파일에 다다르기 위해 그 파일이 속한 폴더들의 연속으로 이루어져 있다.
표준 파일 형식의 예시:
/Users/kaplan/Downloads/0021_001.pdf. 여기서 파일 이름은 0021_001, 파일의 확장자는 .pdf, 그리고 파일은 Users폴더에 위치한 kaplan 폴더에 위치한 Downloads 폴더에 들어있다. 가장 처음에 나오는 / 는 “on this computer”라는 의미를 가진다.
위를 다음과 같이 쓸 수도 있다. ~/Downloads/0021_001.pdf 이 때, ~/ 는 “in my home directory”를 의미한다.
R에서 file.choose() — 오직 console에서만 이용가능, Rmd 파일에서는 안 됨. — 는 파일 브라우져를 열어준다.
몇 가지 흔하게 사용되는 파일 확장자를 알아보면:
.png pictures
.jpg or .jpeg for photographs
.csv or .Rdata for data files
.Rmd for the human editable text of a document (called R Markdown)
.html for web pages themselves
.dbf for a certain kind of database