Search

레이블이 Analysis인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Analysis인 게시물을 표시합니다. 모든 게시물 표시

2018년 12월 23일 일요일

[R] console창의 print 길이 조절하기

#1. 들어가기

print를 통해 한 번에 많은 양의 데이터를 출력하면 아래와 같이

reached getOption("max.print") -- omitted 999 rows

라고 뜨면서 최대 인쇄 길이를 조정하라고 한다.
이 때, 더 많은 양을 출력하기 위해서는 아래와 같이 설정한다.


#2. 코드

# console 프린트 길이
options(max.print=1000000)

[R] 출력되는 소수점 자리수 설정하기

#1. 들어가기

분석 시, 소수점 자리가 너무 길거나 짧게되면 데이터를 확인하는데 불편함이 있을 수 있다.
아래의 코드로 모든 소수에 대해 출력되는 자리 수를 한번에 설정할 수 있다.
(scipen 뒤의 숫자를 변경하면 된다.)


#2. 코드

# 소수자릿수 표현
options(scipen = 4)

[R] string 값을 factor로 자동변경 하지 않기

#1. 들어가기

R에서 분석을 하다보면 file을 통해 데이터를 불러오는 경우가 많다.
이 때, 데이터에 string값이 있을 경우 자동으로 factor로 만들어주기 때문에 read속도가 느리기도 하고, 때에 따라서는 factor를 다시 character로 변경해야하는 불편함이 있다.
그래서 아래의 코드로 아예 처음부터 factor방식으로 변경하지 않게 만들 수도 있다.


#2. 코드

# string을 factor로 자동 변경하지 않음
options(stringsAsFactors = FALSE)

2018년 3월 8일 목요일

[Analysis] [R] (offline R 분석 시) CRAN Repository에 있는 모든 패키지 설치하기

일을 하다 보면 인터넷 연결이 되어 있지 않은 환경에서 R 분석 작업을 진행해야 하는 경우가 있다.
다른 환경도 인터넷 연결 없이 진행하기 힘들겠지만, R은 특히 패키지 의존성이 강하기 때문에 offline으로 작업할 경우 매번 필요한 패키지를 설치하기 어려워 분석을 지속적으로 진행하기 어려운 경우가 생긴다.
보통 필수적으로 필요로 하는 패키지 위주로 개별적으로 다운을 받아서 옮기는 작업을 하는데, 이러다 보면 일부 dependency 패키지가 설치되어 있지 않아서 다시 다운받고 옮기는 작업을 반복하게 된다.
중간중간 패키지를 매번 새로 받아 옮기는 것보다 CRAN Repository에 있는 모든 패키지를 미리 다운받아서 설치하는 것이 편리한데, 이번 블로그에 그 내용을 담아보고자 한다.


1. CRAN Repository download

wget ftp://cran.r-project.org/pub/R/src/contrib/*.tar.gz

* 유효한 ftp 주소인지 확인해 보려면 .. (thanks to @김진혁)

ftp ftp://cran.r-project.org/pub/R/src/contrib/


2. Install on R

2-1. 압축 풀기

tar -xzvf /다운로드된경로 -C /압축풀경로


2-2. 압축푼경로로 R에서 라이브러리 경로지정

[Anaysis] [R] 현재 라이브러리 경로 확인 및 패키지 설치



2-3. 특정 패키지 설치여부 확인
(정말 필수적으로 필요한 패키지에 대해 샘플링하여 설치여부 확인)

pk.list <- c("RJDBC", "data.table", "dplyr", "tidyr", "Amelia" , "lubridate", "xlsx",
             "sparklyr", "rsparkling", "h2o", "visNetwork", "igraph", "ggplot2")
pk.installed <- installed.packages()[, "Package"]
setdiff(pk.list, pk.installed)
character(0)  # 모든 필수 라이브러리 설치 완료


* 대부분의 경우 이런 방식으로 리눅스 서버에서 설치 가능하지만 만약 설치가 안되는 경우가 있다면 다음 방법 참조

download.path <- "압축푼경로"
pk.list <- list.files(download.path)
pk.list <- setdiff(pk.list, installed.packages()[, "Package"])
for(i in pk.list){
  pk.path <- file.path(download.path, i)
  install.packages(pk.path, repos = NULL, type="source")
}

다만, 이 방법은 dependency 에 따라서 설치가 안되는 패키지가 있을 수 있으니, 여러번 반복수행하여야 한다.



2018년 3월 4일 일요일

[Analysis] [R] Text Analysis 맛보기(2) - Word Counter 만들고, 트랜드 살펴보기

#1. 들어가기
지난 시간에는 Google에서 단순하게 뉴스를 수집해주는 프로그램을 만들었다.
이번에는 그 후속편으로, 모아놓은 뉴스들을 활용해 그 안에서 의미를 파악하는 방법을 다루어보고자 한다.


#2. 워드 카운터 만들어보기
이번 화에서 사용할 데이터는 전 시간('Google News Crawler 만들기'편 참조)의 최종 결과물인 'result'라는 변수에 저장된 data.frame으로, 그 중 기사내용(article) 컬럼에 있는 단어들을 추출해 작업해보고자 한다. 아래는 그 코드이다.

#########################################
# WORD COUNTER - v1.0
# - martinpark
# - ruserive@gmail.com
#########################################

# load library and user function ------------------------------------------
# install.packages(c("KoNLP","plyr","dplyr","qdap","plotly"))
library(KoNLP)
library(plyr)
library(dplyr)
library(qdap)
library(plotly)


# word count part ---------------------------------------------------------
# 기사 내용 추출해서 단어 카운트하기 (전체 기사)
txt        <- result$article
txt        <- gsub(keyWord," ",gsub("“|”|\"|`|'|\\(|\\)|<|>|\\[|\\]|·|…|△|▷| \\(중략\\)..."," ",txt))
txt        <- unlist(sapply(txt, extractNoun, USE.NAMES = F))
txt        <- base::Filter(function(x){nchar(x)>1},txt)
word_count <- freq_terms(txt,top=10)

# 완성 데이터 확인
print(word_count)

먼저, '쇼트트랙'이라는 단어로 검색한 뉴스의 기사내용들을 모아 단어만 추출하고, 다시 그 단어들 중에 사용된 순서가 높은 순서대로 10개만 모아보면 아래와 같다.



결과에서 m이 1위에 뽑힌 이유는, 간단하게 이용해보려고 사용한 KoNLP 라이브러리의 단어사전에 숫자들이 제외되었기 때문이다. 예를 들어, 500m, 1000m, 3000m 등등의 텍스트에서 숫자는 다 없어지고 m만 남았다.


#3. 시간의 흐름에 따른 단어 사용량 파악해보기
간단하게 위 방법을 사용해 단어와 그 사용 빈도만 파악해 보아도 최근 뉴스에서 어떤 내용을 다루는지 충분히 짐작할 수 있을 것이다. 하지만, 단순하게 단어에 대한 사용량만 놓고 본다면 무엇인가 새로운 인사이트를 찾고자 노력할 때, 정보가 너무 뭉개졌다는 느낌을 받을 것이다.

그래서, 아래의 코드를 추가해 분석을 조금 더 진행해봤다. 이번에는 3위에 랭크된 '금메달'이라는 단어를 뽑아, 시간의 흐름에 따른 카운트를 다시 파악해봤다.

# time trend --------------------------------------------------------------
# 기사 내용 추출해서 시간별로 단어의 사용량 추이 확인하기
df           <- result[,c("article","time")]
df$article   <- gsub(keyWord," ",gsub("“|”|\"|`|'|\\(|\\)|<|>|\\[|\\]|·|…|△|▷| \\(중략\\)..."," ",df$article))

# 날짜별
txt2         <- sapply(df$article, extractNoun, USE.NAMES = F)
txt2         <- lapply(txt2, function(x) x[nchar(x)>1])
names(txt2)  <- df$time
txt2_result  <- data.frame(date = rep(names(txt2), lapply(txt2, length))
                           ,word = unlist(txt2)
                           ,row.names = NULL
                           ,stringsAsFactors = FALSE)

# 빈도 높은 단어(혹은 관심 단어) 하나 선택하기
word_filter  <- "금메달"

## word plot(1) - 0불포함(쇼트트랙 관련 기사에 금메달이라는 단어가 없던 날은 아예 그래프에서 제외)
tmpPlot      <- txt2_result[txt2_result$word == word_filter,]$date

# 결과 그래프(1) 확인
plot(table(tmpPlot),"l")


## word plot(2) - 0포함(쇼트트랙 관련 기사에 금메달이라는 단어가 없던 날도 그래프에 포함)
tmpPlot2      <- left_join(data.frame(tmpPlot=unique(txt2_result$date),stringsAsFactors=FALSE)
                           ,as.data.frame(table(tmpPlot),stringsAsFactors=FALSE))
tmpPlot2$Freq[is.na(tmpPlot2$Freq)] <- 0
tmpPlot2      <- tmpPlot2[order(tmpPlot2$tmp),]
tmpPlot2$Date <- gsub("-","/",substr(tmpPlot2$tmpPlot,6,10))

# 결과 그래프(2) 확인
plot_ly(tmpPlot2, x = ~Date, y = ~Freq, type = 'scatter', mode = 'lines')

위 코드를 그대로 붙여넣어 수행하면 얻어지는 그래프를 1번, 2번 순서대로 캡쳐해 보았다.
(간단하게 보여주기 위함이니.. 선이나 글씨 크기, 배치 등등은 스스로 설정하자.)




이렇게 그래프를 그리고 나면, 우리는 여기에서 새로운 정보를 얻을 수 있게 되었다.
나는 분명 신문 기사를 읽지도 않았고 쇼트트랙도 잘 모르지만, 쇼트트랙 기사 중 금메달이라는 카운트가 2/10, 2/17/ 2/20, 2/22에 높다는 사실을 알 수 있다. (캡쳐해놓은 이미지가 인터넷 상에선 잘 안보이지만.. 코드를 돌려보면 나옵니다..)
그래서, 해당 날짜들에 어떤 사건이 있는지 역추적 해보니 아래와 같다는 것을 알 수 있다.

2/10 - 임효준 남자 1,500m 금메달
2/17 - 최민정 여자 1,500m 금메달
2/20 - 대한민국 여자 3,000m 계주 금메달
2/22 - 금메달은 못 땄으나, 남자 500m 은,동메달, 여자 1,000m 4위와 실격처리, 남자 5,000m 계주 4위 등 아쉬운 장면들이 많이 연출되던 날.


#4. 마치며
우선은 일반 사람들에게 생소한 TA(Text Analysis) 맛보기를 해보았는데, 실제로 해보면 생각만큼 TA영역이 쉽지 않은 것임을 알 수 있을 것이다. 단어 정제도 그렇고, 의미 파악도 그렇고.. 하지만 이 분야에 재미를 느끼는 독자분들이 있다면, 한 번 씩 도전해 보고 언젠간 멋진 결과를 다시 공유해줄 수 있었으면 합니다.


2018년 2월 18일 일요일

[Analysis] [R] Text Analysis 맛보기(1) - Google News Crawler 만들기

#1. 들어가기
가끔 세상이 어떻게 돌아가는지 알아보기 위해 구글링을 할 때가 종종 있다.
그런데, 수백 수천건의 뉴스기사를 시간순으로 정렬해 일일히 눈으로 확인하는 것은 몹시 피곤한 일이다. 그래서 이번에는 필자 대신 뉴스기사를 긁어 모아서, 얼마나 많은 단어들이 사용되었는지 확인할 수 있는 아주 간단한(?) 텍스트 분석 도우미를 만들어보고자 한다.

본 시리즈는 총 2편으로 구성할 계획이며,
1편에서는 Google News Crawler를 R로 만들어 뉴스기사를 스크랩할 예정이고,
2편에서는 KoNLP 패키지를 사용해 간단하게 word count를 구현해보고자 한다.
(추가적으로, 시간이 된다면 파이썬 버전도 만들어볼 계획)

#2. 구글 뉴스 크롤러 만들어보기
구글 뉴스 크롤러를 만들기 위해 사용되는 패키지는 총 4개로, 개발자마다 다르게 사용할 수도 있다. 또한, 다른 코드가 더 맘에 든다면 얼마든지 변경할 수 있으며, 독자분들 중에 더 효율적인 라이브러리나 코드를 찾았다면 댓글 부탁드립니다.
사용할 라이브러리는 httr, xml2, stringr, lubridate인데, 가급적 인스톨 패키지를 통해 최신으로 업데이트 하는 것을 추천한다. (특히 lubridate의 경우, 하위 버전에서 동작하지 않는 타입을 확인했음)

작성한 코드는 아래와 같으며, keyWord와 numOfPost를 변경하여 가볍게 사용해볼 수 있게 만들어두었다. 또한, 맨 하단에 csv로 내려받는 코드를 넣어두었는데, 저장 위치를 변경해서 쉽게 다운로드할 수 있다.

#########################################
# GOOGLE NEWS CRAWLER - v1.0
# - martinpark
# - ruserive@gmail.com
#########################################

# load library and user function ------------------------------------------
# install.packages(c("httr","xml2","stringr","lubridate"))
library(httr)
library(xml2)
library(stringr)
library(lubridate)
unescape_html <- function(str){
  xml2::xml_text(xml2::read_html(paste0("<x>", str, "</x>")))
}

# control keyword and number of posts -------------------------------------
# 검색어
keyWord     <- "쇼트트랙"

# 검색 뉴스 수 (너무 많을 경우, 블락당할 수 있음)
numOfPost   <- 300

# google news crawler main part -------------------------------------------
# 키워드 변환
keyWordUTF8 <- URLencode(iconv(keyWord,to='utf8'))

# 크롤링 페이지 분할
startPosts    <- seq(1,numOfPost,100)
startPosts[1] <- startPosts[1] - 1
if (numOfPost%%100==0) {
  endPosts      <- rep(100,numOfPost/100)
} else {
  endPosts      <- c(rep(100,floor(numOfPost/100)),numOfPost%%100)
}

# 결과셋 생성
result      <- data.frame(stringsAsFactors=FALSE)

for (i in seq(length(startPosts))) {
  # 뉴스 가져오기
  url         <- paste0("https://www.google.co.kr/search?hl=ko&q=",keyWordUTF8,"&tbm=nws&start=",startPosts[i],"&num=",endPosts[i])
  doc         <- content(GET(url), "text")
  # doc         <- readLines(url,warn=FALSE)
  doc_table   <- str_split(doc,"<table><tr>")
  
  for(p in seq(endPosts[i])+1) {
    # 뉴스 정제
    doc_tab     <- str_split(doc_table[[1]][p],"</div>")
    doc_tab2    <- str_split(doc_tab[[1]][1],"</a></h3>")
    
    # 뉴스 제목
    title       <- unescape_html(doc_tab2[[1]][1])
    
    # 뉴스 기사
    article     <- unescape_html(gsub("&nbsp;..."," (중략)...",doc_tab[[1]][2]))
    
    # 뉴스 제공업체
    supplier    <- str_split(unescape_html(doc_tab2[[1]][2])," - ")[[1]][1]
    
    # 뉴스 URL
    news_url    <- URLdecode(str_sub(doc_tab2[[1]][1]
                                     ,str_locate(doc_tab2[[1]][1],"\"/url")[2]+4
                                     ,str_locate(doc_tab2[[1]][1],"&")[1]-1))
    
    # 뉴스 게시 시간
    tmp_time    <- str_split(unescape_html(doc_tab2[[1]][2])," - ")[[1]][2]
    if(length(grep(" 전",tmp_time))==0){
      post_time <- as_date(tmp_time)
    } else {
      post_time <- lubridate::ymd_hms(Sys.time())
      num       <- as.integer(gsub("[^0-9]","",tmp_time))
      unit      <- gsub("([0-9]*)| 전","",tmp_time)
      if(unit=="일"){
        lubridate::day(post_time) <- lubridate::day(post_time) - num
      } else if(unit=="시간"){
        lubridate::hour(post_time) <- lubridate::hour(post_time) - num
      } else if(unit=="분"){
        lubridate::minute(post_time) <- lubridate::minute(post_time) - num
      } else if(unit=="초"){
        lubridate::second(post_time) <- lubridate::second(post_time) - num
      }
      post_time <- as_date(post_time)
    }
    
    # 데이터프레임화
    res         <- data.frame(keyword=keyWord
                              ,title=title
                              ,article=article
                              ,supplier=supplier
                              ,url=news_url
                              ,time=post_time
                              ,stringsAsFactors=FALSE)
    
    result      <- rbind(result, res)
  }
  print(paste0("Done..! (",nrow(result),"/",numOfPost,")"))

  # 빠르게 자주 사용하면 블락당함..
  Sys.sleep(3)
}

# 완성 데이터 확인
# View(result)

# csv 추출
write.csv(result, file.path("C:\\Users\\Martin\\Desktop\\google_news.csv"),row.names=FALSE,fileEncoding="CP949")

#3. 크롤링 결과 확인
더 필요한 정보가 있다면 구조를 변경하여 추가해도 되지만, 우선은 간단하게 이 정도만 크롤링 해보는 것으로 이번 장을 마칩니다.



2016년 1월 24일 일요일

[Analysis] [R] 훈련데이터 및 테스트데이터 샘플링하기

* sampleBy()를 활용해 훈련데이터 및 테스트데이터 샘플링하기

 
-모델의 정확성을 잘 평가하려면 훈련데이터와 테스트데이터로 분리하여 학습해야 한다.
-데이터에서 샘플링 할 때, 훈련 데이터와 테스트 데이터에 데이터의 종류가 균일하게 분리되어야 한다.
-예를 들어 iris데이터를 분리할 때, 훈련 데이터에는 setosa만 들어 있고, 테스트 데이터에는 vericolorvirginica만 들어 있다면 제대로 된 모델의 평가가 이루어 질 수 없다.
-base::sample() 함수는 무작위 샘플링이기 때문에, 특정 종류별로 데이터의 수를 균일하게 분리하려면 doBy패키지의 sampleBy()함수를 활용하는 것이 좋다.
 
* iris데이터의 Species별로 10% 데이터를 추출하려면,

1. base::sample()을 사용했을 때,
iris[sample(NROW(iris),NROW(iris)*0.1),]














- 샘플링 된 15행의 데이터 중, setosa 종류만 8개가 샘플링 된 것을 볼 수 있음(불균일)

2. doBy::sampleBy()를 사용했을 때,
sampleBy(~Species, frac=0.1, data=iris)











-각 종류별로 5개씩 균일하게 샘플링 된 것을 볼 수 있음


[참고- R을 이용한 데이터 처리&분석 실무]

2015년 12월 18일 금요일

[Anaysis] [R] 현재 라이브러리 경로 확인 및 패키지 설치


1 .libPaths() 

   * 간혹 현재 라이브러리 경로를 모르거나 알아야 할 경우가 있다.
     이 경우에 .libPaths() 명령어를 활용하면 된다.

.libPaths()


# example
.libPaths("/User/GGAAEN_MAC/Documents/ggaaen/library")
> .libPaths("/User/GGAAEN_MAC/Documents/ggaaen/library")
> .libPaths()
[1] "/User/GGAAEN_MAC/Documents/ggaaen/library"
[2] "Library/Frameworks/R.framework/Versions/3.1/Resources/library"
> .
   * 라이브러리 경로를 추가 하고 싶은 경우 다음과 같이 활용하면 된다.
    .libPaths("추가할 라이브러리 경로")

   ** 이 경우에 라이브러리를 탐색할 때 우선적으로 [1]번 라이브러리 경로가 탐색되고,
     패키지를 설치 할 경우에는 [1]번 라이브러리 경로에 설치가 된다.
   ** 프로젝트별로 라이브러리 관리를 하고 싶을 경우 유용하게 활용될 수 있다.




2 install.packages()

   * 현재 R 버전에 맞는 최신 패키지를 CRAN 저장소에서 다운받아 설치하는 방법이다.
     이 경우 의존적인 패키지가 모두 자동으로 설치되는 장점이 있다.


   * 만약 CRAN 저장소에서 관리하지 않는 패키지를 설치하고 싶거나, 하위 버전의 패키지를 다운받아 설치해야 할 경우 다음과 같이 활용하면 된다.

   ** 로컬에 저장되어 있는 패키지를 설치할 경우
      install.packages("파일 경로", repos = NULL, type="source")

# example
> install.packages("/Users/GGAAEN_MAC/Downloads/plyr_1.8.2.tar", repos = NULL, type = "source")


   ** 외부 저장소에 있는 패키지를 설치할 경우
      (출처: http://stackoverflow.com/questions/1474081/how-do-i-install-an-r-package-from-source)
      install.packages("패키지명", repos = "저장소 경로", type="source")

# example
> install.packages("RJSONIO", repos = "http://www.omegahat.org/R", type="source")





3. R CMD INSTALL

   * 커멘드 라인에서 패키지를 설치하는 방법이다.
     R CMD INSTALL 파일경로

# example
[GGAAEN_MAC:~ ]$ R CMD INSTALL plyr_1.8.2.tar




 (주의)
로컬에 저장되어 있는 패키지를 설치하는 경우와 R CMD INSTALL 로 설치를 진행할 경우 의존적인 패키지는 설치가 되지 않으므로 의존적인 패키지가 모두 설치 된 이후 본 패키지를 설치해야 설치가 정상적으로 완료된다.