Sophisticated data structures

R은 데이터의 저장과 조작을 위한 정교한 구조를 제공한다.

이러한 구조는 데이터 표현, 조작 및 분석을 단순화한다.

Factor

Factor는 미리 정의된 값만을 포함할 수 있는 벡터로, 범주형 데이터를 저장하는 데 사용된다.

Factor는 두 가지 속성을 사용하는 정수 벡터 위에 구축된다: class “factor”는 이를 일반 정수 벡터와 다르게 동작하게 만들며, levels는 허용된 값의 집합을 정의한다.

hair <- c("blonde", "black", "brown", "brown", "black", "gray", "none")
is.character(hair)
## [1] TRUE
is.factor(hair)
## [1] FALSE

위에서 hair는 factor는 아니며, character 벡터이다.

이것을 factor로 바꿔보자.

hair <- factor(hair)
is.factor(hair)
## [1] TRUE
class(hair)
## [1] "factor"
levels(hair)
## [1] "black"  "blonde" "brown"  "gray"   "none"

table() 함수는 팩터의 각 수준(level)이 나타나는 횟수를 계산한다.

table(hair)
## hair
##  black blonde  brown   gray   none 
##      2      1      2      1      1

levels 인수를 사용하여 수준(level)을 지정한다.

hair <- factor(hair, levels=c("black", "blonde", "brown", "gray", "white", "none"))
table(hair)
## hair
##  black blonde  brown   gray  white   none 
##      2      1      2      1      0      1

수준(level)에 없는 값을 사용할 수 없다.

hair[2] <- "green"
## Warning in `[<-.factor`(`*tmp*`, 2, value = "green"): invalid factor level, NA
## generated
hair
## [1] blonde <NA>   brown  brown  black  gray   none  
## Levels: black blonde brown gray white none
# reset
hair[2] <- "black"

사실, factor의 타입은 정수이다.

typeof(hair)
## [1] "integer"

각 레벨을 정수화하여 표현해 볼 수 있다.

as.numeric(hair)
## [1] 2 1 3 3 1 4 6

Dataframe

Dataframe은 R에서 데이터를 저장하는 가장 일반적인 방법이다.

creating data.frame

data.frame()을 사용하여 데이터프레임을 생성하며, 이 함수는 이름이 지정된 벡터들이나 기존의 데이터프레임을 입력으로 받는다:

data.frame(col1=x1, col2=x2, ..., df1, df2, ...)
  • col1col2는 열 이름이다.

  • x1x2는 길이가 같은 벡터들이다.

  • df1df2는 데이터프레임이며, 이들의 열은 x1, x2와 같은 길이여야 한다.

df <- data.frame(x = 2:4, y = c("a", "b", "c"))
str(df)    #결과는 3개의 행과 2개의 열이 있음.
## 'data.frame':    3 obs. of  2 variables:
##  $ x: int  2 3 4
##  $ y: chr  "a" "b" "c"
print(df)
##   x y
## 1 2 a
## 2 3 b
## 3 4 c

data.frame()은 R 3.x 및 2.x에서 문자열을 팩터로 변환한다.

이 동작을 억제하려면 stringsAsFactors = FALSE를 사용하라:

(R 4.x에서는 stringsAsFactors = FALSE가 기본값으로 설정되어 있다.)

df <- data.frame(
  x = 2:4,
  y = c("a", "b", "c"),
  stringsAsFactors = FALSE)

# R에서 객체의 구조를 간략하게 보여준다.
str(df)
## 'data.frame':    3 obs. of  2 variables:
##  $ x: int  2 3 4
##  $ y: chr  "a" "b" "c"
df <- data.frame(
  x = 2:4,
  y = c("a", "b", "c"),
  stringsAsFactors = TRUE)     #factor로 바꾸고 싶으면 TRUE로
str(df)
## 'data.frame':    3 obs. of  2 variables:
##  $ x: int  2 3 4
##  $ y: Factor w/ 3 levels "a","b","c": 1 2 3
typeof(df)
## [1] "list"
class(df)
## [1] "data.frame"
is.data.frame(df)
## [1] TRUE
  • typeof(df): 이 함수는 객체 df의 내부 저장 모드를 반환한다. 데이터프레임의 경우, 보통 "list"를 반환한다. 이는 데이터프레임이 내부적으로 벡터들의 리스트라는 것을 의미한다.

  • class(df): 이 함수는 객체 df의 클래스 속성을 반환한다. 데이터프레임의 경우, "data.frame"을 반환하여 객체가 R에서 데이터프레임으로 인식되고 있음을 나타낸다.

  • is.data.frame(df): 이 함수는 객체 df가 데이터프레임인지 확인한다. df가 데이터프레임이면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환한다.

Dataframe들을 합치기:

cbind(df, data.frame(z = 3:1))
##   x y z
## 1 2 a 3
## 2 3 b 2
## 3 4 c 1
rbind(df, data.frame(x = 10, y = "z"))
##    x y
## 1  2 a
## 2  3 b
## 3  4 c
## 4 10 z

read.table

파일로부터 데이터프레임을 생성하기 위해 read.table을 사용할 수 있다.

다음의 가상의 데이터를 고려해 보자.

Plot Tree Species Diameter Height
2 1 DF 39 20.5
2 2 WL 48 33.0
3 2 GF 52 30.0

대형 데이터프레임은 보통 파일로부터 read.table을 사용하여 R로 읽어들인다.

read.table(file, header=FALSE, sep="")
  • file
    • 읽어들일 파일 이름으로, 상대 경로나 절대 경로를 사용할 수 있다.
    • 각 행에 동일한 수의 값이 있어야 한다.
    • 값들은 서로 다른 모드를 가질 수 있지만, 각 행에서 모드의 패턴은 동일해야 한다.
  • header
    • 파일의 첫 번째 줄이 변수 이름인지 여부를 지정한다.
  • sep
    • 각 행에서 값을 구분하는 데 사용되는 문자를 지정한다.
    • 기본값인 ""는 특수 해석으로, 가변적인 양의 공백(공백, 탭, 줄바꿈)이 값을 구분할 수 있음을 의미한다.

more about read.table

read.table의 두 가지 일반적으로 사용되는 변형

  • read.csv(file)
    • 쉼표로 구분된 데이터를 위한 함수(4,5,6,7,8,9)
    • read.table(file, header=TRUE, sep=",")와 동등하다
  • read.delim(file)
    • 탭으로 구분된 데이터를 위한 함수(4 5 6 7 8 9)
    • read.table(file, header=TRUE, sep="\t")와 동등하다

read csv file

ufc.csv는 쉼표로 구분되어 있으며, 헤더 라인이 존재한다.

  • 아래의 코드에서 "the path of ufc.csv"ufc.csv 파일의 위치를 지정한다.
ufc <- read.csv("the path of ufc.csv")
  • 예를 들어, ufc.csv 파일이 현재 작업 디렉토리 아래의 /data/에 존재한다면 다음과 같이 작성한다.

    • 아래에서 .는 현재 작업 디렉토리를 의미한다.

    • 현재 작업 디렉토리는 getwd()를 code chunk 안에서 실행하여 확인할 수 있다.

ufc <- read.csv("./data/ufc.csv")    # .을 현재 디렉토리를 의미(SSUR)
                                     # ..은 한 단계 위를 의미
#현재 작업 디렉토리를 확인
getwd()

내용을 살펴보기 위해 headtail 함수를 사용해 보자.

head(ufc)
##   plot tree species dbh.cm height.m
## 1    2    1      DF     39     20.5
## 2    2    2      WL     48     33.0
## 3    3    2      GF     52     30.0
## 4    3    5      WC     36     20.7
## 5    3    8      WC     38     22.5
## 6    4    1      WC     46     18.0
tail(ufc)
##     plot tree species dbh.cm height.m
## 331  143    1      GF   28.0     21.0
## 332  143    2      GF   33.0     20.5
## 333  143    7      WC   47.8     20.5
## 334  144    1      GF   10.2     16.0
## 335  144    2      DF   31.5     22.0
## 336  144    4      WL   26.5     25.0

각 열은 고유한 이름을 가지며, 우리는 $를 사용하여 names로 해당 변수를 추출할 수 있다.

ufc$plot[1:10]
##  [1] 2 2 3 3 3 4 4 5 5 6
x <- ufc$height.m
x[1:5]
## [1] 20.5 33.0 30.0 20.7 22.5

accessing element in data.frame

우리는 [[ ]]를 사용하여 열을 추출할 수 있다.

  • ufc$height.m, ufc[[5]], ufc[["height.m"]]은 모두 동등하다.

  • 결과는 벡터이다.

x1 <- ufc[["height.m"]]  # x1은 벡터
x1[1:5]
## [1] 20.5 33.0 30.0 20.7 22.5
x2 <- ufc[[5]]   # x2는 벡터
x2[1:5]
## [1] 20.5 33.0 30.0 20.7 22.5

행렬 인덱싱을 사용하여 데이터프레임의 요소를 직접 추출할 수 있다.

# the result is a vector
ufc[1:5, 5, drop=FALSE] #drop=FALSE를 써서 데이터프레임으로로 달라짐.
##   height.m
## 1     20.5
## 2     33.0
## 3     30.0
## 4     20.7
## 5     22.5

데이터프레임에서 여러 변수를 선택하려면 [ ]를 사용한다.

  • ufc[4:5]ufc[c("dbh.cm", "height.m")]와 동등하다. 둘다 ufc[]안에 벡터를 넣음.

  • [ ]는 데이터프레임의 타입을 유지한다.

#diam.height and z are data.frame
diam.height <- ufc[4:5]    
(z <- diam.height[1:5, ])
##   dbh.cm height.m
## 1     39     20.5
## 2     48     33.0
## 3     52     30.0
## 4     36     20.7
## 5     38     22.5
is.data.frame(diam.height)
## [1] TRUE
# diam.height1는 data.frame이다. 하나짜리도 data.frame으로 인식한다.
diam.height1 <- ufc[5]
is.data.frame(diam.height1)
## [1] TRUE
# z1은 데이터프레임이 아닌 벡터이다. 이는 [ , ]가 단순화(중요!!)하기 때문이다.
z1 <- diam.height1[1:5, ]
is.data.frame(z1)
## [1] FALSE
  • [[ ]]를 사용하여 열을 선택하면 추출되는 객체의 타입이 유지된다.

  • 반면, [ ]는 추출이 이루어지는 객체의 타입을 유지한다.

typeof(ufc)
## [1] "list"
typeof(ufc[5])
## [1] "list"
# numeric vector
typeof(ufc[[5]])
## [1] "double"

또한, [,]는 가능하다면 데이터 타입을 단순화하는 경향이 있다.

typeof(ufc[1:5, 5])
## [1] "double"

아래의 경우, 단순화는 불가능하므로 원래의 데이터프레임 타입이 유지된다.

# In this case, simplification is impossible, and original data.frame type is preserved.
typeof(ufc[1:5, 4:5])
## [1] "list"
class(ufc[1:5, 4:5])
## [1] "data.frame"

http://r4ds.had.co.nz/vectors.html

create new variable

데이터프레임 내에 변수를 새로 생성하고 이름을 지정한 후 값을 할당하여 생성할 수 있다.

ufc$volume.m3 <- pi * (ufc$dbh.cm / 200)^2 * ufc$height / 2
mean(ufc$volume.m3)
## [1] 1.93294

name of column

  • names(df)는 데이터프레임 df의 이름을 반환한다.

  • df의 이름을 변경하려면 문자열 벡터를 names(df)에 전달한다.

(ufc.names <- names(ufc))
## [1] "plot"      "tree"      "species"   "dbh.cm"    "height.m"  "volume.m3"
names(ufc) <- c("P", "T", "S", "D", "H", "V")
names(ufc)
## [1] "P" "T" "S" "D" "H" "V"
names(ufc) <- ufc.names

subset

subset은 데이터프레임의 행을 선택하는 데 유용한 도구이다. * x %in% y는 논리 벡터를 반환하며, 만약 x[i]y에 포함되어 있으면 i번째 요소는 TRUE이다.

ufc$species %in% c("DF", "GF")
##   [1]  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE
##  [13] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE
##  [25]  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE
##  [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
##  [49]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE
##  [61] FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE  TRUE
##  [73] FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE
##  [85] FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE
##  [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
## [109] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE
## [121] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE
## [133] FALSE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE FALSE FALSE  TRUE
## [145]  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE
## [157]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
## [169]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE
## [181] FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE
## [193] FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE  TRUE
## [205]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE FALSE
## [217] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
## [229]  TRUE  TRUE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE
## [241]  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
## [253] FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE FALSE
## [265] FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE
## [277]  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
## [289] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE
## [301]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE
## [313]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE FALSE FALSE
## [325] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
fir.height <- subset(ufc, 
                     subset=species %in% c("DF", "GF"), 
                     select = c(plot, tree, height.m, species))
head(fir.height)
##    plot tree height.m species
## 1     2    1     20.5      DF
## 3     3    2     30.0      GF
## 7     4    2     17.0      DF
## 8     5    2     29.3      DF
## 9     5    4     29.0      GF
## 10    6    1     26.0      DF

write a dataframe

write.table(x, file="", append=FALSE, sep=" ", row.names=TRUE, col.names=TRUE)
  • x는 작성할 데이터프레임이다.

  • file은 작성할 파일의 주소이다.

  • append는 추가 여부를 나타낸다.

  • sep는 값을 구분하는 데 사용되는 문자이다.

  • row.name은 행 이름을 첫 번째 열로 포함할지 여부를 나타낸다.

  • col.names는 열 이름을 첫 번째 행으로 포함할지 여부를 나타낸다.

write.table(fir.height, "data/mydf.csv", sep=",")

Another method to read and write tabular data

  • read_csv()read_tsv()readr 패키지의 일반 함수 read_delim()의 특별한 경우이다.

  • 각각 쉼표로 구분된 값과 탭으로 구분된 값의 가장 일반적인 평면 파일 데이터를 읽는 데 유용하다.

  • 아래 코드에서 ufc_tibble은 더 나은 출력 방식을 제공하는 데이터 프레임으로, 대규모 데이터 세트를 다룰 때 유용하다.

library(readr)
ufc_tibble <- read_csv("./data/ufc.csv")
## Rows: 336 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): species
## dbl (4): plot, tree, dbh.cm, height.m
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
ufc_tibble
## # A tibble: 336 × 5
##     plot  tree species dbh.cm height.m
##    <dbl> <dbl> <chr>    <dbl>    <dbl>
##  1     2     1 DF        39       20.5
##  2     2     2 WL        48       33  
##  3     3     2 GF        52       30  
##  4     3     5 WC        36       20.7
##  5     3     8 WC        38       22.5
##  6     4     1 WC        46       18  
##  7     4     2 DF        25       17  
##  8     5     2 DF        54.9     29.3
##  9     5     4 GF        51.8     29  
## 10     6     1 DF        40.9     26  
## # ℹ 326 more rows

List

Example

(my.list <- list("one", TRUE, 3, c("f", "o", "u", "r")))
## [[1]]
## [1] "one"
## 
## [[2]]
## [1] TRUE
## 
## [[3]]
## [1] 3
## 
## [[4]]
## [1] "f" "o" "u" "r"
str(my.list)
## List of 4
##  $ : chr "one"
##  $ : logi TRUE
##  $ : num 3
##  $ : chr [1:4] "f" "o" "u" "r"
my.list[[2]]
## [1] TRUE
mode(my.list[[2]])
## [1] "logical"
my.list[2]
## [[1]]
## [1] TRUE
mode(my.list[2])
## [1] "list"
my.list[[4]]
## [1] "f" "o" "u" "r"
my.list[[4]][1]
## [1] "f"
my.list[4][1]
## [[1]]
## [1] "f" "o" "u" "r"

리스트를 출력할 때,

  • R은 리스트 요소를 나타내기 위해 이중 대괄호 [[1]], [[2]], 등을 사용한다.

  • 그런 다음 벡터 요소를 나타내기 위해 단일 대괄호 [1], [2], 등을 사용한다.

# list can contain other list
my.list2 <- list("a", c(5,6,7), my.list)
str(my.list2)
## List of 3
##  $ : chr "a"
##  $ : num [1:3] 5 6 7
##  $ :List of 4
##   ..$ : chr "one"
##   ..$ : logi TRUE
##   ..$ : num 3
##   ..$ : chr [1:4] "f" "o" "u" "r"
my.list2[3]
## [[1]]
## [[1]][[1]]
## [1] "one"
## 
## [[1]][[2]]
## [1] TRUE
## 
## [[1]][[3]]
## [1] 3
## 
## [[1]][[4]]
## [1] "f" "o" "u" "r"
str(my.list2[3])
## List of 1
##  $ :List of 4
##   ..$ : chr "one"
##   ..$ : logi TRUE
##   ..$ : num 3
##   ..$ : chr [1:4] "f" "o" "u" "r"
#error
my.list2[3][[4]]
my.list2[[3]]
## [[1]]
## [1] "one"
## 
## [[2]]
## [1] TRUE
## 
## [[3]]
## [1] 3
## 
## [[4]]
## [1] "f" "o" "u" "r"
my.list2[[3]][4]
## [[1]]
## [1] "f" "o" "u" "r"
my.list2[[3]][[4]]
## [1] "f" "o" "u" "r"

name of elements of list

리스트가 생성될 때 리스트의 요소에 이름을 지정할 수 있다.

my.list <- list(first = "one", second=TRUE, third=3, fourth = c("f", "o", "u", "r"))
names(my.list)
## [1] "first"  "second" "third"  "fourth"
my.list$second
## [1] TRUE

리스트의 요소는 names 속성을 통해 이름을 지정할 수 있다.

names(my.list) <- c("Fi", "Se", "Th", "Fo")   #새로운 이름 
my.list$Se     
## [1] TRUE
my.list$"Fi"
## [1] "one"
my.list[["Fi"]]
## [1] "one"

Simplify vs. Preserving

type 단순화(Simplifying) 보존(Preserving)
vector x[[1]] x[1]
array(matrix) x[1, ], x[, 1] x[1, , drop = F], x[, 1, drop = F]
list x[[1]], x$a, x[["a"]] x[1], x["a"]
data.frame x[, 1] x[1, ], x[, 1, drop = F]

데이터프레임은 리스트라는 점에 유의하라. 따라서 리스트에 대한 단순화 및 보존 규칙은 데이터프레임에도 적용된다.

http://adv-r.had.co.nz/Subsetting.html

list as output of function

많은 함수들이 출력으로 리스트 객체를 생성한다.

  • 예를 들어, 최소제곱 회귀분석을 수행할 때, 회귀분석 결과는 리스트 객체로 반환된다.

  • 회귀분석의 복잡한 결과를 표현하기 위해 유연한 list 객체를 활용하는 것.

  • 이러한 객체들은 리스트 연산을 사용하여 추가적인 작업을 수행할 수 있다.

  • 아래에서 lm 함수는 선형 회귀 모델을 적합하는 함수이다.

    • ~ 기호는 R에서 모델을 정의할 때 사용되며 왼쪽이 종속 변수, 오른쪽이독립 변수이다.
lm.xy <- lm(y~x, data=data.frame(x=1:5, y=1:5))
typeof(lm.xy)
## [1] "list"
# 요소들의 이름 출력
names(lm.xy)
##  [1] "coefficients"  "residuals"     "effects"       "rank"         
##  [5] "fitted.values" "assign"        "qr"            "df.residual"  
##  [9] "xlevels"       "call"          "terms"         "model"
  • str 함수는 리스트나 데이터프레임을 요약하는 데 사용할 수 있다:

    lm.xy$coefficients
    ##  (Intercept)            x 
    ## 1.191616e-15 1.000000e+00
str(lm.xy)
## List of 12
##  $ coefficients : Named num [1:2] 1.19e-15 1.00
##   ..- attr(*, "names")= chr [1:2] "(Intercept)" "x"
##  $ residuals    : Named num [1:5] -4.83e-16 8.35e-16 -2.10e-16 -1.54e-16 1.20e-17
##   ..- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
##  $ effects      : Named num [1:5] -6.71 3.16 1.11e-16 4.44e-16 8.88e-16
##   ..- attr(*, "names")= chr [1:5] "(Intercept)" "x" "" "" ...
##  $ rank         : int 2
##  $ fitted.values: Named num [1:5] 1 2 3 4 5
##   ..- attr(*, "names")= chr [1:5] "1" "2" "3" "4" ...
##  $ assign       : int [1:2] 0 1
##  $ qr           :List of 5
##   ..$ qr   : num [1:5, 1:2] -2.236 0.447 0.447 0.447 0.447 ...
##   .. ..- attr(*, "dimnames")=List of 2
##   .. .. ..$ : chr [1:5] "1" "2" "3" "4" ...
##   .. .. ..$ : chr [1:2] "(Intercept)" "x"
##   .. ..- attr(*, "assign")= int [1:2] 0 1
##   ..$ qraux: num [1:2] 1.45 1.12
##   ..$ pivot: int [1:2] 1 2
##   ..$ tol  : num 1e-07
##   ..$ rank : int 2
##   ..- attr(*, "class")= chr "qr"
##  $ df.residual  : int 3
##  $ xlevels      : Named list()
##  $ call         : language lm(formula = y ~ x, data = data.frame(x = 1:5, y = 1:5))
##  $ terms        :Classes 'terms', 'formula'  language y ~ x
##   .. ..- attr(*, "variables")= language list(y, x)
##   .. ..- attr(*, "factors")= int [1:2, 1] 0 1
##   .. .. ..- attr(*, "dimnames")=List of 2
##   .. .. .. ..$ : chr [1:2] "y" "x"
##   .. .. .. ..$ : chr "x"
##   .. ..- attr(*, "term.labels")= chr "x"
##   .. ..- attr(*, "order")= int 1
##   .. ..- attr(*, "intercept")= int 1
##   .. ..- attr(*, "response")= int 1
##   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##   .. ..- attr(*, "predvars")= language list(y, x)
##   .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
##   .. .. ..- attr(*, "names")= chr [1:2] "y" "x"
##  $ model        :'data.frame':   5 obs. of  2 variables:
##   ..$ y: int [1:5] 1 2 3 4 5
##   ..$ x: int [1:5] 1 2 3 4 5
##   ..- attr(*, "terms")=Classes 'terms', 'formula'  language y ~ x
##   .. .. ..- attr(*, "variables")= language list(y, x)
##   .. .. ..- attr(*, "factors")= int [1:2, 1] 0 1
##   .. .. .. ..- attr(*, "dimnames")=List of 2
##   .. .. .. .. ..$ : chr [1:2] "y" "x"
##   .. .. .. .. ..$ : chr "x"
##   .. .. ..- attr(*, "term.labels")= chr "x"
##   .. .. ..- attr(*, "order")= int 1
##   .. .. ..- attr(*, "intercept")= int 1
##   .. .. ..- attr(*, "response")= int 1
##   .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##   .. .. ..- attr(*, "predvars")= language list(y, x)
##   .. .. ..- attr(*, "dataClasses")= Named chr [1:2] "numeric" "numeric"
##   .. .. .. ..- attr(*, "names")= chr [1:2] "y" "x"
##  - attr(*, "class")= chr "lm"

apply family

tapply(X, INDEX, FUN, ...)

tapply example

tapply를 사용하여 종(species)별로 평균 키(height)를 구하는 방법은 다음과 같다:

ufc <- read.csv("./data/ufc.csv")
ufc$volume.m3 <- pi * (ufc$dbh.cm / 200)^2 * ufc$height / 2

tapply(ufc$height.m, ufc$species, mean)
##       DF       GF       WC       WL 
## 25.30000 24.34322 23.48777 25.47273
tapply(ufc$height.m, ufc$species, mean)
##       DF       GF       WC       WL 
## 25.30000 24.34322 23.48777 25.47273
mean(ufc[ufc$species == "DF", 'height.m'])  #위의 DF를 나타냄!
## [1] 25.3

결과 반올림:

round(tapply(ufc$height.m, ufc$species, mean), digits=1)
##   DF   GF   WC   WL 
## 25.3 24.3 23.5 25.5

각 종(species)별로 샘플 수를 확인하는 방법은 다음과 같다:

tapply(ufc$species, ufc$species, length)
##  DF  GF  WC  WL 
##  57 118 139  22
# the same result
tapply(ufc$height.m, ufc$species, length)
##  DF  GF  WC  WL 
##  57 118 139  22
tapply(ufc$height.m, ufc$species, max)
##   DF   GF   WC   WL 
## 42.0 47.0 40.0 42.5

Example : tapply

tapply를 사용하여 벡터의 요소 수를 계산할 수 있다:

x <- c(1,2,3,4,5,4,6,2,5,6,5,3,4,1,4,5,6,7,2,2,6,7,9,3,5)
tapply(X = x, INDEX = x, FUN = length)   #1이 몇개? 2가 몇개?~~ 
## 1 2 3 4 5 6 7 9 
## 2 4 3 4 5 4 2 1

위 내용은 다음과 거의 동일하다:

table(x)
## x
## 1 2 3 4 5 6 7 9 
## 2 4 3 4 5 4 2 1
y <- x %% 2
tapply(X = x, INDEX = y, FUN = length)
##  0  1 
## 12 13
y <- x %% 2
tapply(X = x, INDEX = y, FUN = max)
## 0 1 
## 6 9

lapply and sapply

  • lapply(X, FUN, ...)는 리스트 X의 각 요소에 함수 FUN을 적용하고 리스트로 반환한다.

  • sapply(X, FUN, ...)X의 각 요소에 함수 FUN을 적용한다. X는 리스트나 벡터일 수 있으며, 기본적으로 결과를 벡터나 행렬로 반환하려고 시도한다. 만약 이것이 의미가 없다면, 리스트로 반환한다.

나무의 평균 직경, 높이 및 부피를 구하려면:

ufc[4:6]
##     dbh.cm height.m   volume.m3
## 1     39.0     20.5  1.22445537
## 2     48.0     33.0  2.98576966
## 3     52.0     30.0  3.18557495
## 4     36.0     20.7  1.05350168
## 5     38.0     22.5  1.27587932
## 6     46.0     18.0  1.49571226
## 7     25.0     17.0  0.41724277
## 8     54.9     29.3  3.46794495
## 9     51.8     29.0  3.05574706
## 10    40.9     26.0  1.70796847
## 11    29.0     22.0  0.72657184
## 12    29.4     32.0  1.08618681
## 13    68.5     26.0  4.79086989
## 14    63.0     33.0  5.14345476
## 15    46.6     27.5  2.34511645
## 16    55.3     30.0  3.60272740
## 17    46.2     31.3  2.62354293
## 18    27.1     27.0  0.77868576
## 19    40.0     27.0  1.69646003
## 20    36.3     28.0  1.44887583
## 21    42.0     33.0  2.28597989
## 22    37.5     29.8  1.64565459
## 23    38.3     27.1  1.56108562
## 24    22.3     21.5  0.41986345
## 25    22.5     22.6  0.44929684
## 26    21.8     18.0  0.33592736
## 27    15.1     15.5  0.13878594
## 28    23.0     20.0  0.41547563
## 29    32.0     22.5  0.90477868
## 30    52.5     29.0  3.13889285
## 31    10.5      5.0  0.02164754
## 32    75.0     32.0  7.06858347
## 33    89.5     35.0 11.00966237
## 34    30.0     25.0  0.88357293
## 35    32.0     31.0  1.24658396
## 36    29.5     27.0  0.92271521
## 37    42.5     22.5  1.59595361
## 38    83.0     35.0  9.46856391
## 39    39.0     24.0  1.43350873
## 40    25.0     28.0  0.68722339
## 41    22.5     26.0  0.51689017
## 42    21.0     22.5  0.38965566
## 43    12.5     14.0  0.08590292
## 44    24.0     19.0  0.42976988
## 45    27.5     23.0  0.68305097
## 46    32.5     26.5  1.09918927
## 47    11.5      8.0  0.04154756
## 48    36.5     31.5  1.64799606
## 49    28.2     25.0  0.78072504
## 50    19.8     16.0  0.24632600
## 51    21.5     17.5  0.31766901
## 52    38.9     30.0  1.78270853
## 53    44.3     37.5  2.89000508
## 54    26.3     28.0  0.76055288
## 55    34.3     23.5  1.08571538
## 56    26.2     21.0  0.56608515
## 57    40.5     22.0  1.41707427
## 58    19.9     17.0  0.26437170
## 59    14.6     11.0  0.09207851
## 60    39.8     36.5  2.27048634
## 61    40.1     37.5  2.36799019
## 62    23.0     13.0  0.27005916
## 63    37.1     21.0  1.13508138
## 64    21.5     19.0  0.34489779
## 65    14.8     15.0  0.12902521
## 66    68.6     28.0  5.17447328
## 67    13.9     12.5  0.09484174
## 68    18.5     19.0  0.25536240
## 69    14.2     16.0  0.12669415
## 70    48.7     25.0  2.32840121
## 71    52.7     30.0  3.27191770
## 72    32.2     26.0  1.05863190
## 73    64.0     27.0  4.34293768
## 74    58.5     34.0  4.56930907
## 75    24.3     13.0  0.30145034
## 76    29.6     32.0  1.10101513
## 77    43.0     29.0  2.10569175
## 78    52.2     31.0  3.31713071
## 79    27.2     23.0  0.66822932
## 80    34.0     23.0  1.04410832
## 81    40.4     26.0  1.66646411
## 82    11.1      9.5  0.04596523
## 83    20.7     25.0  0.42066907
## 84    28.3     31.0  0.97497718
## 85    49.6     23.0  2.22203592
## 86    44.9     25.0  1.97921319
## 87    42.5     30.0  2.12793815
## 88    71.9     32.0  6.49632352
## 89    56.5     27.5  3.44738252
## 90    31.1     25.0  0.94955620
## 91    42.5     27.0  1.91514433
## 92    35.2     27.0  1.31373865
## 93    42.1     30.0  2.08807134
## 94    14.0     20.0  0.15393804
## 95    17.7     19.0  0.23375452
## 96    33.5     20.0  0.88141309
## 97    40.5     22.0  1.41707427
## 98    29.5     28.0  0.95688985
## 99    69.0     30.0  5.60892098
## 100   46.5     26.0  2.20769533
## 101   42.5     29.0  2.05700688
## 102   30.5     21.0  0.76714747
## 103   30.5     25.0  0.91327080
## 104   37.8     28.0  1.57109164
## 105   49.7     30.0  2.91000622
## 106   37.7     28.0  1.56278998
## 107   32.5     25.0  1.03697101
## 108   26.2     23.0  0.61999802
## 109   31.0     26.0  0.98119793
## 110   38.5     27.0  1.57161118
## 111   94.0     36.0 12.49160071
## 112  101.5     39.0 15.77816805
## 113   35.0     34.0  1.63559168
## 114   31.5     24.5  0.95465638
## 115   59.0     31.2  4.26499477
## 116   35.0     34.0  1.63559168
## 117   31.5     24.5  0.95465638
## 118   59.0     31.2  4.26499477
## 119   60.2     32.0  4.55410298
## 120   18.0     22.0  0.27991591
## 121   47.1     30.0  2.61350271
## 122   63.7     28.5  4.54133574
## 123   63.8     34.0  5.43475737
## 124   12.5     10.0  0.06135923
## 125   15.5     11.5  0.10849785
## 126   45.5     31.5  2.56090361
## 127   60.0     33.0  4.66526509
## 128   20.0     17.5  0.27488936
## 129   32.0     30.0  1.20637158
## 130   42.0     30.5  2.11279960
## 131   25.5     22.5  0.57454330
## 132   27.9     15.0  0.45852134
## 133   52.8     31.5  3.44856395
## 134   23.4     18.0  0.38704736
## 135   47.7     31.0  2.76986331
## 136   61.3     25.0  3.68910353
## 137   37.7     24.2  1.35069705
## 138   16.5     17.2  0.18388920
## 139   39.7     25.3  1.56589061
## 140   80.4     32.0  8.12310303
## 141   99.8     42.0 16.42745396
## 142   45.6     32.5  2.65382898
## 143   38.7     27.0  1.58798202
## 144   50.2     37.0  3.66158436
## 145   68.3     39.0  7.14440227
## 146   42.2     32.8  2.29381628
## 147   34.4     25.7  1.19429027
## 148   18.5     20.2  0.27149055
## 149   54.3     30.5  3.53150141
## 150   86.1     40.2 11.70286625
## 151   51.9     32.5  3.43777906
## 152   25.8     22.8  0.59598337
## 153   40.0     21.1  1.32575210
## 154   37.4     20.0  1.09858354
## 155   10.4     16.5  0.07008265
## 156   24.8     19.0  0.45889872
## 157   33.5     27.5  1.21194300
## 158   25.0     23.5  0.57677678
## 159   14.1     14.0  0.10930151
## 160   15.7     17.5  0.16939369
## 161   25.0     19.0  0.46633016
## 162   19.7     16.5  0.25146427
## 163   37.2     27.0  1.46726828
## 164   30.0     28.0  0.98960169
## 165   47.0     30.0  2.60241681
## 166   19.1     14.5  0.20772780
## 167   46.3     30.0  2.52547528
## 168   57.5      3.4  0.44144286
## 169   78.0     42.0 10.03456109
## 170   58.0     33.5  4.42548303
## 171   28.9     20.5  0.67237171
## 172   49.6     27.0  2.60847695
## 173   52.8     28.5  3.12012929
## 174   44.5     27.0  2.09963436
## 175   15.8     17.0  0.16665678
## 176   35.7     34.5  1.72669413
## 177   25.3     27.5  0.69124758
## 178   14.8     14.5  0.12472437
## 179   30.5     23.5  0.85847455
## 180   12.2     14.0  0.08182906
## 181   38.2     23.5  1.34664919
## 182   27.5     23.5  0.69789990
## 183   14.6     23.5  0.19671318
## 184   54.5     26.5  3.09099829
## 185   18.2     19.0  0.24714752
## 186   32.2     23.0  0.93648207
## 187   35.0     23.0  1.10642966
## 188   50.2     30.0  2.96885218
## 189   10.8     10.0  0.04580442
## 190   14.4     10.0  0.08143008
## 191   22.6     14.0  0.28080498
## 192   40.5     18.0  1.15942440
## 193   43.7     27.0  2.02482048
## 194   64.4     42.0  6.84039075
## 195   29.0     23.0  0.75959783
## 196   52.5     27.0  2.92241748
## 197   24.8     24.0  0.57966154
## 198   46.6     25.0  2.13192404
## 199   28.3     21.5  0.67619385
## 200   15.3     13.0  0.11950501
## 201   58.8     25.0  3.39433378
## 202   59.5     23.0  3.19758173
## 203   65.6     35.0  5.91473932
## 204   10.5      9.5  0.04113032
## 205   19.6     18.5  0.27908967
## 206   44.1     30.0  2.29117530
## 207   24.5     22.0  0.51857877
## 208   24.8     21.0  0.50720385
## 209   50.6     32.0  3.21744327
## 210   45.3     30.0  2.41756158
## 211   17.1     12.0  0.13779497
## 212   69.0     40.0  7.47856131
## 213   71.6     35.0  7.04618391
## 214   41.5     28.0  1.89371278
## 215   45.5     33.5  2.72350067
## 216   72.5     35.5  7.32764215
## 217   44.3     20.5  1.57986944
## 218   15.5     14.5  0.13680163
## 219   14.0      9.0  0.06927212
## 220   47.3     30.0  2.63574519
## 221   43.3     29.5  2.17198936
## 222   70.8     42.5  8.36595128
## 223   79.8     31.0  7.75224273
## 224   22.0     18.0  0.34211944
## 225   44.0     32.0  2.43284935
## 226   55.8     26.0  3.17908128
## 227   60.7     26.0  3.76192918
## 228   12.1     10.5  0.06036983
## 229   30.0     17.0  0.60082959
## 230   47.6     25.5  2.26889277
## 231   30.9     17.0  0.63742012
## 232   33.0     29.0  1.24018297
## 233   51.5     29.5  3.07253161
## 234   50.8     28.5  2.88823263
## 235   53.0     23.0  2.53711096
## 236   43.0     18.5  1.34328611
## 237   46.0     28.0  2.32666352
## 238   59.4     33.3  4.61399383
## 239   33.8     24.1  1.08121068
## 240   20.1     16.1  0.25543351
## 241   26.2     14.5  0.39086832
## 242   10.8     14.8  0.06779054
## 243   51.2     27.0  2.77948012
## 244   43.5     26.4  1.96174397
## 245   37.1     28.8  1.55668304
## 246   42.1     32.4  2.25511705
## 247   78.5     37.0  8.95366669
## 248   10.1      9.0  0.03605331
## 249   49.4     23.6  2.26165203
## 250   60.7     30.0  4.34068752
## 251   46.3     30.0  2.52547528
## 252   55.1     18.0  2.14602901
## 253   65.4     35.5  5.96271066
## 254   23.9     23.2  0.52040765
## 255   28.4     19.3  0.61129927
## 256   19.7     11.0  0.16764285
## 257   28.2     20.5  0.64019454
## 258   22.2     18.7  0.36191571
## 259   11.9     11.5  0.06395163
## 260   24.5     23.8  0.56100794
## 261   31.4     27.0  1.04540108
## 262   12.0     12.8  0.07238229
## 263   15.9     12.5  0.12409782
## 264   27.0     17.0  0.48667197
## 265   27.7     20.5  0.61769386
## 266   43.8     17.9  1.34853163
## 267   39.7     19.5  1.20691174
## 268   47.5     27.0  2.39227372
## 269   49.8     24.5  2.38607810
## 270   42.3     30.5  2.14309025
## 271   48.8     24.5  2.29121379
## 272   81.2     47.0 12.16941782
## 273   45.0     28.0  2.22660379
## 274   56.5     30.0  3.76078093
## 275   53.0     23.5  2.59226554
## 276   52.2     35.0  3.74514758
## 277   34.3     25.5  1.17811668
## 278   34.1     24.5  1.11875433
## 279   23.9     21.0  0.47105865
## 280   41.3     26.0  1.74153953
## 281   19.7     18.0  0.27432466
## 282   15.0     16.5  0.14578953
## 283   43.2     24.0  1.75888976
## 284   26.8     22.0  0.62051481
## 285   28.6     29.5  0.94757582
## 286   30.2     29.5  1.05656395
## 287   31.4     28.0  1.08411964
## 288   26.6     19.0  0.52793051
## 289   34.1     25.0  1.14158605
## 290   33.0     17.0  0.72700381
## 291   26.7     15.0  0.41992687
## 292   23.4     20.0  0.43005262
## 293   31.2     19.0  0.72631109
## 294   35.2     24.5  1.19209618
## 295   25.7     18.0  0.46687287
## 296   16.3      9.0  0.09390260
## 297   40.1     19.5  1.23135490
## 298   17.6     16.5  0.20071007
## 299   42.5     28.0  1.98607561
## 300   31.4     23.0  0.89052685
## 301   27.1     21.0  0.60564448
## 302   40.0     21.0  1.31946891
## 303   51.3     31.0  3.20373296
## 304   28.4     23.0  0.72849135
## 305   39.3     25.0  1.51629951
## 306   33.7     17.0  0.75817351
## 307   21.3     15.5  0.27615365
## 308   20.1     16.0  0.25384697
## 309   45.4     25.0  2.02353910
## 310   29.7     20.0  0.69279187
## 311   22.8     12.0  0.24496883
## 312   29.2     23.0  0.77011117
## 313   38.3     24.0  1.38251125
## 314   17.4     12.0  0.14267229
## 315   23.9     17.5  0.39254887
## 316   18.9     16.0  0.22444166
## 317   20.5     13.0  0.21454133
## 318   21.0     18.5  0.32038355
## 319   55.5     27.5  3.32643120
## 320   16.4     13.0  0.13730645
## 321   56.5     37.0  4.63829648
## 322   37.3     20.5  1.12003453
## 323   20.7     14.0  0.23557468
## 324   44.6     28.5  2.22625272
## 325   36.7     25.0  1.32230617
## 326   44.5     27.0  2.09963436
## 327   31.6     20.5  0.80387387
## 328   28.3     24.0  0.75482104
## 329   52.2     27.5  2.94261596
## 330   22.5     20.5  0.40754802
## 331   28.0     21.0  0.64653977
## 332   33.0     20.5  0.87668106
## 333   47.8     20.5  1.83937187
## 334   10.2     16.0  0.06537026
## 335   31.5     22.0  0.85724246
## 336   26.5     25.0  0.68943233
lapply(ufc[4:6], mean)   # return a list
## $dbh.cm
## [1] 37.41369
## 
## $height.m
## [1] 24.2256
## 
## $volume.m3
## [1] 1.93294
sapply(ufc[4:6], mean)   # return a vector
##    dbh.cm  height.m volume.m3 
##  37.41369  24.22560   1.93294
result <- rep(0,3)    #뭔가 중요할듯.
for (i in 4:6){
  result[i] <- mean(ufc[[i]])
}
result
## [1]  0.00000  0.00000  0.00000 37.41369 24.22560  1.93294
result <- list()   
for (i in 4:6){
  result[[i-1]] <- mean(ufc[[i]])
}
result
## [[1]]
## NULL
## 
## [[2]]
## NULL
## 
## [[3]]
## [1] 37.41369
## 
## [[4]]
## [1] 24.2256
## 
## [[5]]
## [1] 1.93294

Simple example:

sapply(1:3, function(x) x^2)
## [1] 1 4 9
lapply(1:3, function(x) x^2)
## [[1]]
## [1] 1
## 
## [[2]]
## [1] 4
## 
## [[3]]
## [1] 9

lapply example

df <- data.frame(replicate(6, sample(c(1:10, -99), 6, rep = TRUE)))
names(df) <- letters[1:6]
df
##   a   b c   d  e  f
## 1 8 -99 8   5  5  3
## 2 2   6 8   6  9  7
## 3 5   1 4   1  2  7
## 4 4   9 5  10 10  1
## 5 6  10 6   3  5  4
## 6 6   6 9 -99  1 10

모든 -99를 NA로 대체하려고 한다면

fix_missing <- function(x) {
  x[x == -99] <- NA
  x
}
df[] <- lapply(df, fix_missing)  #list to data.frame, use df[]
df
##   a  b c  d  e  f
## 1 8 NA 8  5  5  3
## 2 2  6 8  6  9  7
## 3 5  1 4  1  2  7
## 4 4  9 5 10 10  1
## 5 6 10 6  3  5  4
## 6 6  6 9 NA  1 10
sapply(df, fix_missing)
##      a  b c  d  e  f
## [1,] 8 NA 8  5  5  3
## [2,] 2  6 8  6  9  7
## [3,] 5  1 4  1  2  7
## [4,] 4  9 5 10 10  1
## [5,] 6 10 6  3  5  4
## [6,] 6  6 9 NA  1 10

More about apply : http://adv-r.had.co.nz/Functional-programming.html

three dots ellipsis … in function argument

함수 인수에서 세 개의 점으로 이루어진 생략 기호 ...는 가변 길이 인수 목록을 받는 데 사용된다.

  • 예를 들어, paste 함수에서는 가변 개수의 인수를 넣을 수 있다. ?paste를 통해 확인할 수 있다.

...를 처리하기 위해서는, 함수 내에서 이를 리스트로 변환하여 사용한다.

addemup <- function(x, ...){
  args <- list(...)
  for (a in args) x <- x + a
  x
}
addemup(1, 1)
## [1] 2
addemup(1, 2, 3, 4, 5)
## [1] 15

reverse_paste0 함수는 입력된 인수를 반대 순서로 결합하는 함수이다.

reverse_paste0 <- function(...){
  result <- ""
  args <- list(...)
  
  for (i in length(args):1){
    result <- paste0(result, args[i])
  }
  result
}
reverse_paste0("a", "b", "c")
## [1] "cba"
reverse_paste0("a", "b", "c", "d", "e")
## [1] "edcba"