factor level 수정 melt (reshape시 발생하는 문제 해결)



data frame에서 각각의 column의 factor level을 확장하는 방법


DF[2:3] <- lapply(DF[2:3], factor, levels=letters)
melt(DF, id.vars="id", factorsAsStrings=F)$value
[1] a b c z y x
Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z

If however we reset the factors to have the same levels and only then melt:

DF[2:3] <- lapply(DF[2:3], factor, levels=letters)
melt(DF, id.vars="id", factorsAsStrings=F)$value


Assert 

# Assert 개발 -- 위코드에 추가함 

assert("A Poisson random number is non-negative", {

  x = rpois(1, 10)

  (x >= 11)

  (x > -1)  # () is optional because it's the last expression

})



'AI > R Basic' 카테고리의 다른 글

R Studio Server Install in Ubuntu Server  (3) 2018.07.04
Jupyter Notebook으로 R 실행  (2) 2018.04.15
Data Transformation: dplyr package  (0) 2018.04.14
두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
R Factor 검색  (0) 2017.11.13

R Studio Server Install in Ubuntu Server


Ubuntu Server 환경에 RStudio server를 설치하는 방법을 다룬다.

sudo apt-get --assume-yes update
sudo apt-get --assume-yes install r-base
sudo apt-get --assume-yes install gdebi-core

wget으로 버전에 맞는 RStudio deb 페키지 다운로드

공식사이트

$ wget https://download2.rstudio.org/rstudio-server-1.1.453-amd64.deb

Debian package로 설치하기

sudo gdebi --non-interactive rstudio-server-1.1.453-amd64.deb
Reading package lists... Done
Building dependency tree
Reading state information... Done
Reading state information... Done
Selecting previously unselected package rstudio-server.
(데이터베이스 읽는중 ...현재 80134개의 파일과 디렉터리가 설치되어 있습니다.)
Preparing to unpack rstudio-server-1.1.453-amd64.deb ...
Unpacking rstudio-server (1.1.453) ...
rstudio-server (1.1.453) 설정하는 중입니다 ...
groupadd: group 'rstudio-server' already exists
rsession: no process found
Created symlink from /etc/systemd/system/multi-user.target.wants/rstudio-server.service to /etc/systemd/system/rstudio-server.service.
● rstudio-server.service - RStudio Server
   Loaded: loaded (/etc/systemd/system/rstudio-server.service; enabled; vendor preset: enabled)
   Active: active (running) since 수 2018-07-04 19:06:22 KST; 1s ago
  Process: 5096 ExecStart=/usr/lib/rstudio-server/bin/rserver (code=exited, status=0/SUCCESS)
 Main PID: 5100 (rserver)
    Tasks: 3
   Memory: 1.2M
      CPU: 618ms
   CGroup: /system.slice/rstudio-server.service
           └─5100 /usr/lib/rstudio-server/bin/rserver

 7월 04 19:06:22 ubuntu systemd[1]: Starting RStudio Server...
 7월 04 19:06:22 ubuntu systemd[1]: Started RStudio Server.

Jupyter Notebook으로 R 실행


Anaconda 설치

Jupyter Notebook update

conda update ipython-notebook

IRkernel 설치

conda install -c r ipython-notebook r-irkernel

Rkernel을 jupyter에서 실행하기 위한 필수 package설치
아래의 명령어는 R console에서 실행 한다.

install.packages(c('rzmq','repr','IRkernel','IRdisplay'), repos = 'http://irkernel.github.io/', type = 'source')

모두 설치 후 R Console에서 다음을 입력한다.

IRkernel::installspec()
quit() # 종료

아래와 같이 R kernel이 생성 되었다.


Data Transformation: dplyr package


R의 신 Hadley Wickham의 책 R for Data Science 5장에 나오는 내용을 정리 한다.

Hadley Wickham본인이 직접 만든 패키지이므로 유용하다.
기타 그가 만든 패키지는 아래와 같다.

  • ggplot2
  • plyr
  • reshape2

plyr은 모든 함수가 R로 작성되어서 처리 속도가 느리다는 단점이 있다.
dplyr C++로 작성되어 불필요한 함수를 불러오지 않기 때문에 매우 빠른 처리 속도를 자랑한다.
결국 분할(split),적용(apply) 병합(combine)을 plyr로 하던것을 dplyr로 변경하는 패러다임 전환이다.

필자도 plyr {}{}ply를 많이 사용 했었다. 하지만 파이프연산과 조합한dplyr이 좀 더 가독성이 높고
속도도 빠르다고하니 이쪽으로 옴겨 가야 하는 것 같다.

dplyr의 지원 함수군 외의 특징

  • data.table 지원
  • 각종 DB지원: MySQL, PostgreSQL, SQLite, BigQuery
  • 데이터 큐브
함수명내용유사함수
filter()지정한 조건식에 맞는 데이터 추출subset()
select()열의 추출data[, c(“Year”, “Month”)]
mutate()열 추가transform()
arrange()정렬order(), sort()
summarise()집계aggregate()

필요 package

install.packages("nycflights13")
library("nycflights13")
library(tidyverse)

tidyverse 로딩시 아래와 같이 conflict메시지가 나올 수도 있다.

-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
√ ggplot2 2.2.1     √ purrr   0.2.4
√ tibble  1.4.1     √ dplyr   0.7.4
√ tidyr   0.7.2     √ stringr 1.2.0
√ readr   1.1.1     √ forcats 0.3.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()

flights데이터를 출력하면 아래와 같이 출력 된다.

> flights
# A tibble: 336,776 x 19
    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum origin dest  air_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>     <dbl> <chr>    <int> <chr>   <chr>  <chr>    <dbl>
 1  2013     1     1      517            515      2.00      830            819     11.0  UA        1545 N14228  EWR    IAH      227  
 2  2013     1     1      533            529      4.00      850            830     20.0  UA        1714 N24211  LGA    IAH      227  
 3  2013     1     1      542            540      2.00      923            850     33.0  AA        1141 N619AA  JFK    MIA      160  
 4  2013     1     1      544            545     -1.00     1004           1022    -18.0  B6         725 N804JB  JFK    BQN      183  
 5  2013     1     1      554            600     -6.00      812            837    -25.0  DL         461 N668DN  LGA    ATL      116  
 6  2013     1     1      554            558     -4.00      740            728     12.0  UA        1696 N39463  EWR    ORD      150  
 7  2013     1     1      555            600     -5.00      913            854     19.0  B6         507 N516JB  EWR    FLL      158  
 8  2013     1     1      557            600     -3.00      709            723    -14.0  EV        5708 N829AS  LGA    IAD       53.0
 9  2013     1     1      557            600     -3.00      838            846    - 8.00 B6          79 N593JB  JFK    MCO      140  
10  2013     1     1      558            600     -2.00      753            745      8.00 AA         301 N3ALAA  LGA    ORD      138  
# ... with 336,766 more rows, and 4 more variables: distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>
> class(flights)
[1] "tbl_df"     "tbl"        "data.frame"

336,776의 뉴욕에서 2013에 출발한 비행 정보를 담고 있다.
US Bureau of Transportation Statistics

tibble이라는 data.frame을 약간 변형 시킨것을 사용한다.
tibble에 대한 상세한 내용의 링크이다.

dplyr basics

중요 package 5개를 설명한다.

  • Pick obervations by their values (filter())
  • Reorder the rows (arrange())
  • Pick variables by their names(select())
  • Create new variables with functions of existing variables (mutate())
  • Collpase many values down to a single summary (summarise())

추가로 group_by()를 통해서 scope을 조절 할 수 있다.

filter()

관찰한 데이터의 subset을 쉽게 구할 수 있도록 해준다.
첫 번째 인자는 data frame이고, 아래 예제에서 그 다음 인자들은 조건을 의미한다.
아래의 예제는 January 1st를 필터링한 예제이다.

nov_dec <- filter(flights, month %in% c(11, 12))
# A tibble: 55,403 x 19
    year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum origin dest  air_time
   <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>     <dbl> <chr>    <int> <chr>   <chr>  <chr>    <dbl>
 1  2013    11     1        5           2359      6.00      352            345      7.00 B6         745 N568JB  JFK    PSE      205  
 2  2013    11     1       35           2250    105         123           2356     87.0  B6        1816 N353JB  JFK    SYR       36.0
 3  2013    11     1      455            500   -  5.00      641            651    -10.0  US        1895 N192UW  EWR    CLT       88.0
 4  2013    11     1      539            545   -  6.00      856            827     29.0  UA        1714 N38727  LGA    IAH      229  
 5  2013    11     1      542            545   -  3.00      831            855    -24.0  AA        2243 N5CLAA  JFK    MIA      147  
 6  2013    11     1      549            600   - 11.0       912            923    -11.0  UA         303 N595UA  JFK    SFO      359  
 7  2013    11     1      550            600   - 10.0       705            659      6.00 US        2167 N748UW  LGA    DCA       57.0
 8  2013    11     1      554            600   -  6.00      659            701    - 2.00 US        2134 N742PS  LGA    BOS       40.0
 9  2013    11     1      554            600   -  6.00      826            827    - 1.00 DL         563 N912DE  LGA    ATL      126  
10  2013    11     1      554            600   -  6.00      749            751    - 2.00 DL         731 N315NB  LGA    DTW       93.0
# ... with 55,393 more rows, and 4 more variables: distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

arrange()

정렬 용도

arrange(flights, desc(arr_delay))
#> # A tibble: 336,776 × 19
#>    year month   day dep_time sched_dep_time dep_delay arr_time
#>   <int> <int> <int>    <int>          <int>     <dbl>    <int>
#> 1  2013     1     9      641            900      1301     1242
#> 2  2013     6    15     1432           1935      1137     1607
#> 3  2013     1    10     1121           1635      1126     1239
#> 4  2013     9    20     1139           1845      1014     1457
#> 5  2013     7    22      845           1600      1005     1044
#> 6  2013     4    10     1100           1900       960     1342
#> # ... with 3.368e+05 more rows, and 12 more variables:
#> #   sched_arr_time <int>, arr_delay <dbl>, carrier <chr>, flight <int>,
#> #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>,
#> #   distance <dbl>, hour <dbl>, minute <dbl>, time_hour <dttm>

select()

선택 용도

select(flights, year, month, day)
select(flights, year:day)
select(flights, -(year:day))
  • starts_with(“abc”): matches names that begin with “abc”.
  • ends_with(“xyz”): matches names that end with “xyz”.
  • contains(“ijk”): matches names that contain “ijk”.
  • matches(“(.)\1”): selects variables that match a regular expression. This one matches any variables that contain - repeated characters. You’ll learn more about regular expressions in strings.
  • num_range(“x”, 1:3) matches x1, x2 and x3.

mutate()

현재 있는 Data.Frame의 맨 뒤에다가 새로운 컬럼을 추가하는 것이다.

flights_sml <- select(flights, 
  year:day, 
  ends_with("delay"), 
  distance, 
  air_time
)
mutate(flights_sml,
  gain = arr_delay - dep_delay,
  speed = distance / air_time * 60
)
# A tibble: 336,776 x 9
    year month   day dep_delay arr_delay distance air_time   gain speed
   <int> <int> <int>     <dbl>     <dbl>    <dbl>    <dbl>  <dbl> <dbl>
 1  2013     1     1      2.00     11.0      1400    227     9.00   370
 2  2013     1     1      4.00     20.0      1416    227    16.0    374
 3  2013     1     1      2.00     33.0      1089    160    31.0    408
 4  2013     1     1     -1.00    -18.0      1576    183   -17.0    517
 5  2013     1     1     -6.00    -25.0       762    116   -19.0    394
 6  2013     1     1     -4.00     12.0       719    150    16.0    288
 7  2013     1     1     -5.00     19.0      1065    158    24.0    404
 8  2013     1     1     -3.00    -14.0       229     53.0 -11.0    259
 9  2013     1     1     -3.00    - 8.00      944    140   - 5.00   405
10  2013     1     1     -2.00      8.00      733    138    10.0    319
# ... with 336,766 more rows

plyr:transform과 다른점은 연이어서 생성한 컬럼을 바로 사용해도 된다는 것이다.

mutate(flights_sml,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
)
# A tibble: 336,776 x 10
    year month   day dep_delay arr_delay distance air_time
   <int> <int> <int>     <dbl>     <dbl>    <dbl>    <dbl>
 1  2013     1     1      2.00     11.0      1400    227  
 2  2013     1     1      4.00     20.0      1416    227  
 3  2013     1     1      2.00     33.0      1089    160  
 4  2013     1     1     -1.00    -18.0      1576    183  
 5  2013     1     1     -6.00    -25.0       762    116  
 6  2013     1     1     -4.00     12.0       719    150  
 7  2013     1     1     -5.00     19.0      1065    158  
 8  2013     1     1     -3.00    -14.0       229     53.0
 9  2013     1     1     -3.00    - 8.00      944    140  
10  2013     1     1     -2.00      8.00      733    138  
# ... with 336,766 more rows, and 3 more variables: gain <dbl>,
#   hours <dbl>, gain_per_hour <dbl>

새로 생성한 variable columns만 유지하고 싶으면 transmute를 사용한다.

transmute(flights,
  gain = arr_delay - dep_delay,
  hours = air_time / 60,
  gain_per_hour = gain / hours
)
# A tibble: 336,776 x 3
     gain hours gain_per_hour
    <dbl> <dbl>         <dbl>
 1   9.00 3.78           2.38
 2  16.0  3.78           4.23
 3  31.0  2.67          11.6 
 4 -17.0  3.05         - 5.57
 5 -19.0  1.93         - 9.83
 6  16.0  2.50           6.40
 7  24.0  2.63           9.11
 8 -11.0  0.883        -12.5 
 9 - 5.00 2.33         - 2.14
10  10.0  2.30           4.35
# ... with 336,766 more rows

summarise()

그룹핑해서 하나의 single row로 합치는 역할을 한다.
그냥 summarise만 단독해서 사용하면 엄청나게 유용하진 않지만, group_by와 함께 사용하면 그 위력이 증대된다.

그냥 summarise하면 단 하나의 row로 처리됨

summarise(flights, delay = mean(dep_delay, na.rm = TRUE))
# A tibble: 1 x 1
  delay
  <dbl>
1  12.6

group_by를 이용해서 그룹핑 가능함

by_day <- group_by(flights, year, month, day)
summarise(by_day, delay = mean(dep_delay, na.rm = TRUE))
# pipe
group_by(flights, year, month, day) %>% summarise(delay = mean(dep_delay, na.rm = TRUE))
# A tibble: 365 x 4
# Groups:   year, month [?]
    year month   day delay
   <int> <int> <int> <dbl>
 1  2013     1     1 11.5 
 2  2013     1     2 13.9 
 3  2013     1     3 11.0 
 4  2013     1     4  8.95
 5  2013     1     5  5.73
 6  2013     1     6  7.15
 7  2013     1     7  5.42
 8  2013     1     8  2.55
 9  2013     1     9  2.28
10  2013     1    10  2.84
# ... with 355 more rows

파이프의 사용

아래 세개의 작업을 수행

  • flight를 destination에 따라서 그룹핑함
  • flight의 수와 거리, 평균 딜레이를 요약
  • Honolulu airport와 noisy point를 제거 한다.

파이를 사용하면 쓸 때 없는 중간 변수들을 정의하지 않아도 되기 때문에 편리하고 직관적인 이해를 달성한다.

파이프 사용

delays <- flights %>% 
  group_by(dest) %>% 
  summarise(
    count = n(),
    dist = mean(distance, na.rm = TRUE),
    delay = mean(arr_delay, na.rm = TRUE)
  ) %>% 
  filter(count > 20, dest != "HNL")

파이프 미사용

# Combining multiple operations with the pipe
by_dest <- group_by(flights, dest)
delay <- summarise(by_dest,
   count = n(),
   dist = mean(distance, na.rm = TRUE),
   delay = mean(arr_delay, na.rm = TRUE)
)
delay <- filter(delay, count > 20, dest != "HNL")

참고자료

R 데이터 처리의 새로운 강자, dplyr 패키지
dplyr로 데이터 집계와 분석


'AI > R Basic' 카테고리의 다른 글

R Studio Server Install in Ubuntu Server  (3) 2018.07.04
Jupyter Notebook으로 R 실행  (2) 2018.04.15
두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
R Factor 검색  (0) 2017.11.13
RStudio v1.1 Released  (0) 2017.10.10

두 개 데이터 프레임 병합, 빼기


공통 키를 기준으로 병합

하나이상의 key를 가지고 두 개의 데이터 프레임을 join하는 연산

# merge two data frames by ID
total <- merge(data frameA,data frameB,by="ID")

두 개의 데이터로 병합

# merge two data frames by ID and Country
total <- merge(data frameA,data frameB,by=c("ID","Country"))

빼기

Larger - Smaller

small

     ID       CSF1PO CSF1PO.1 D10S1248 D10S1248.1 D12S391 D12S391.1
203079_BA_M     10       11       14         16      -9        -9
203079_BA_F      8       12       14         17      -9        -9
203080_BA_M     10       12       13         13      -9        -9

big

      ID      CSF1PO CSF1PO.1 D10S1248 D10S1248.1 D12S391 D12S391.1
203078_MG_M     -9       -9       15         15      18        20
203078_MG_F     -9       -9       14         15      17        19
203079_BA_M     10       11       14         16      -9        -9
203079_BA_F      8       12       14         17      -9        -9
203080_BA_M     10       12       13         13      -9        -9
203080_BA_F     10       11       14         16      -9        -9
203081_MG_M     10       12       14         16      -9        -9
203081_MG_F     11       12       15         16      -9        -9
203082_MG_M     11       11       13         15      -9        -9
203082_MG_F     11       11       13         14      -9        -9

Solution

BigDF[ !(BigDF$ID %in% SmallDF$ID), ]

'AI > R Basic' 카테고리의 다른 글

Jupyter Notebook으로 R 실행  (2) 2018.04.15
Data Transformation: dplyr package  (0) 2018.04.14
R Factor 검색  (0) 2017.11.13
RStudio v1.1 Released  (0) 2017.10.10
rJava load 에러  (0) 2017.04.16

R Factor 검색


factor로 구성된 vector가 있다고 가정 한다.

%in

'a' %in% v

any()
any('a' == v)
[1] TRUE

is.element()
is.element('a',v)

첫 번째 매치 index 반환

match('a',v)

모든 일치하는 index 반환

which('a' == v)
[1] 2 4


'AI > R Basic' 카테고리의 다른 글

Data Transformation: dplyr package  (0) 2018.04.14
두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
RStudio v1.1 Released  (0) 2017.10.10
rJava load 에러  (0) 2017.04.16
Swapping columns in a matrix  (0) 2017.03.31

RStudio v1.1 Released


R Studio가 정식버전으로 2017-10-09일자로 v1.1이 업데이트 되었습니다.

위와 같이 Dark 테마가 기본으로 설정됩니다. 또한 terminal이 기본으로 탑제 되었습니다.

기타 변경사항의 Highlight는 아래와 같습니다.

  • connection tab: 다양한 database들과 쉽게 연결 하여 탐색 할 수 있습니다.
  • terminal tab: shell을 지원합니다.
  • object explorer: R data 구조와 객체를 좀 더 깊이 있게 탐색 할 수 있습니다.
  • dark theme: 현대적인 Theme을 사용 할 수 있습니다.
  • 다양한 약간의 향상과 버그 수정

Pro version은 좀 더 다양한 기능을 제공 받습니다.

설치 방법

  1. 공식사이트 URL에 접속후 운영체제에 맞는 설치파을을 다운로드 한다.

  2. 기존 설치자의 경우도 알아서 uninstall후 재설치가 자동으로 이뤄 진다.

출처

R Studio 공식 블로그


'AI > R Basic' 카테고리의 다른 글

두 개 데이터 프레임 병합, 빼기  (0) 2018.03.04
R Factor 검색  (0) 2017.11.13
rJava load 에러  (0) 2017.04.16
Swapping columns in a matrix  (0) 2017.03.31
R Notebook  (0) 2016.11.02

rJava load 에러



JDK를 업데이트 하면 발생한다.


JAVA_HOME 환경변수를 다시 설정해 준다.


cmd에서 확인 방법


echo %JAVA_HOME%


환경변수가 잘 변경 되었는지 위 방법을 통해서 알 수 있다. 

'AI > R Basic' 카테고리의 다른 글

R Factor 검색  (0) 2017.11.13
RStudio v1.1 Released  (0) 2017.10.10
Swapping columns in a matrix  (0) 2017.03.31
R Notebook  (0) 2016.11.02
R Markdown  (0) 2016.11.02

Swapping columns in a matrix


그냥 간단하게 column을 swapping한다면

m[, c(1,2)] <- m[,c(2,1)]

하지만 위에 처럼 하게 되면 column의 이름이 swap되지 않는다.

아래와 같이 수행해야 column 이름까지 모두 함께 변경 된다.

m <- m[, c(2, 1, 3:ncol(m))]


'AI > R Basic' 카테고리의 다른 글

RStudio v1.1 Released  (0) 2017.10.10
rJava load 에러  (0) 2017.04.16
R Notebook  (0) 2016.11.02
R Markdown  (0) 2016.11.02
Data를 그룹별로 요약 (Summarizing data)  (0) 2016.10.27

R Notebook


Python의 Jupyter Notebook과 다르게 R의 경우 그동안 R Markdown만 있을뿐 Interative한 Document 타입이 없어서 불편 했었다.

하지만 이번 R Studio preview 업데이트로 막강한 Notebook기능이 업데이트 되었다.

Data Analysis시 좀 더 체계적인 문서와 관리가 가능해진 것 같다.

RStudio v1.0.44 Preview — Release Notes

  • Authoring tools for R Notebooks.
  • Integrated support for the sparklyr package (R interface to Spark).
  • Enhanced data import tools based on the readr, readxl and haven packages.
  • Performance profiling via integration with the profvis package.
  • Authoring tools for R Markdown websites and the bookdown package.
  • Many other miscellaneous enhancements and bug fixes.

동작 모습

아래와 같이 Notebook생성 기능이 새로 만들어 졌다.

그리고 아래와 같이 preview버튼으로 실행하고 옵션을 in panel로 하면 viewer 창에 결과가 보이고
interactive 하게 편집할 수 있도록 바뀐다.


R Markdown


R Studio가 1.0이상의 버전이 되면서 많은 부분들이 개선 되었다.
그것들에 대해서 하나씩 이야기해본다.

기본 R Markdown

아래처럼 HTML을 생성 할 때 Option으로 toc: truetoc_float: true를 설정하면 왼쪽에 제목에 따른 목차가 생성 되는 것을 알 수 있다. 추가 html옵션을 보려면 ?html_document를 실행 한다.

title: "Viridis Demo 2"
output: 
  html_document:
    toc: true
    toc_float: true

패널에 preview 표시

preview in viewer panel을 선택하면 안에서 표시 할 수 있게 된다.


Data를 그룹별로 요약 (Summarizing data)


특정 값에 따라서 그룹으로 나눈다음 특정 함수(평균, SD)를 적용하는 방법은 3가지가 있다.

  • ddply해당 함수는 plyr package를 통해서 쉽게 사용할 수 있다.
  • summarizeBy() 해당 함수는 doBy package를 이용해서 쉽게 사용할 수 있다.
  • aggregate() 해당 함수는 약간 어렵지만, 기본 R 함수이다.

주어진 데이터 형태

data <- read.table(header=TRUE, text='
 subject sex condition before after change
       1   F   placebo   10.1   6.9   -3.2
       2   F   placebo    6.3   4.2   -2.1
       3   M   aspirin   12.4   6.3   -6.1
       4   F   placebo    8.1   6.1   -2.0
       5   M   aspirin   15.2   9.9   -5.3
       6   F   aspirin   10.9   7.0   -3.9
       7   F   aspirin   11.6   8.5   -3.1
       8   M   aspirin    9.5   3.0   -6.5
       9   F   placebo   11.5   9.0   -2.5
      10   M   placebo   11.9  11.0   -0.9
      11   F   aspirin   11.4   8.0   -3.4
      12   M   aspirin   10.0   4.4   -5.6
      13   M   aspirin   12.5   5.4   -7.1
      14   M   placebo   10.6  10.6    0.0
      15   M   aspirin    9.1   4.3   -4.8
      16   F   placebo   12.1  10.2   -1.9
      17   F   placebo   11.0   8.8   -2.2
      18   F   placebo   11.9  10.2   -1.7
      19   M   aspirin    9.1   3.6   -5.5
      20   M   placebo   13.5  12.4   -1.1
      21   M   aspirin   12.0   7.5   -4.5
      22   F   placebo    9.1   7.6   -1.5
      23   M   placebo    9.9   8.0   -1.9
      24   F   placebo    7.6   5.2   -2.4
      25   F   placebo   11.8   9.7   -2.1
      26   F   placebo   11.8  10.7   -1.1
      27   F   aspirin   10.1   7.9   -2.2
      28   M   aspirin   11.6   8.3   -3.3
      29   F   aspirin   11.3   6.8   -4.5
      30   F   placebo   10.3   8.3   -2.0
 ')

ddply 사용

library(plyr)

# Run the functions length, mean, and sd on the value of "change" for each group, 
# broken down by sex + condition
cdata <- ddply(data, c("sex", "condition"), summarise,
               N    = length(change),
               mean = mean(change),
               sd   = sd(change),
               se   = sd / sqrt(N)
)
cdata
#>   sex condition  N      mean        sd        se
#> 1   F   aspirin  5 -3.420000 0.8642916 0.3865230
#> 2   F   placebo 12 -2.058333 0.5247655 0.1514867
#> 3   M   aspirin  9 -5.411111 1.1307569 0.3769190
#> 4   M   placebo  4 -0.975000 0.7804913 0.3902456

참고자료

http://www.cookbook-r.com/Manipulating_data/Summarizing_data/


'AI > R Basic' 카테고리의 다른 글

R Notebook  (0) 2016.11.02
R Markdown  (0) 2016.11.02
리스트 데이터 프레임을 단일 큰 데이터 프레임으로 변환, identical  (0) 2016.10.10
Word Cloud from PDF using R  (1) 2016.08.25
빈도분석 표와 백분율 구하기  (0) 2016.08.21

리스트 데이터 프레임을 단일 큰 데이터 프레임으로 변환


do.call 방식

id가 따로 생성되지 않아서 나중에 식별이 어렵다.

df <- do.call("rbind", listOfDataFrames)

plyr pakcage의 ldply이용

.id로 index를 만들기 때문에 여러므로 편리하다.
ldply을 사용하는것이 좋다.
plyr package를 반드시 부착 한다.

df <- ldply(listOfDataFrames, data.frame)
system.time({ df <- do.call("rbind", listOfDataFrames) })
user  system elapsed 
0.25    0.00    0.25 


ldply(phoneStatusDf, function(x){
  x[,2]  
})
system.time({ df2 <- ldply(listOfDataFrames, data.frame) })
user  system elapsed 
0.30    0.00    0.29
identical(df, df2)
[1] TRUE

빠른 속도: rbindlist

library("data.table")
rbindlist(listOfDataFrames, idcol=TRUE)

idcol의 옵션에 따라서 .id 컬럼이 생성된다.


'AI > R Basic' 카테고리의 다른 글

R Markdown  (0) 2016.11.02
Data를 그룹별로 요약 (Summarizing data)  (0) 2016.10.27
Word Cloud from PDF using R  (1) 2016.08.25
빈도분석 표와 백분율 구하기  (0) 2016.08.21
Vector 분할  (0) 2016.08.21

이 때 까지 출판한 논문들을 이용해서 Word Cloud를 생성해 보았다.

저전력 컴퓨팅을 주로 했지만 어느 순간 부터 모델링을 하다보니 기계학습 내용도 많이 공부하게 됬다.

스스로의 학문적 근간이 모호해지는 상황이다.

최종적으로 생성한 Word Cloud는 아래와 같다.


해당 코드는 아래의 필자의 Github에 업로드 했다.

https://github.com/leejaymin/WordCloud 


Word Cloud from PDF using R


This project is to create Wrold Cloud from PDF file.
My code shows how a word cloud can be generated using the Rprogramming language on the basis of a given PDF document.

Used packages are as bellow:

  • tm (text mining)
  • wordcloud
  • RColorBrewer (fancy colors in a word cloud)

Code strcture

  • Loading the required libraries and setting inital parameters
  • Reading the text in the PDF file
  • Creating the text corpus
  • Generating the word cloud. This result is the following:

  • Anlyzing word frequency is as follow.

Reference

[1] Using R to create a Wrod Cloud from a PDF Document
[2] Basic Text mining in R


빈도분석 표와 백분율 구하기


descr package

질적 자료의 빈도와 백분율을 구하고 싶을 때, 유용한 함수로는 descr 패키지에 있는 freq()가 있다.

# 사용법 : freq(질적 자료)
# 예제 데이터 : InsectSprays
> attach(InsectSprays)

>install.packages("descr")
>library(descr)...

# 빈도표 작성하기 : 빈도와 백분율을 한번에 구해 준다.
> freq(spray)

# 빈도표와 막대그래프 작성하기
> freq(spray, plot=TRUE)

plyr package

install.packages('plyr')

Then, call its library, and the count() function will be ready for use.
> library(plyr)
> count(mtcars, 'gear')
       gear      freq
1      3         15
2      4         12
3      5         5
> y = count(mtcars, 'gear')
> y
       gear      freq
1      3         15
2      4         12
3      5         5
> class(y)
[1] "data.frame"

정렬하기

plyr페키지의 arrange를 사용

> library(plyr)

> arrange(v123, v1, desc(v2), v3)

  v1   v2 v3

1 30 6500  B

2 40 5100  A

3 40 4500  A

4 50 3000  B

5 50 2000  A

6 50 2000  B

7 90 9000  A 


Vector 분할


한줄로 해결 가능하다.

split(d, ceiling(seq_along(d)/20))

seq_along()split()ceiling()을 좀 더 자세히 설명하면 아래와 같다.

> d <- rpois(73,5)
> d
 [1]  3  1 11  4  1  2  3  2  4 10 10  2  7  4  6  6  2  1  1  2  3  8  3 10  7  4
[27]  3  4  4  1  1  7  2  4  6  0  5  7  4  6  8  4  7 12  4  6  8  4  2  7  6  5
[53]  4  5  4  5  5  8  7  7  7  6  2  4  3  3  8 11  6  6  1  8  4
> max <- 20
> x <- seq_along(d)
> d1 <- split(d, ceiling(x/max))
> d1
$`1`
 [1]  3  1 11  4  1  2  3  2  4 10 10  2  7  4  6  6  2  1  1  2

$`2`
 [1]  3  8  3 10  7  4  3  4  4  1  1  7  2  4  6  0  5  7  4  6

$`3`
 [1]  8  4  7 12  4  6  8  4  2  7  6  5  4  5  4  5  5  8  7  7

$`4`
 [1]  7  6  2  4  3  3  8 11  6  6  1  8  4


테스트 주도의 개발을 위한 Unit Test in R


유닛 테스트를 통한 Test Driven Development (TDD)를 생각해 보자.

RUnit 테스팅을 위해서는 RUnit와 testthat 두 개의 package가 존재 한다.

사용할 수 있는 함수

  • expect_true(x): x가 참인가

  • expect_false(x): x가 거짓인가

  • expect_equal(object, expected): object가 기대되는 값 expected와 동일한가. 값의 비교에는 all.equal()이 사용되며 all.equal()은 두 객체가 (거의) 같은지를 비교한다. 따라서 부동소수의 경우 epsilon 이하로 차이나는 두 값은 같은 값으로 취급한다.

  • expect_equivalent(x,y): x,y가 동등한가. expect_equal()과 달리 속성 (예를 들면, rownames)을 제거한 뒤 값만 비교 한다.

생성한 파일 구조는 아래와 같다.

tests/test_fibo.R #test case가 저장됨
run_tests.R #test 실행 명령어들의 집함
fibo.R # test할 함수가 저장됨

소스코드

fibo.R

fibo <- function(n){
  if(n==0 || n == 1){
    return(1)
  }
  return(fibo(n-1) + fibo(n-2))
}

run_tests.R

require(testthat)
source("fibo.R")

test_dir("tests", reporter="summary")

tests/test_fibo.R

context("fibonacci series")

test_that("base test",{
  expect_equal(1, fibo(0))
  expect_equal(1, fibo(1))
})

test_that("recursion test",{
  expect_equal(2, fibo(2))
  expect_equal(3, fibo(3))
  expect_equal(5, fibo(4))
})

실행 결과

정상적인경우

> source("run_tests.R")
fibonacci series: .....

DONE ============================================================================================================================================

의도적으로 오류를 발생 시키자

  expect_equal(0, fibo(4))

문제가 있는 경우

> source("run_tests.R")
fibonacci series: ....1

Failed ------------------------------------------------------------------------------------------------------------------------------------------
1. Failure: recursion test (@test_fibo.R#12) ----------------------------------------------------------------------------------------------------
0 not equal to fibo(4).
1/1 mismatches
[1] 0 - 5 == -5


DONE ============================================================================================================================================

참고문헌

[1] R을 이용한 데이터 처리 & 분석 실무, 서민구


Missing Value

How do I replace NA values with zeros in R

> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
> d <- as.data.frame(m)
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   4  3 NA  3  7  6  6 10  6   5
2   9  8  9  5 10 NA  2  1  7   2
3   1  1  6  3  6 NA  1  4  1   6
4  NA  4 NA  7 10  2 NA  4  1   8
5   1  2  4 NA  2  6  2  6  7   4
6  NA  3 NA NA 10  2  1 10  8   4
7   4  4  9 10  9  8  9  4 10  NA
8   5  8  3  2  1  4  5  9  4   7
9   3  9 10  1  9  9 10  5  3   3
10  4  2  2  5 NA  9  7  2  5   5

> d[is.na(d)] <- 0

> d
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   4  3  0  3  7  6  6 10  6   5
2   9  8  9  5 10  0  2  1  7   2
3   1  1  6  3  6  0  1  4  1   6
4   0  4  0  7 10  2  0  4  1   8
5   1  2  4  0  2  6  2  6  7   4
6   0  3  0  0 10  2  1 10  8   4
7   4  4  9 10  9  8  9  4 10   0
8   5  8  3  2  1  4  5  9  4   7
9   3  9 10  1  9  9 10  5  3   3
10  4  2  2  5  0  9  7  2  5   5

listwise deletion of missing values

# create new dataset without missing data 
newdata <- na.omit(mydata)

na.locf 함수 사용

zoo package에 구현되어 있는 함수이다.

Last Observation Carried Forward

Generic function for replacing each NA with the most recent non-NA prior to it.

x <- c(NA,NA, "A","A", "B","B","B", NA,NA, "C", NA,NA,NA, "A","A","B", NA,NA)
na.locf(x)
x

출력 결과

 [1] "A" "A" "B" "B" "B" "B" "B" "C" "C" "C" "C" "A" "A" "B" "B" "B"

참고 사이트: http://www.cookbook-r.com/Manipulating_data/Filling_in_NAs_with_last_non-NA_value/


병렬화를 통한 연산 성능 향상


성능 측정 방법: system.time과 R profiler

특정함수에 대한 시간만 보고싶으면 간단하게 system.time함수를 이용한다.

아래와 같이 do.call ldply의 성능을 비교한 것이다.
user, sys, elapsed이 세가지 관점으로 시간을 나타내주게 된다.

> ptList <- list(1:100000)
> system.time(do.call(rbind,ptList))
 사용자  시스템 elapsed 
      0       0       0 
> system.time(ldply(ptList,rbind))
 사용자  시스템 elapsed 
   0.17    0.00    0.17

사용자(user): 시간의 경우 프로그램 코드 자체를 R에서 수행한 시간이다.

시스템(sys): 시간의 경우 운영체제(OS)가 대신 작업을 처리하는데 걸린 시간이다. 예를 들면 save()또는 load()함수의 경우 sys 시간이 더 길게 된다. 이는 OS 작업을 통해서 파일 입출력을 수행하기 때문이다.
sys 시간이 크다면 메모리 부족도 의심해 봐야한다. R은 기본적으로 메모리에 모든 오브젝트를 로드하고 처리하므로 만약 메모리가 부족할경우 페이지 폴트가 지속적으로 발생해서 성능저하의 원인이 된다.

경과(elapsed): 시간는 가장 이해하기 쉬운 개념으로 프로그램 시작할 때 시간을 측정해서 끝날 때 종료한 시간 차이이다.

병렬 프로세싱 (doParallel, Window도 가능)

doMC는 내부적으로 fork()를 이용하기 때문에 linux에서 동작 하게 된다.
doParallel는 윈도우에서 사용 할 수 있는 package를 의미한다.

상세 관련 문서 vignette(“gettingstartedParallel”)

doParallel은 내부적으로 multicore, foreach, snow를 사용하기 때문에snow의 기능인 다수의 머신에 클러스터를 구현하는 기능을 제공하므로 doMC보다 더 막강하다고 할 수 있다.

install.packages("doParallel")
library(doParallel)

프로세스의 수 설정

코어의 수를 설정 한다.

registerDoParallel(cores=4)

작업관리자를 보면, Rscript.exe가 존재 하는 것을 알 수 있다.

plyr의 병렬화

{adl}{adl_}ply

형태의 함수들의 도움말을 살펴보면 .parallel 옵션이 있다. 이 옵션 값이 TRUE로 설정 되면
registerDoParallel()을 사용해 설정한 만큼의 프로세스가 동시에 실행되어 데이터를 병렬적으로 처리한다.

foreach의 병렬화

이미 for보다는 apply 계열의 함수가 더 빠르다는 것을 알고 있다.
foreach는 이러한 apply보다 더 빠른 loop연산 함수 이다.
그 이유가 바로 간단한 병렬화를 지원하기 때문이다.

foreach()는 기본적으로 %do를 사용해 실행할 명령의 블록을 지정해야 한다.
만약 foreach()에서 블록 내 명령을 병렬로 수행하고자 한다면registerDoParallel()을 한 뒤 foreach() %do% 대신 %dopar%를 지정하면 된다.

registerDoParallel로 core 수를 결정하면 실행 중인 프로세스 목록에 Rscript.exe라는 프로세스들이 설정한 코어 갯수 만큼 생성된것을 알 수 있다. 반복적으로registerDoParallel을 실행하면 해당 프로세스가 계속해서 늘어나기 때문에 이를 막기 위해서 명시적으로 stopImplicitCluster()를 해주는 것이 좋다.R-session을 종료하면 자동으로 정리해 주긴 하지만 말이다.

foreach는 apply()계열의 함수와 for()를 대체할 수 있는 루프문을 위한 함수 이다.
for문과의 가장 큰 차이는 반환 값이 있다는 점이다. 또한 {}가 아닌 %do%문을 사용해 블록을 지정한다는 점이다.

foreach::foreach(
    ... # 표현식 ex에 넘겨줄 인자
    # .combine은 ex에서의 반환 값을 어떻게 합칠지 지정한다. cbind(컬럼 방향으로 합친 데이터 프레임 반환),
    # rbind(행 방향으로 합친 데이터 프레임 반환), c(벡터로 반환) 등이 그예다. 기본값은 결과를 리스트로 합친다.
    .combine
    %do% ex # ex는 평가할 표현식
)

단순히 foreach만 사용할 경우

system.time(l1 <- rnorm(10000000))

library(foreach)
system.time(l2 <- foreach(i=1:4, .combine = 'c')
            %do% rnorm(2500000))

> system.time(l1 <- rnorm(10000000))
 사용자  시스템 elapsed 
   0.75    0.00    0.75 
> 
> library(foreach)
> system.time(l2 <- foreach(i=1:4, .combine = 'c')
+             %do% rnorm(2500000))
 사용자  시스템 elapsed 
   0.78    0.00    0.78

오히려 속도가 느려지는 것을 알 수 있다.

doParallel과 같이 이용
좀더 차이를 주기위해서 이전 예제보다 10대 갯수를 증가 시켰다.

> system.time(l1 <- rnorm(100000000))
 사용자  시스템 elapsed 
   7.38    0.14    7.55 
> 
> library(foreach)
> system.time(l2 <- foreach(i=1:4, .combine = 'c')
+             %do% rnorm(25000000))
 사용자  시스템 elapsed 
   8.28    0.28    8.58 

> library(doParallel)
> registerDoParallel(cores = 8)
> system.time(l3p <- foreach(i=1:10, .combine = 'c')
+             %dopar% rnorm(10000000))
 사용자  시스템 elapsed 
   1.54    2.25    5.15 
> stopImplicitCluster()

> length(l1)
[1] 100000000
> length(l2)
[1] 100000000
> length(l3p)
[1] 100000000

코어를 8개로 병렬화 했지만 8배까지는 아니고 2배정도 향상된것 같다.
데이터 분할 및 병합 overhead 때문에 발생하는 통상의 문제이다.
또한 i7-processor 특징상 물리적으로는 4-cores 지만 HT기술을 고려해서 논리적으론 8개로 잡았다.

작업이 끝나면 stopImplicitCluster()를 실행해서 closing doParallel cluster를 수행 시켜 주자.

하지만, stopImplicitCluster()을 수행할경우 apply()계열의 함수들이 connection error가 발생 하므로
모든 작업이 끝난 다음에 한번만 호출해 주자.

foreach 기타 옵션들

foreach값이 return하는 list/data.frame에 이름을 부여하고 싶을 경우
.final = function(x) setName(x, names(foo))를 이용한다.
.final은 마지막에 한번만 호출되게 된다.

foo <- list(a = 1, b = 2)
bar <- foreach (x = foo, .final = function(x) setNames(x, names(foo))) %do% {
    x * 2
    }

병렬 프로세싱 (Parallel package, Linux 전용)

set up worker processes that can complete tasks simultaneously.

It does this by including components of the multicore and snow packages, each taking a different approach towards multitasking.

To determine the number of cores your machine has, use the detectCores()function as follows.

An easy way to get started with the multicore functionality is to use themclappy() function, which is a parallel version of lapply().

mclapply {parallel}

mclapply(X, FUN, ..., mc.preschedule = TRUE, mc.set.seed = TRUE,
         mc.silent = FALSE, mc.cores = 1L,
         mc.cleanup = TRUE, mc.allow.recursive = TRUE)

참고자료

http://www.exegetic.biz/blog/2013/08/the-wonders-of-foreach/


위도,경도를 주소로 변환 ggmap package를 이용한 (geocoding and revgeocode in R)


GGMAP package

geocode

geocode함수는 latitude와 longitude를 가지고 location으로 변환 하는것을 말한다.
이것은 Google Map을 이용하게 된다.

Usage

geocode(location, output = c("latlon", "latlona", "more", "all"),
source = c("google", "dsk"), messaging = FALSE, force = ifelse(source ==
"dsk", FALSE, TRUE), sensor = FALSE, override_limit = FALSE,
client = "", signature = "", nameType = c("long", "short"), data)
geocodeQueryCheck(userType = "free")

예제

library(ggmap)

gc <- as.numeric(geocode('Baylor University'))
revgeocode(gc, output = 'more')
revgeocode(gc, output = 'all')

as.numeric(dfLocation[3,])
revgeocode(as.numeric(dfLocation[2:3,]),output = 'more')
revgeocode(latlng,output = 'more')
revgeocode(latlng, ics = 'WGS-84', api = 'google', output = 'address')

data.frame에 기록된 longitude와 latitude를 이용해서 Place로 변환하는 코드이다.

place <- adply(dfLocation, 1,function(x){
    revgeocode(as.numeric(x),output = 'more')
    }
)

test code

Using Google Maps API and R

library(RCurl)
library(RJSONIO)
library(plyr)

url <- function(address, return.call = "json", sensor = "false") {
    root <- "http://maps.google.com/maps/api/geocode/"
    u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
    return(URLencode(u))
}

geoCode <- function(address,verbose=FALSE) {
    if(verbose) cat(address,"\n")
    u <- url(address)
    doc <- getURL(u)
    x <- fromJSON(doc,simplify = FALSE)
    if(x$status=="OK") {
        lat <- x$results[[1]]$geometry$location$lat
        lng <- x$results[[1]]$geometry$location$lng
        location_type  <- x$results[[1]]$geometry$location_type
        formatted_address  <- x$results[[1]]$formatted_address
        return(c(lat, lng, location_type, formatted_address))
        Sys.sleep(0.5)
    } else {
        return(c(NA,NA,NA, NA))
    }
}
address <- geoCode("The White House, Washington, DC")


'AI > R Basic' 카테고리의 다른 글

Missing Value  (0) 2016.03.20
병렬화를 통한 연산 성능 향상 및 성능 측정 방법  (0) 2016.03.06
Do.call()  (0) 2016.02.05
날짜 시간 변환 (Date-Time Conversion Function in R)  (0) 2015.12.14
JSON in R using jsonlite  (0) 2015.12.12

Do.call()


데이터는 리스트 구조에 담겨져 있다.
이 데이터를 어떤 함수로 전달하고 싶지만 그 함수는 리스트를 인자로 받을 수 없는 구조이다.

해결책
1. 리스트를 벡터로 변환한다.
2. do.call함수로 리스트를 개별 인자들로 분해한 쓰려고 하는 함수에 적용 한다.

do.call(function, list)

예제 아래와 같이 중첩 리스트(nested list)일 경우에 데이터행렬로 변경하기가 골치아프게 된다.

> list <- list(col1 = list (1,2,3), col2 = list(3,4,5), col3 = list(6,7,8))
> list
$col1
$col1[[1]]
[1] 1

$col1[[2]]
[1] 2

$col1[[3]]
[1] 3


$col2
$col2[[1]]
[1] 3

$col2[[2]]
[1] 4

$col2[[3]]
[1] 5


$col3
$col3[[1]]
[1] 6

$col3[[2]]
[1] 7

$col3[[3]]
[1] 8

# cbind를 수행해도 원하는 않는 코드가 생성 된다.
> cbind(list)
     list  
col1 List,3
col2 List,3
col3 List,3


# data.frame()을 수행해도 이상한 결과이다.
> as.data.frame(list)
  col1.1 col1.2 col1.3 col2.3 col2.4 col2.5 col3.6 col3.7 col3.8
1      1      2      3      3      4      5      6      7      8

> unlist(list)
col11 col12 col13 col21 col22 col23 col31 col32 col33 
    1     2     3     3     4     5     6     7     8 

> cbind(unlist(list))
      [,1]
col11    1
col12    2
col13    3
col21    3
col22    4
col23    5
col31    6
col32    7
col33    8

#비로써 적절히 행과 열이 나뉘어서 합쳐지는 것을 볼 수 있다.
> do.call(cbind,list)
     col1 col2 col3
[1,] 1    3    6   
[2,] 2    4    7   
[3,] 3    5    8 


Date-Time Conversion Function in R


R에서는 이것의 처리를 위해서 POSIXlt POSICct를 사용 할 수 있다.

예제

> Sys.time()
[1] "2015-12-12 13:08:11 KST"
w
> Sys.timezone()
[1] "Asia/Seoul"

> Sys.Date()
[1] "2015-12-12"

현재 datetime을 class로 받은다음 그것을 integer로 변경하는 방법

> z <- Sys.time()
> z
[1] "2015-12-12 13:27:17 KST"
> unclass(z)
[1] 1449894437

#다시 원래대로 복구함
> as.POSIXct(1449894437,origin="1970-01-01")
[1] "2015-12-12 13:27:17 KST"

서로 다른 시간으로 변경하

> as.POSIXlt(Sys.time(), "GMT")
[1] "2015-12-12 04:45:42 GMT"
> as.POSIXlt(Sys.time(), "EST5EDT")  # the current time in New York
[1] "2015-12-11 23:46:48 EST"
> as.POSIXlt(Sys.time(), "EST" )     # ditto, ignoring DST
[1] "2015-12-11 23:46:48 EST"
> as.POSIXlt(Sys.time(), "HST")      # the current time in Hawaii
[1] "2015-12-11 18:46:48 HST"
> as.POSIXlt(Sys.time(), "Australia/Darwin")
[1] "2015-12-12 14:16:48 ACST"

timestamp (milliseconds) 처리하기

#POSIXct 함수를 이용한
time <- 1433848856453
timezone <- 10800000
options(digits.secs=3)
as.POSIXct((time+timezone)/1000, origin="1970-01-01")

lt와 ct의 차이

lt는 list time의 약어이고 ct는 continuous time`의 약어이다.

  • as.POSIXlt(): 시계열분석이나 년/월/일/시간/분/초 단위로 구분해서 연산을 해야 하는 경우 해당 함수로 날짜/시간 type으로 바꾸어주면 편하다.

  • as.POSIXct():

참고자료

http://astrostatistics.psu.edu/su07/R/html/base/html/as.POSIXlt.html
http://stackoverflow.com/questions/1962278/dealing-with-timestamps-in-r
지수표기를 숫자표기로 변경하는 R 옵션


Handling json in R using jsonlite


JSON format을 R에서 다루기 위해서는 두개의 package가 조재한다.
첫 번째는 rJSON package이고 두 번째는 jsonlite package이다.
여기서는 jsonlite를 다룬다. 이유는 rJSON을 fork하여 확장한것이 jsonlite이기 때문이다. version도 2015년 11월로 Post를 작성 하고 있는 지금도 계속해서 개선되어지고 있는 package이기 때문이다.

지원하는 함수들의 목록은 아래와 같다.

  • flatten: Flatten nested data frames
  • fromJSON: Convert R objects to/from JSON
  • prettify: Prettify or minify a JSON string
  • rbind.pages: Combine pages into a single data frame
  • serializeJSON: serialize R objects to JSON
  • stream_in: Streaming JSON input/output
  • unbox: Unbox a vector or data frame
  • validate: Validate JSON

Streaming JSON input/output

When can nested dataframe be appeared ?

아래는 3개의 data frame이 nested된 구조를 JSON으로 병경한 것이다.

[
{
"driver":"Bowser",
"occupation":"Koopa",
"vehicle":
    {
    "model":"Piranha Prowler","stats":
        {
            "speed":55,"weight":67,"drift":35
        }
    }
},
{
"driver":"Peach","occupation":"Princess","vehicle":
    {
    "model":"Royal Racer","stats":
        {
            "speed":34,"weight":24,"drift":32
        }
    }
}
] 

아래와 같이 ""안에 들어 있으면 그냥 value로 처리된다.

"data":"{}"

참고자료

http://rpackages.ianhowson.com/cran/jsonlite/man/stream_in.html
JSON 공식 사이트


'AI > R Basic' 카테고리의 다른 글

Do.call()  (0) 2016.02.05
날짜 시간 변환 (Date-Time Conversion Function in R)  (0) 2015.12.14
통계처리 (기본)  (0) 2015.10.28
데이터 분리 및 병합 (split, subset, merge)  (1) 2015.10.22
doBy package, 데이터 그룹 처리  (0) 2015.10.22

통계처리 (기본)



Rounding of Numbers


정확한 계산을 필요로 하는 경우도 있지만, 때로는 반올림을 할 필요도 있다. 이 경우를 위해서 R은 아래와 같은 

몇가지 반올림 관련 함수들을 제공 한다.


ceiling(x)

floor(x)

trunc(x, ...)

round(x, digits =)

signif(x, digits =)


digits는 반올림할 decimal point의 위치를 결정 한다. 

상수면 소수점(decimal point)를 나타내며, 음수면 10,100의 자리를 나타낸다 (multiples of 10, 100).


round(123.456, digits=2)
[1] 123.46
round(-123.456, digits=-2)
[1] 100




만약 유효숫자(significant digits)를 숫자의 크기에 상관없이 명시하고 싶다면,

signif()를 사용할 수 있다.

> signif(-123.456,digits=4)
[1] -123.5
> signif(-123.456,digits=5)
[1] -123.46
> signif(-123.456,digits=1)
[1] -100
> signif(-123.456,digits=1)
[1] -100



round와 signif는 5를 기준으로 작은지 큰지에 따라 rounding을 수행 한다. 이와 다르게 한쪽 방향으로만 rounding을 수행하는

함수들도 존재 한다.


floor(x) 가장 작은 정수로 x가 결정 된다.

> floor(123.45)
[1] 123
> floor(-123.45)
[1] -124


ceiling(x) 가장 큰 정수로 x가 결정 된다.

> ceiling (123.45)
[1] 124
> ceiling (-123.45)
[1] -123



trunc(x) 가장 가까운 정수로 반올림되는데 방향이 0이랑 가장 근접한 쪽이다.

> trunc(123.45)
[1] 123
> trunc(-123.45)
[1] -123




데이터 분리 및 병합 (split, subset, merge)


split

split: 주어진 조건에 따라서 데이터를 분리 한다.
x # 분리할 벡터 또는 데이터 프레임
f # 분리할 기준을 지정한 factor

iris$Species에 따라서 분리하고 이것을 리스트에 저장 한다.

> head(split(iris, iris$Species))
$setosa
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1           5.1         3.5          1.4         0.2  setosa
2           4.9         3.0          1.4         0.2  setosa

$versicolor
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
51           7.0         3.2          4.7         1.4 versicolor
52           6.4         3.2          4.5         1.5 versicolor

$virginica
    Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
101          6.3         3.3          6.0         2.5 virginica
102          5.8         2.7          5.1         1.9 virginica

split()의 실행 결과가 리스트므로, split()후 lapply()를 적용하면 iris의 종별 Sepal.Length의 평균을 구할 수 있다.

> lapply(split(iris$Sepal.Length, iris$Species),mean)
$setosa
[1] 5.006

$versicolor
[1] 5.936

$virginica
[1] 6.588

subset()

subset()
x # 일부를 취할 객체
subset # 데이터를 취할 것인지 여부

# 특정 조건에 의해서 데이터를 추출한다.
> subset(iris, Species == "setosa" & Sepal.Length > 5.0)
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1           5.1         3.5          1.4         0.2  setosa
6           5.4         3.9          1.7         0.4  setosa
11          5.4         3.7          1.5         0.2  setosa
15          5.8         4.0          1.2         0.2  setosa
16          5.7         4.4          1.5         0.4  setosa
17          5.4         3.9          1.3         0.4  setosa
18          5.1         3.5          1.4         0.3  setosa
#특정 컬럼을 선택해서 데이터를 추출 한다.
> subset(iris, select=c(Sepal.Length, Species))
    Sepal.Length    Species
1            5.1     setosa
2            4.9     setosa
3            4.7     setosa
4            4.6     setosa
5            5.0     setosa
#특정 컬럼을 제거하는 두가지 서로 다른 스타일의 방법이다.
> subset(iris, select=-c(Sepal.Length, Species))
    Sepal.Width Petal.Length Petal.Width
1           3.5          1.4         0.2
2           3.0          1.4         0.2
3           3.2          1.3         0.2
4           3.1          1.5         0.2
5           3.6          1.4         0.2
6           3.9          1.7         0.4
7           3.4          1.4         0.3
> iris[, !names(iris) %in% c("Sepal.Length","Species")]
    Sepal.Width Petal.Length Petal.Width
1           3.5          1.4         0.2
2           3.0          1.4         0.2
3           3.2          1.3         0.2
4           3.1          1.5         0.2
5           3.6          1.4         0.2
6           3.9          1.7         0.4

merge

merge(): 두 데이터 프레임을 공통된 값을 기준으로 묶는 함수다.
Database에서 join과 같은 역할을 하는 함수 이다.

다음은 name column을 기준으로 수학 점수가 저장된 데이터 프레임과 영어 점수가 저장된 데이터 프레임을 병합한 예이다.
x와 y에 name값이 서로 다른 순서로 저장되어 있으나 공통된 name 값을 기준으로 점수가 잘 병합된 것을 볼 수 있다.

> x <- data.frame(name=c("a","b","c"), math=c(1,2,3))
> y <- data.frame(name=c("c","b","a"), english=c(4,5,6))
> merge(x,y)
  name math english
1    a    1       6
2    b    2       5
3    c    3       4

cbind의 경우 단순히 column만 합치는 것이기 때문에 merge()하고 그 결과가 다르다.

> cbind(x,y)
  name math name english
1    a    1    c       4
2    b    2    b       5
3    c    3    a       6

merge() 수행 시 공통된 값이 한쪽에만 있는 경우에는 반대편 데이터가 비게 되고 이 경우 해당 행은 병합 결과에서 빠진다.
NA를 추가해서라도 전체 데이터를 모두 병합하고 싶다면 all 인자에 TRUE를 지정 한다.

아래의 예제는 all=FALSE(기본값)인 경우와 all=TRUE인 경우의 비교를 보인 것이다.
all=FALSE인 경우에는 공통된 name이 양측에 포함된 "a","b"만 결과에 나타나며, all=TRUE인 경우 공통된 값이 없는 쪽에 NA가 채워지면서 x,y의 전체 행이 결과에 포함된다.

> y <- data.frame(name=c("c","b","d"), english=c(4,5,6))
> merge(x,y)
  name math english
1    b    2       5
2    c    3       4
> merge(x,y, all=TRUE)
  name math english
1    a    1      NA
2    b    2       5
3    c    3       4
4    d   NA       6


'AI > R Basic' 카테고리의 다른 글

JSON in R using jsonlite  (0) 2015.12.12
통계처리 (기본)  (0) 2015.10.28
doBy package, 데이터 그룹 처리  (0) 2015.10.22
R 기본 디버깅 (Debugging) 및 RStudio 이용  (0) 2015.10.04
R Studio 설치법 및 사용 Tip  (0) 2015.10.04

doBy package, 데이터 그룹 처리


doBy 패키지에는 summaryBy(), orderBy(), sampleBy()와 같은 특정 값에 따라 데이터를 처리하는 유용한 함수들이 있다.

다음은 이 함수들의 특징을 요약한 것이다.


 함수

특징 

 doBy::summaryBy()

 데이터 프레임을 컬럼 값에 따라 그룹으로 묶은 후 요약 값 계산 

 doBy::orderBy()

 지정된 컬럼 값에 따라 데이터 프레임을 정렬

 doBy::sampleBy()

 데이터 프레임을 특정 컬럼 값에 따라 그룹으로 묶은 후 각 그룹에 샘플 추출



install.packages("doBy")

library(doBy)



▣ summaryBy()


doBy::summaryBy: 포뮬러에 따라 데이터를 그룹으로 묶고 요약한 결과를 반환한다.

formula, #요약을 수행할 포뮬러

data=parent.frame() # 포뮬러를 적용할 데이터


반환 값은 데이터 프레임이다.


저것을 사용하기 위해서 formula 문법에 대해서 알아야 한다.



 연산자

예 

의미 

 Y~X1+X2

 Y를 X1, X2로 모델링, 상수항은 암시적으로 허용 된다. 따라서 선형 회귀에 이 포뮬러를 사용하면 Y=a*X1 + b * X2 + c 를 의미한다.

-

 Y~X1-X2

 Y를 X1로 모델링하되 X2는 제외한다.


특히, 선형 회귀에서 Y ~ X1 + X2 - 1은 Y를 X1과 X2로 모델링하되 상수항은 제외 한다는 의미다. 즉, Y= a*x1 + b * X2를 의미한다.

|

 Y~X1 | X2

 X2의 값에 따라 데이터를 그룹으로 묶은 후 각 그룹별로 Y~X1을 적용한다. 

:

Y ~ X1:X2 

 Y를 X1과 X2의 상호 작용 (interaction)에 따라 모델링 한다. 상호 작용은 Y = a * X1 * X2 + b 와 같이 X1과 X2가 동시에 Y 값에 영향을 주는 상황을 말한다.


특히, 영향을 주는 방식이 (+) 합 연산자의 예제인 Y= A*X1 +b*X2 +c와 같은 형태와는 전적으로 다르다.

*

 Y ~ X1 * X2

 Y ~ X1 + X2 + X1:X2의 충약형 표현이다.



summaryBy는 특정 조건에 따라 컬럼의 값을 요약해서 보여주게 된다.

아래의 경우 Sepal.Length와 Sepal.With를 Species에 따라 출력해서 보는 방식이다.

> summaryBy(Sepal.Width + Sepal.Length ~ Species, iris)
     Species Sepal.Width.mean Sepal.Length.mean
1     setosa            3.428             5.006
2 versicolor            2.770             5.936
3  virginica            2.974             6.588



▣ orderBy


doBy::orderBy: 포뮬러에 따라 데이터를 정렬한다.

formula, # 정렬할 기준을 지정한 포뮬러

# ~의 좌측은 무시하며, ~ 우측에 나열한 이름에 따라 데이터가 정렬된다.

data, # 정렬할 데이터


기본은 ascending 이기 때문에 descending으로 하고 싶을 경우 - (마이너)를 붙인다.

orderBy(~-Mean, dataFrame) 이런 식이다.


# 다음의 코드는 Species, Sepal.Width 순으로 정렬한 예이다.
> orderBy(~Species + Sepal.Width, iris)
    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
42           4.5         2.3          1.3         0.3     setosa
9            4.4         2.9          1.4         0.2     setosa
2            4.9         3.0          1.4         0.2     setosa
13           4.8         3.0          1.4         0.1     setosa
14           4.3         3.0          1.1         0.1     setosa


▣ sampleBy


doBy::sampleBy
formula, # ~우측에 나열한 이름에 따라 데이터가 그룹으로 묶인다.
frac = 0.1 #추출할 샘플의 비율이며 기본값은 10%
replace = FALSE # 복원 추출 여부
data=parent.frame() # 데이터를 추출할 데이터 프레임
systematic=FALSE # 계통 추출 (Systematic Sampling)을 사용할지 여부

반환 값은 데이터 프레임이다.


샘플 함수는 정보를 추출하는 함수이다. 아래와 같다.

10개 중 5개를 랜덤으로 추출한다. replace=TRUE를 설정하면 중복을 허용하는 것이다.

sampleBy과 대응 되므로 같이 알아두면 좋다.

> sample(1:10,5)
[1]  1 10  7  3  8
> sample(1:10,5, replace=TRUE)
[1] 8 8 2 3 6


이러한 샘플링은 주어진 데이터를 Training DataTest Data로 분리하는데 유용하게 사용 할 수 있다.


절적한 모델 테스팅을 위해선 균일한 분푸로 Test Data를 생성하는 것이 좋다. 이럴떄 sampleBy가 유용하게 사용 된다.

다음은 Iris 데이터에서 각 Species 별로 10%의 데이터를 추출한 예이다. sampleBy()에서 Species를 지정했으므로 각 종별로 5개씩 데이터가 정확히 샘플로 추출된 것을 볼 수 있다.

> sampleBy(~Species, fra=0.1, data=iris)
              Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
setosa.13              4.8         3.0          1.4         0.1     setosa
setosa.24              5.1         3.3          1.7         0.5     setosa
setosa.27              5.0         3.4          1.6         0.4     setosa
setosa.35              4.9         3.1          1.5         0.2     setosa
setosa.40              5.1         3.4          1.5         0.2     setosa
versicolor.59          6.6         2.9          4.6         1.3 versicolor
versicolor.64          6.1         2.9          4.7         1.4 versicolor
versicolor.77          6.8         2.8          4.8         1.4 versicolor
versicolor.84          6.0         2.7          5.1         1.6 versicolor
versicolor.89          5.6         3.0          4.1         1.3 versicolor
virginica.102          5.8         2.7          5.1         1.9  virginica
virginica.104          6.3         2.9          5.6         1.8  virginica
virginica.121          6.9         3.2          5.7         2.3  virginica
virginica.132          7.9         3.8          6.4         2.0  virginica
virginica.144          6.8         3.2          5.9         2.3  virginica






R 기본 디버깅 (Debugging) 및 RStudio 이용


디버깅 방법은 아래와 같이 크게 2가지로 나눠 진다.

  • print(), sprint(), cat()을 사용해서 메시지나 객체의 내용을 출력해보는 방법
  • browser()를 사용한 코드 디버깅 방법


print()


print()문으로 중간 중간 데이터를 찍어 보면서 수행 하도록 한다.

paste() 함수와 같이 쓰는면 유용하다.

인자간의 공백을 사용하지 않는 함수는 paste0() 함수 이다.

fibo <- function (n) {
    if (n == 1 || n == 2) {
        print (" base case ")
        return (1)
    }
    print ( paste0 (" fibo (", n - 1, ") + fibo (", n - 2, ")"))
    return ( fibo (n - 1) + fibo (n - 2))
}
> fibo(3)
[1] " fibo (2) + fibo (1)"
[1] " base case "
[1] " base case "
[1] 2


sprintf()


print()와 유사하지만 주어진 인자들을 특정한 규직에 맞게 문자열로 변환해 출력 한다.

sprintf("포멧팅 문자열",인자1,인자2,..인자n)
# %d / %f / %s (C언어의 문법과 유사하다)


cat()


행 바꿈을 수행하지 않고 출력하는 특징이 있다.

줄바꿈 하고 싶으면 "\n"을 수행 하면 된다.


이러한 특징 때문에 cat()을 사용해서 테스트 방식의 프로그레스 상태 메시지를 보여줄 수 있다.

> sum_to_ten <- function () {
+     sum <- 0
+     cat(" Adding ...")
+     for (i in 1:10) {
+         sum <- sum + i
+         cat(i, "...")
+     }
+     cat(" Done !", "\n")
+     return (sum)
+ }
> sum_to_ten()
 Adding ...1 ...2 ...3 ...4 ...5 ...6 ...7 ...8 ...9 ...10 ... Done ! 
[1] 55


Cat을 이용한 또다른 디버깅 코드이다.

#for detecting error, analyze each Corpus

sapply(1:length(vTitle), function(x){

    cat(x,'...')

    sms_corpus_clean <- tm_map(sms_corpus[x], content_transformer(tolower))

    if(x%%10 == 0){

        cat('\n')

    }

})



browser()


해당 함수가 호출 되면 명령어의 수행이 중지되고, 해당 시점부터 디버깅 모드가 시작된다.

원하는 부분에다가 직접 browser() 코드를 삽입 해야한다.

그럼 해당 코드 위치에 도달 했을때

Browse[1]> 이라는 명련 표시줄로 변경이 된다.

명령어는 gdb와 대부부 같다.

n,s,c

종료는 Q 이다.


browser()만의 장점은 다음과 같다.

  • 어떠한 editor에서도 사용하다.
  • 추가적으로 conditional breakpoint의 기능을 구현할수도 있다.
for (i in 1:1024) {
  start_work()
  if (i == 512)
    browser()
  finish_work()
}



R-Studio를 이용한 디버깅 방법



아래와 같이 편집기에서 마우스로 클릭하면 breakpoint를 설정 할 수 있다.

해당 라인에서 Shift + F9를 해도 된다.


breakpoint를 설정하면 아래와 같이 걸려있는 함수를 환경변수 패널에서 확인 할 수 있다.


만약 아래와 같은 경고가 나온다면 이유는 두가지 이다.

첫 번째는 source()를 통해서 해당 파일을 읽어 들이지 않아서 그래서 object가 생성되지 않았을 때이다.

두 번째는 editor 상의 file과 source()로 읽어들인 file간의 차이가 존재 했을 때이다.


위 두상황 모두 source()를 해주면 해결 된다.



정상적으로 breakpoint를 걸었다면,

이제 해당 코드를 실행하면 원하는 위치에서 멈추는거을 알 수 있다.

R Studio는 디버깅 명령어들을 모두 위즈윅 모드로 제공하므로 마우스를 써서 디버깅 하면 된다.


디버깅 실행 화면



만약 source 코드가 없는 상태에서 디버깅 하고 싶다면?


install.packages("devtools")


참고문헌: Debugging with RStudio





R Studio 설치법 및 사용 Tip



R Studio의 특징


대화식 R

R 그래픽 작업

코드 구조화, 다수의 프로젝트 관리

분석 내용 재현

R에 설치된 패키지 관리

분석 보고서 작성 및 공유

본인의 코드 공유 및 다른 사용자와의 협업

다양한 적용 가능 플랫폼

윈도우

리눅스

맥 OS X



Comprehensive R Archive Network


R언어를 일단 잘알아야 RStudio를 통해서 통계분석이 가능하다.

위즈윅(WYSIWYG)에 익숙한 사람들, 즉 마우스로 클릭하고 데이터를 이동하는것에 익숙 했던 사람들은 여간 사용하기 어려운것이 아니다.



하지만, 분석의 재현을 위해서는 반드시 각 분석 단계를 소스코드 형태로 저장해야한다.

그래야 분석 과정을 재현하기 쉽다.


프로그래밍 방식은 또한 

단순히 사전식으로 해당 기능에대해서만 동작하는 위즈윅 방식의 툴보다 훨씬 유연하며 강력한 기능을 조합을통해서 달성 할 수 있다.



항상 최신 버전을 사용하라

View(news()) 를통해서 최신 정보를 알 수 있다.

update.packages()를 통해서 페키지를 업데이트 하라



설치방법


1. R을 설치해야한다.


Rstudio는 기본적으로 2.11 이상의 R을 설치해야한다. 

공식 사이트: http://www.r-project.org/

이곳에서 가장 가까운 서버인

http://cran.nexr.com/

위 사이트에서 Window용 R을 다운 받았다.

Tip: 항상 최신 버전의 알을 수시로 확인해서 다운받아서 설치하자


1.1 업데이트 방법

기본적으로 자동 업데이트는 제공하고 있지 않으므로, 이전 버전을 제거한다음 새로 설치하면 된다.


이전 package 설치본들을 복사한 다음 붙여 넣기 한다.

그 다음 현재 package들을 업데이트 한다.

update.packages(checkBuilt=TRUE, ask=FALSE) 


개인 라이브러리의 경우 아래의 경로에 저장 되어 있다.

C:\Users\<사용자이름>\Documents\R\win-library\3.3


현재 R에 설치된 라이브러리 리스트를 얻어서 그대로 재설치하는 방법도 있다.

library()


현재 R의 버전을 알아내는 방법


package_version(R.version)


아래의 명령어를 통해서 설치된 package와 설치된 version을 알 수 있다.


installed.packages()[,c("Package","Version")]
> installed.packages()[,c("Package","Version")]
             Package        Version   
BH           "BH"           "1.58.0-1"
bitops       "bitops"       "1.0-6"   
brew         "brew"         "1.0-6"   
caTools      "caTools"      "1.17.1"  
colorspace   "colorspace"   "1.2-6"   
curl         "curl"         "0.9.3"   



2. R studio 설치

공식 사이트: http://www.rstudio.com/products/rstudio/download/

Tip: RStudio에서

Help > Check for Updates를 클릭하여 신규 업데이트 정보를 확인하자.

업데이트가 필요하면 위 공식 사이트에가서 신규버전으로 다시 설치하자.

아직까지는 자동 업데이트 기능은 없는것 같다.


3. 필수 package 설치 및 로드

R studio의 하단에 보면 package tab이 있다. 이곳에서 이미 설치된 package들의 리스트를 확인 할 수 있다. 


update 버튼을 통해서 기존 package들을 업데이트 할 수도 있다. 


그리고 install을 통해서 새로운 package들을 쉽게 설치 할 수 있다. 


추가로 설치한 리스트

install.packages("ggplot2")

xlsx 

knitr // A General-Purpose Package for Dynamic Report Generation in R


설치된 package를 로드하기위해서는

library 명령어를 타이핑 해도되고

package 창에서 마우스로 check 해도 된다.



단축키 (shortcuts)


Keyboard Shortcuts: R support





GIt을 이용한 버전 관리


git을 설치한다.

자신의 운영체제에 맞춰서 설치파일을 다운로드 한다.

https://git-scm.com/downloads



Next > Next 만을 선택해서 설치한다.

설치확인 방법은 아래와 같이 적당한 디렉터리 아무곳에서나 오른쪽 마우스 클릭을해서

Git bash here 와 같은 명령어들이 모이면 정상적으로 설치된 것이다.




RStudio와 연동하기

메뉴 바에서

Toos -> Global Options -> Git/SVN 에서 Git을 설치한 디렉터리에서 git 실행파일을 연결해 준다.


git



이렇게 하고 재부팅을 해준다.

아래와 같이 정상적으로 git tab이 생성되는것을 알 수 있다.





자료형(integer,character) 변환 및 데이터 구조(dataFrame, list) 변환



자료형


각각의 자료형들간의 변환은 아래의 함수들을 이용 한다.

as.character(x)

as.complex(x)

as.numeric(x) or as.double(x)

as.integer(x)

as.logical(x)





R에서는 데이터 분석을 위한 유용한 데이터 구조를 기본으로 제공해 준다.

데이터 구조(5개): vector, list, data frame, matrix(array), factor 


모드: 

R에서 해당 객체를 메모리에 어떻게 저장할 것인가를 가리키는 것이 "모드"이다

숫자로 저장할 것인가?

문자열 ?

다른 객체로의 포인터로된 리스트들?

함수?

위의 다양한 것들로서 메모리에 저장 될 수 있다.


객체, 예, 모드

숫자, 3.21415, 수치형

숫자백터, c(2, 3), 수치형

문자열, "More", 문자형

문자열 백터, c("More","Larry","Curly"), 문자형

요인, factors(c("NY","CA","IL")),수치형

리스트, list("More","Larry","Curly"), 리스트

데이터 프레임, data.frame(x=1:3, y=c("NY","CA","IL")), 리스트

함수, print, 함수


알아내느 방법

mode()



Class: 추상적인 자료형


R에서는 모든 객체는 추상 자료형인 '클래스'도 가지고 있다.

거리, 시간, 무게 모두 어떤 숫자이므로 모드는 숫자(numeric)이다.

하지만 각각의 해석 방법이 다르므로 클래스는 상이할 수 있다.


결국 클래스가 R에서 직접적인 데이터 처리 방식을 결정하게 된다.


예를들면 print()라는 함수는 입력된 데이터의 class에 따라서 그 처리를 다르게 하는 것이다.

위에서 설명한 모드는 메모리에 저장되는 형태지, 논리적으로 프로그래밍 할 때 쓰는 단위는 아니다.





Factor (범주형 자료)



생성 방법

factor(

x, #팩터로 표현하고자 하는 값(주로 문자열 벡터로 지정)

levels, #값의 레벨

ordered #TRUE면 순서형, FALSE면 명목형 데이터를 뜻한다. 기본값은 FALSE다.

)


팩터에서 레벨의 개수를 반환함.

nlevels(

x # 팩터 값

)


중간에 값 넣기

factor(append(as.character(proximity),"TRUE"))


factor level rename

http://www.cookbook-r.com/Manipulating_data/Renaming_levels_of_a_factor/



Vectors


백터는 동질적이다.

같은 자료형을 가진다.

같은 모드를 가지고 있어야 한다.


스칼라와 백터의 관계는 통상 엄밀히 구분하지만 R에서는 딱히 구분하지 않는다.

하나의 값으로 구성된 백터가 스칼라고

여러개 있으면 백터라고 생각하면 된다.




List


이질적이다.

다양한 자료형을 포함 할수 있다.


생성방법

list <- list(x,y,z) #이질적인 데이터도 가능함.

list <- list(mid=0.5, right=0.841, far=0.9)



접근방법

리스트 변수[[인덱스] # 값을 접근함

리스트 변수[인덱스] # (키,값) 의 형태로 서브 리스트를 반환 한다.


제거방법

x[-2] # without 2nd element

x[-c(2,3)] # without 2nd and 3rd

x["arrival_time"] <- NULL


빈리스트를 생성하고 인덱스를 이름으로 지정하는 방법

vecNames <- list.files("./ESLABCollector/")
filenames <- sapply(vecNames,list)  

Foreach를 사용할 때 list 인덱스의 이름을 유지하는 방법

jsonDfList <- foreach (x = rawDataList, .final = function(x) setNames(x, names(filenames))) %do% {

    jsonTodf(x)

}


.final 을 이용한다.

결국 setNames란 아래의 것을 축약한 기능이다.

setNames( 1:3, c("foo", "bar", "baz") )

# this is just a short form of

tmp <- 1:3

names(tmp) <-  c("foo", "bar", "baz")

tmp



List 중간에 값을 삽입 하기


append(testList, list(x=42), 3)

$`1`

[1] 1

$`2`

[1] 2

$`3`

[1] 3

$x

[1] 42

$`4`

[1] 4


append(lst, list(f=1:5), after=0)# after - position to append

Helper 함수를 생성하는 방법

lappend <- function (lst, ...){
lst <- c(lst, list(...))
  return(lst)
}

> a <- list()
> a
list()

> lappend(a,c(1,2,3))
[[1]]
[1] 1 2 3

> lappend(a, c(4,5,6), c(7,8,9))
[[1]]
[1] 4 5 6

[[2]]
[1] 7 8 9




Matrix


백터에 차원을 정해주면 바로 Matrix로 변경 된다.


백터의 dim 속성이 처음엔 NULL 이지만 이것을 주게 되면 matrix가 된다.

dim(2,3) # 2 by 3 행렬


list도 dim 변경을해서 행렬화 할 수 있다.

하지만 list의 특성상 이질적인 행렬을 만들어 낼 수 있으므로 그러한 것들은 조심해야 한다.




Array (배열)


3차원 matrix 부터는 배열이라는 이름을 쓴다.


Factor(요인)

백터처럼 생겼지만 특별한 속성이 있다.

R은 백터에 있는 고유한 값(unique value)의 정보를 얻어 내는데, 이 고유 값들을 요인의 '수준(level)'이라고 일컫는다.

요인들은 간단하고 효율적인 형태로 데이터 프레임에 저장된다.

다른 프로그래밍 언어에서는 요인을 '열거형 값(enumerated value)들로 이루어진 백터로 표현한다.


요인의 사용처는 아래와 같다.


범주형 변수>

요인 하나는 범주형 변수 하나를 나타낼 수 있다. 

범주형 변수들은 분할표, 선형 회귀, 변량 분석, 로지스틱 회귀 분석 등 많은 분야에서 사용 된다.


집단 분류

이것은 데이터 항목에다가 집다에 따른 라벨을 붙이거나 태깅을 할 때 쓰는 방법이다.




데이터 프레임 (Data Frame)


가장 중요한 데이터 타입이다.

표 형태의 데이터를 표현하기 위함이다.


특징

행은 모두 같은 길이이다. 열은 하나의 엘리먼트를 나타낸다.

행렬과 다른점은 각각의 행들이 서로다른 데이터 타입들을 가질 수 있다는 것이다.

즉, 각각의 열들은 같은 타입으로 이뤄지지만, 모든 열이 모두 같을 필요는 없다.

데이터 프레임의 속성은 row.names()를 통해서 알 수 있다.

통상 read.table() 또는 read.csv()를 통해서 생성 한다.

행렬을 data frame으로 변경 할 수 있다. data.matrix() 호출을 통해서



▣ 데이터 프레임 생성하기

data.frame()을 사용


g <- c("A","B")

x <- 1:3

dat <- data.frame(g,x)


▣ 리스트를 프레임 데이터로 변경

frame.data(list)



▣ 프레임의 구조를 알려준다.

str(data)

> str(ac)

'data.frame': 356 obs. of  2 variables:

 $ Time : num  0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 ...

 $ Power: num  14.8 14.1 19.9 14.6 14.1 ...



▣ 프레임에서 열들만 따로 출력하는 방법이다.

data$time



▣ 데이터 프레임의 Index를 알아내는 방법

> a <- data.frame(1:6,11:16)

> a

  X1.6 X11.16

1    1     11

2    2     12

3    3     13

4    4     14

5    5     15

6    6     16

> grep(15,a[,2])

[1] 5


▣ 해당 컬럼 이름이 몇번째 인지를 알아내는 방법

> grep("X11.16",colnames(a))

[1] 2



▣ 프레임에서 행과 열만 따로 출력하는 방법이다.

data$time[0]



▣ 위치로 데이터 프레임의 열 선택하기


스타일에 따라 또는 데이터프레임 두가지 자료형중 하나로 반환 된다.


데이터 프레임 스타일의 선택 방법

dfm[[n]] # 하나의 열을 반환 한다.

dfm[n] # n번째 열 단독으로만 구성된 '데이터 프레임'을 반환 한다.

dfm[c(n1,n2,...,nk)] # n1,n2,....,nk 위치에 있는 열들로 만든 "데이터 프레임"을 반환한다.


행렬 방식의 첨자 지정을 이용해서 선택 하는 방법

dfm[,n] # n번째 을 반환 한다

dfm[,c(n1,n2,...,nk)] # n1,n2,...,nk 위치에 있는 열들로 만든 "데이터 프레임"을 반환 한다.



▣ 프레임 열의 이름을 변경하는 방법이다.

names(data) <- c("name1", "name2", "name3")

 


▣ 특정 열을 찾아서 이름을 변경하는 방법

> names(ac)[names(ac)=="Time"] <- c("newTime")

> names(ac)

[1] "newTime" "Power"  

> names(ac)[names(ac)=="newTime"] <- c("Time")

> names(ac)

[1] "Time"  "Power"



▣ 데이터 프레임에 열 추가하기

새로운 열의 이름을 설정하고 "NA"로 채운다.

data$newcol <- NA


새로운 열의 이름을 설정하고 백터를 삽입한다.

data$newcol <- vec



▣ 데이터 프레임에 열을 제거하기

해당열에 NULL을 대입한다.


data$badcol <- NULL

subset(data, select = -badcol)

subset(data, select = c(-badcol, -othercol)



▣ 데이터 프레임 열 순서 변경하기

#숫자로 해당열을 선택해서 변경한다.

dat <- dat[c(1,3,2)]


#이름으로 선택해서 변경 한다.

data <- dat[c("col1","col3","col2")]



▣ 데이터 프레임의 부분 집합 취하기

subset() 함수를 이용해서 부분 집합을 취할 수 있다.


일련의 조건을 기입하고 그 조건에 맞는 행등을 추출 할 수 있다.


subset(climate, Source == "Berkeley", select = c(Year, Anomaly10y))

# 데이터 셋 climate에서

# Source 열이 "Berkeley인 것에 대해서

# Year 와 Anomaly10y의 열에 대해서만 그 값을 추출 


논리 연산자를 조합하면 일정 범위 내의 데이터를 추출 할 수도 있다.


1900년에서 2000년 사이의 source가 "Berkeley"인 행들만 선택 한다.

subset(climate, Source == "Berkeley" & Year >= 1900 & Year <= 2000, select = c(Year, Anomaly10y))



▣ 여러가지 방법을 이용한 데이터 프레임 합치기


데이터 프레임 합치기

cbind # 두개의 데이터를 열로 쌓는다.

rbind # 두개의 데이터를 행으로 쌓는다.


연속적인 리스트라면,

do.call(rbind,mylist)를 하면된다.


주의: 위방법들은 모두 행열이 같은 크기일때만 가능함

크기가 서로 다르면 반복해서 아랫부분을 채워준다고 하지만 이상하게 동작하지 않는다.


서로다른 데이터 프레임 합치기

merge # SQL에서 join에 해당하는 명령어이다

default로 동작은 그냥 다순히 합치는 것이다.

일치하지 않는것이 있다면 데이터의양이 NxM의 양으로 늘어 난다.


일치하는 부분만 합치고 싶으면,

merge(A,B, by="열 이름") 

으로 설정한다.


merge의 다른 option들

## S3 method for class 'data.frame'
merge (x, y, by = intersect(names(x), names(y)),
      by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all,
      sort = TRUE, suffixes = c(".x",".y"),
      incomparables = NULL, ...)

x, y

data frames, or objects to be coerced to one.

by, by.x, by.y

해당 기준으로 합친다. 없는것는들은 제거한다.

즉, 가장 짧은 기준으로 합친다.

5, 10 이라면 5만큼 길이가 설정됨.

all

logical; all = L is shorthand for all.x = L and all.y = L, where L is either TRUE or FALSE.

all.x

logical; if TRUE, then extra rows will be added to the output, one for each row in x that has no matching row in y. These rows will have NAs in those columns that are usually filled with values from y. The default is FALSE, so that only rows with data from both x and y are included in the output.

all.y

logical; analogous to all.x.

sort

logical. Should the result be sorted on the by columns?

suffixes

a character vector of length 2 specifying the suffixes to be used for making unique the names of columns in the result which not used for merging (appearing in by etc).

incomparables

values which cannot be matched. See match. This is intended to be used for merging on one column, so these are incomparable values of that column.


서로다른 크기의 데이터 프레임 합치기

일치하지 않는 컬럼을 단순히 <NA>로 채우고 싶다면,

plyr package의 rbind.fill을 사용하면 된다.



향상된 데이터 프레임 합치기

reshape2 package

본인 정리

Reshape and aggregate data with the R package reshape2


plyr package

본인정리


데이터 프레임 행과 열 크기 알아내기

nrow()

ncol()


help(package = "reshape2")

원본 참고 사이트: http://seananderson.ca/2013/10/19/reshape.html

reshape 2 website: http://had.co.nz/reshape/



서로 다른 데이터 타입들간의 데이터 상호 변환




변환 

방법 

주석 

 벡터 -> 리스트

as.list(vec) 

 

 벡터 -> 행렬

cbind(), as.matrix()

rbind(), matrix(vec,n,m) # n by m 행렬 

생성 

 

 벡터 ->데이터 프레임

#열 한 개짜리 데이터 프레임

as.data.frame(vec)

# 행 한 개짜리 데이터 프레임

as.data.frame(rbind(vec))

 

 리스트 -> 벡터

unlist(list)

as.vector 대신에 unlist가 좋다. 

 리스트 -> 행렬 

열 한 개짜리 행렬: as.matrix(list)

행 한 개짜리 행렬: as.matrix(rbind(list))

n by m 행렬: matrix(list,n,m) 

 

 리스트 -> 데이터 프레임

목록 원소들이 데이터의 열이면:

as.data.frame(list)

 

 

 행렬 -> 벡터

 as.vector(mat) 

 행렬의 모든 원소들을 벡터로 반환 한다. 

 행렬 -> 리스트

 as.list(mat)

 행렬의 모든 원소들을 리스트로 변환 한다.

 행렬 -> 데이터 프레임

 as.data.frame(mat) 

  

 데이터 프레임 -> 벡터

 dfm[1,]#행 하나 짜리 데이터 프레임 변환

 dfm[,1] or dfm[[1]] #열 하나짜리 데이터 프레임 변환

 

 데이터 프레임 -> 리스트

 as.list(dfm)

 

 데이터 프레임 -> 행렬

 as.matrix(dfm)

 






'AI > R Basic' 카테고리의 다른 글

R 기본 디버깅 (Debugging) 및 RStudio 이용  (0) 2015.10.04
R Studio 설치법 및 사용 Tip  (0) 2015.10.04
Apply 함수 (데이터 조작)  (1) 2015.10.03
R의 문자열 처리 및 비교  (0) 2015.10.03
Plyr package (데이터 조작)  (0) 2015.10.01

R에서는 주로 벡터 기반으로 데이터를 처리 한다.

벡터기반 처리는 개별 요소를 for 루프 등으로 하나씩 처리하는 방식보다 빠르게 수행될 뿐만 아니라 손쉽게 병렬화가 가능하다.

따라서 대부분의 Machine Learning이나 통계 함수들은 입력값으로 벡터를 받는다.


따라서 데이터를 벡터로 변환하고 다시 벡터데이터를 가독성 높은 데이터 프레임으로 변경하는 것을 자유 자재로 할 수 있어야한다.

앞으로 보게될 많은 R 코드들은 모두 이러한 벡터 연산들을 이용하기 때문에 벡터를 다루는 함수들을 잘 알고 있어야 한다.



Apply 함수 (데이터 조작)


벡터화된 연산과 apply함수를 이용해서 일괄 실행함으로써 계산을 간소화하고 고속화를 도모 한다.

다양한 데이터를 임의의 함수에 적용하 결과를 얻는 방법으로 apply  함수들을 이용하는 방법이 있다.

이들 함수는 벡터, 행렬, 리스트, 데이터 프레임에 적용할 함수를 명시하는 형태로서, 함수형 언어 스타일에 가깝다고 볼 수 있다.



apply 함수들의 요약


apply() 

배열 또는 행렬에 주어진 함수를 적용한 뒤 그 결과를 벡터, 배열 또는 리스트로 반환

배열 또는 행렬에 적용 가능


lapply()

벡터, 리스트 또는 표현식에 함수를 적용하여 그 결과를 리스트로 반환

결과가 리스트


sapply() 

lappy()와 유사하지만 결과를 벡터, 행렬 또는 배열로 반환

결과가 벡터, 행렬 또는 배열


tapply()

벡터에 있는 데이터를 특정 기준에 따라 그룹으로 묶은 뒤 각 그룹맏 주어진 함수를 적용하고 그 결과를 반환

여러 데이터를 함수의 인자로 적용


mapply() 

sapply의 확장된 버전으로, 여러 개의 벡터 또는 리스트를 인자로 받아 함수에 각 데이터의 첫째 요소들을 적용한 결과,

둘째 요소들을 적용한 결과, 셋째 요소들을 적용한 결과 등을 반환

여러 데이터를 함수의 인자로 적용 가능



▣ Apply 사용법


apply: 배열 또는 행렬에 함수 f를 d방향으로 적용하여 결과를 벡터, 배열 또는 리스트로 반환 한다.

apply( X, d, f)

X #배열 또는 행렬

d # 함수를 적용하는 방향, 1은 행방향, 2는 열 방향

  # c(1,2)는 행과 열 방향 모두를 의미

FUN # 적용할 함수


예제

#합 구하는 함수
> sum(1:10)
[1] 55
# 메트릭스 생성
> d <- matrix(1:9, ncol=3)
> d
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
# 각각의 행을 더해서 벡터로 반환 한다.
> apply(d,1,sum)
[1] 12 15 18
# 각각의 열을 더해서 벡터로 반환 하다.
> apply(d,2,sum) 
[1]  6 15 24


> head(iris[c(1,2,3,4)])
  Sepal.Length Sepal.Width Petal.Length Petal.Width
1          5.1         3.5          1.4         0.2
2          4.9         3.0          1.4         0.2
3          4.7         3.2          1.3         0.2
4          4.6         3.1          1.5         0.2
5          5.0         3.6          1.4         0.2
6          5.4         3.9          1.7         0.4
# 벡터 스타일의 선택
> apply(iris[c(1,2,3,4)],2,sum)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
       876.5        458.6        563.7        179.9 
# 메트릭스 스타일의 선택
> apply(iris[,1:4],2,sum)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
       876.5        458.6        563.7        179.9




▣ lapply 사용법


리스트로 반환하는 특징이 있는 apply 계열 함수이다.


lapply (X, FUN, ...#추가인자) 

반환 값은 X와 같은 길이의 리스트이다.

X는 벡터, 리스트, 표현식, 데이터 프레임을 받을 수 있다.


리스트를 다른 타입으로 변환 하는 방법 

unlist( x, recursive=FALSE, use.name=TRUE )

반환 값은 벡터이다.


do.call # 함수를 리스트로 주어진 인자에 적용하여 결과를 반환한다.

(적용할 함수, 데이터 리스트)

반환 값은 함수 호출 결과다.



# 벡터 입력을 받아서 리스트로 반환하는 코드이다.
> result <- lapply(1:3, function(x){x*2})
> result
[[1]]
[1] 2

[[2]]
[1] 4

[[3]]
[1] 6

> result[[1]]
> unlist(result) # list 구조를  벡터로 변경 한다.
[1] 2 4 6


입력을 list로 받을 수도 있다.

> x <- list(a=1:3, b=4:6)
> x
$a
[1] 1 2 3

$b
[1] 4 5 6

> lapply(x,mean)
$a
[1] 2

$b
[1] 5


# iris의 데이터 구조를 보여줌
> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa

# list로 반환됨 각각의 열들의 평균을 구한다음
> lapply(iris[,1:4],mean)
$Sepal.Length
[1] 5.843333

$Sepal.Width
[1] 3.057333

$Petal.Length
[1] 3.758

$Petal.Width
[1] 1.199333

#각 열에 대한 평균을 구하게 된다.
> colMeans(iris[,1:4])
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.199333


데이터 프레임을 처리한 결과를 리스트로 얻은 뒤 해당 리스트를 다시 데이터 프레임으로 변활할 필요가 있다. 

이 변환은 몇 단계를 거쳐서 처리해야 한다.

  • unlist()를 통해 리스트를 벡터로 변환한다.
  • matrix()를 사용해 벡터를 행렬로 변환한다.
  • as.data.frame()을 사용해 행렬을 데이터 프레임으로 변환한다.
  • names()를 사용해 리스트로부터 변수명을 얻어와 데이터 프레임의 각 컬럼에 이름을 부여한다.


iris 데이터의 각 열의 평균을 구한다음

이 결과는 list로 반환 되므로 이것을 다시 데이터 프레임으로 변경해서 출력하는 예제이다.

># 데이터 프레임으로 변겨하는 코드이다.
# matrix()로 먼저 변환 하는 것은 vector를 바로 data frame으로 변경하면 단일 열로 밖에 변경을 못하기 때문이다.
 d <- as.data.frame(matrix(unlist(lapply(iris[,1:4],mean)),ncol=4,byrow=TRUE))
> d
        V1       V2    V3       V4
1 5.843333 3.057333 3.758 1.199333
> d <- as.data.frame(matrix(unlist(lapply(iris[,1:4],mean)),ncol=4,byrow=TRUE))
> d
        V1       V2    V3       V4
1 5.843333 3.057333 3.758 1.199333
#위와 같이 이름이 자동으로 설정되므로 가독성을 위해서 이름을 변경해 준다.
> names(d) <- names(iris[,1:4])
> d
  Sepal.Length Sepal.Width Petal.Length Petal.Width
1     5.843333    3.057333        3.758    1.199333



unlist 방식의 경우 벡터로 바꾸기 때문에 데이터 타입이 서로 다를 경우 엉뚱한 값으로 바꿔버리게 된다.

> x <- list(data.frame(name="foo",value=1),data.frame(name="bar",value=2))
> x
[[1]]
  name value
1  foo     1

[[2]]
  name value
1  bar     2

> unlist(x)
 name value  name value 
    1     1     1     2 

이렇게 서로 다른 데이터로 구성된 list를 데이터 프레임으로 변경 해야한다면,

do.call() 함수를 이용 해야 한다.

> do.call(rbind,x)
  name value
1  foo     1
2  bar     2

하지만, 해당 방식은 속도면에서 문제가 발생 한다.

그래서 rbindlist()를 사용하게 된다.




▣ sapply 사용법


lapply의 사용자 친화 버전이다. 해당 함수는 리스트 대신에 
행렬과 벡터 등의 데이터 타입으로 결과를 반환하는 특징이 있는 함수 이다.

벡터 리스트 표현식 데이터 프레임등에 함수를 적용하고 그 결과를 벡터 또는 행렬로 반환한다.
sapply {
X, # 벡터, 리스트, 표현식 또는 데이터 프레임
FUN, # 적용할 함수
....., # 추가 인자, 이 인자들은 FUN에 전달된다.
}

> sapply(iris[,1:4],mean)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.199333 
> class(sapply(iris[,1:4],mean))
[1] "numeric"


sapply로 연산하고 벡터를 data frame으로 변경하는 방법이다.

> sapply(iris[,1:4],mean)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.199333 
> class(sapply(iris[,1:4],mean))
[1] "numeric"
> x <- sapply(iris[,1:4],mean)
> as.data.frame(x)
                    x
Sepal.Length 5.843333
Sepal.Width  3.057333
Petal.Length 3.758000
Petal.Width  1.199333
> as.data.frame(t(x))
  Sepal.Length Sepal.Width Petal.Length Petal.Width
1     5.843333    3.057333        3.758    1.199333


sapply를 이용해서 각 컬럼의 데이터 타입을 구할 수도 있다.

> sapply(iris,class)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
   "numeric"    "numeric"    "numeric"    "numeric"     "factor"

다음은 조건문을 이용해서 iris 데이터 집합중에서 3보다 큰지 여부를 판단하는 코드이다.

반환값은 행렬이 된다.

> y <- sapply(iris[,1:4], function(x) {x>3})
> class(y)
[1] "matrix"
> head(y)
     Sepal.Length Sepal.Width Petal.Length Petal.Width
[1,]         TRUE        TRUE        FALSE       FALSE
[2,]         TRUE       FALSE        FALSE       FALSE
[3,]         TRUE        TRUE        FALSE       FALSE
[4,]         TRUE        TRUE        FALSE       FALSE
[5,]         TRUE        TRUE        FALSE       FALSE
[6,]         TRUE        TRUE        FALSE       FALSE

주의해야할 사항은 벡터를 반환 하기 떄문에 sapply를 사용할 때는 데이터 타입을 혼합하여 처리하면 안된다.

데이터 타입을 혼합해야 할 경우에는 lapply를 사용하거나 plyr 페키지에 있는 ddply를 사용해야 한다.


▣ tapply() 사용법


tapply{

X 벡터

Index 데이터를 그룹으로 묶을 색인, 팩터를 지정해야 하며 팩터가 아닌 타입이 지정되면 팩터로 형 변환된다.

FUN 각 그룹마다 적용 할 함수

...., 추가 인자. 이 인자들은 FUN에 전달된다.

}

반환 값은 배열이다.


아래의 코드는 간단한 하나의 그룹 1에 대한 합을 나타낸다.

# rep는 1을 10번 반복하라는 뜻이다. 이렇게해서 1:10 까지의 벡터에 factor 데이터 1을 모두 맵핑해서 하나의 그룹으로 만들어 준다.
> rep(1,10)
 [1] 1 1 1 1 1 1 1 1 1 1
> tapply(1:10, rep(1,10),sum)
 1 
55


# 홀수 짝수를 나누어서 연산하는 것이다.
tapply(1:10,1:10%%2 ==1,sum)
FALSE  TRUE 
   30    25 


조금더 복잡한 연산으로 iris 데이터들중에서 length의 평균을 구하는데 그것을 specie에 따라서 구하는 것이다.

> head(iris)
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          4.9         3.0          1.4         0.2  setosa
3          4.7         3.2          1.3         0.2  setosa
4          4.6         3.1          1.5         0.2  setosa
5          5.0         3.6          1.4         0.2  setosa
6          5.4         3.9          1.7         0.4  setosa
> tapply(iris$Sepal.Length, iris$Species, mean)
    setosa versicolor  virginica 
     5.006      5.936      6.588 


이제 더 복잡한 예제를 살펴보자. 아래의 예제는 추후에 클러스터링 알고리즘을 적용한 다음에 (k-mean clustering)

같은 cluster에 속한 데이터들의 x와 y 좌표의 각가그이 평균을 구하는 용도로 사용 될 수 있다.

#데이터를 아래와 같이 생성 한다.
> m <- matrix(1:8, ncol=2, dimnames=list(c("spring","summer","fall","winter"),c("male","female")))
> m
       male female
spring    1      5
summer    2      6
fall      3      7
winter    4      8

위와 같이 데이터 구조를 생성 했을 때

이때 분기별 과 성별 셀의 합을 구해보자.


상반기 봄, 여름에 대한 남성의 셀 합은 1+2로 구할 수 있다. 그리고 여성의 합은 5+6이다.

하반기 가을, 겨울의 남성의 셀 합은 3+4이고 여성의 합은 7+8이다.


Index를 설정하기 위해서 (n,m)에서 n을 먼저 나열한 뒤 m 값을 나열한다. 

즉, 그룹 (n1, m1), (n2, m2)는 list( c(n1,n2), c(m1,m2))로 표현된다.

> tapply(m, list(c(1,1,2,2,1,1,2,2),c(1,1,1,1,2,2,2,2)),sum)
  1  2
1 3 11
2 7 15


▣ mapply() 사용법


sapply와 유사하지만 다수의 인자를 함수에 넘긴다는 점에서 차이가 존재 한다.

sapply 처럼 행렬과 벡터반환 하게 된다.


1) 여러개의 인자를 보내야 하는 경우에 사용 한다.

2) 어떤 함수에 여러개의 벡터를 입력으로 주고 싶은 경우

a,b를 받아서 처리하는 함수가 있을때

c(....), c(....) 이런식으로 2개의 벡터를 입력으로 보내서 연속적인 처리를 할 수 있다.



mapply: 함수에 리스트 또는 벡터로 주어진 인자를 적용한 결과를 반환 한다.

Fun #실행할 함수

... # 적용할 인자



rnorm의 경우 n개의 데이터를 mean에 대해서 sd인 정규 분포를 생성 한다.


그냥 rnorm을 세번 호출하면 되지만 편의를 위해서 mapply를 이용했다.

세개인자를 rnorm함수로 전달해서 연살을 수행하게 된다.

> mapply(rnorm, c(1,2,3),c(0,10,100),c(1,1,1))
[[1]]
[1] 0.5746612

[[2]]
[1] 10.026820  9.574186

[[3]]
[1]  99.53101  98.92185 101.26264

#iris 데이터의 경우 아래와 같이 수행 된다.
> mapply(mean,iris[,1:4])
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.199333 

> sapply(iris[,1:4],mean)
Sepal.Length  Sepal.Width Petal.Length  Petal.Width 
    5.843333     3.057333     3.758000     1.199333 

> lapply(iris[,1:4],mean)
$Sepal.Length
[1] 5.843333

$Sepal.Width
[1] 3.057333

$Petal.Length
[1] 3.758

$Petal.Width
[1] 1.199333




+ Recent posts