IT/후기2016.08.16 15:09

Pycon 2016 정리


작년에 일정에 쫓겨 못갔지만 이번 파이선은 아주 천재일우의 기회로 다녀오게 됨. 그것도 3일간 풀로 말이다. 물론 기대가 너무 커서 실망도 크지만 얻은것도 많았다. 대부분 ML 주제가 거의 차지한 거같았다. 다른 세션은 많이 비우는 경우도 생기고. 데이터 분석이 대세인가 싶다. 마지막 날은 튜토리얼 하는 날인데 가서 실제로 Django가지고 간단한 웹서비스도 만들었고 이를 cloud에 배포까지 해보는 실습을 해보면서 장고걸스 / django를 알아보는 좋은 기회도 있었다. 


아래는 내가 우선 놓친(다른 것을 듣느라) 세션들이다. 나중에 유투브가 올라오면 영상까지 볼 만한 것들이다.

뉴스를 재미있게 만드는 방법; 뉴스잼 링크

Django로 쇼핑몰 만들자 링크

Basic Statistics with Python 링크

TOROS: Python Framework for Recommender System 링크

파이썬으로 기초 산수 풀어보기 (이것은 튜토리얼이므로 나중에 업데이트할 예정)

Python으로 IoT, 인지(Cognitive), 머신러닝 삼종세트 활용하기 링크

Django vs Flask, 까봅시다! 링크

검색 로그 시스템 with Python 링크

Decision making with Genetic Algorithms using DEAP 링크

파이썬 데이터 분석 3종 세트 - statsmodels, scikit-learn, theano 링크  


나중에 들은것은 다시 강의 보고 한번 내용 요약해서 올릴 예정.


저작자 표시
신고

'IT > 후기' 카테고리의 다른 글

PyconKR 2016 정리  (0) 2016.08.16
Polyglot Programming  (0) 2015.03.13
2013 JCO 후기  (0) 2013.02.23
Posted by 억사마

파이선 컨을 앞두고 파이선 재미난 코드 snippet 을 보다가 하나 따라해봄. (출처)

주피터에 있는걸 복붙. 사전에 webkit2png  설치가 필요하며 그리고 실행하는 경로에 images라는 폴더 생성을 해야한다.



import requests # http 
import bs4  # beautiful soup
import re # reqular expression
import subprocess # capture screen
import json  #json util
import os # os util 사용하기 위
In [39]:
# Requests
BASE_URL_SDS = "http://search.daum.net/search?nil_suggest=btn&w=news&DA=SBC&cluster=y&q=%EC%82%BC%EC%84%B1sds"
data = requests.get(BASE_URL_SDS)

# row개수 확인
data = bs4.BeautifulSoup(data.text)
# 아래는 reqular expression을 이용하여 totalCount를 가져오는 예제
match = re.search("totalCount: [0-9]+", data.text)
# total Count를 가져오는 부분이며 두번째 인덱스에 숫자가들어있것지
total_count = int(match.group(0).split("totalCount: ")[1])
/Users/jouk/Workspace/python/test/images
In [50]:
# 총 페이지 개수 (페이지당 10개)
pages = total_count / 10 + 1
article_data = [] #아티클 보관할 배열 생성

# 오호라 이 문법은 정말 신기하구먼 자바랑 좀 다른건가 for in 하고 비슷하긴한데 range라는게 있구먼..
for page in range(1, pages+1):
    TARGET_URL = BASE_URL_SDS + "&p=" + str(page)
    data = requests.get(TARGET_URL)
    data = bs4.BeautifulSoup(data.text)
    articles = data.findAll("div", attrs={'class': 'cont_inner'})

    for article in articles:
        title_and_link = article.findAll("a")[0]
        title = title_and_link.text.encode('utf-8')
        link = title_and_link["href"]

        date_and_media = str(article.findAll("span", attrs={'class': 'date'})[0])
        date = date_and_media.split("\n")[1]
        media = date_and_media.split("\n")[2].split("</span> ")[1]

        article_data.append(
            {
                "title": title,
                "link": link,
                "date": date,
                "media": media,
            }
        )
        
        # 아래를 실행하기 위해서는 http://www.paulhammond.org/webkit2png/ 에서 우선 webkit2png가 필요!!
        # ScreenShot
        subprocess.call([
            "webkit2png",
            "-F",   # only create fullsize screenshot
            "--filename=temporary",
            "--dir=" + os.path.join(os.getcwd(), "images"),
            link
        ])
        # Rename Screenshot
        # webkit2png --filename=FILENAME 옵션을 사용하면 한글깨짐 문제 발생
        for filename in os.listdir("./images/"):
            if filename.startswith("temporary"):
                os.rename(
                    os.path.join(os.getcwd(), "images", filename),
                    os.path.join(os.getcwd(), "images",
                                "Screenshot_" + date + "_" + media + "_" + title.replace(" ", "_") + ".png")
                )

# Result as JSON
# 단, ensure_ascii 옵션으로 UTF-8 ( 한글로 보이도록 ) 출력한다.
with open('result.json', 'w') as outfile:
    json.dump(article_data, outfile, ensure_ascii=False)        





저작자 표시
신고
Posted by 억사마
데이터분석2016.06.10 12:07

7일차에 올린 내용에 이어서 올릴려고 하니 Tistory에서 에러를 뱉어서 별도로 빼서 올립니다. ㅜ.ㅜ




Update


네 업데이트입니다. 마저 끝내겠습니다. 


경쟁업체가 오픈하면 어떤일이 벌어질까요? 이 효과를 평과하기 위해 우리는 가게중 처음 CompetitorDistance 의 값이 NA로 되어 있다가 후에 의미있는값으로 채워지는 것을 가져옵니다.

특정 날짜가 아닌 경쟁업체의 개업 달만 알려져있다고 합니다. 그래서 우리는 효과를 보기 위해 꽤 큰 window 하다고 합니다.(100일) 

위에 볼드체로 원문에도 적혀있는데 무슨말인지 함 보죠. 147개의 가게가 이용가능한 기간동안 그들의 영역에 옮겨왔다고 합니다. 이 경쟁은 기간을 어떻게 잡느냐에 따라 달라지는 판매량에서 움픅 들어간 모습을 보여준답니다. 그래서 우리는 아래 plot에 기초한 통계에 대해서 aruge를 하지 말자고 합니다. 여튼 보는것은 유익하니까요.

# Sales before and after competition opens
train_store$DateYearmon <- as.yearmon(train_store$Date) # 소스가 길어 주석을 달자면 월로 truncate
train_store <- train_store[order(Date)] #  R을 보면서 항상 이런게 대박인것 같습니다. vectorize연산이 이리 쉽게 되죠. Date순으로 order줍니다.
timespan <- 100 # Days to collect before and after Opening of competition 

그리고  바로 함수를 만듭니다. 실제로 이 함수를 만들어서 list에 verctorize연산을 할려고 합니다. 인자로 받은 가게와 일치하는 가게들만 뽑아서 아까 truncate한 DateYerMon하고 경쟁업체 개업월을 비교하죠 그게 daysWithComp에 담기고  TTTT가다가 FFFF 로 되겠죠. 그리고 그 사이에 경쟁업체 개장월이  경계에 있을테고.  그럼 여기에서 FFF가 있어야만 해당 가게가 운영하다가 경쟁업체가 없다가 생긴걸로 판단이 되겠죠? 당근??! 그래서 any()를 써서  있다면 comOpening(경쟁업체 오픈되는 시점의  인덱스)를 구하고 그리고 timespan즉 100일이 전후로 있다고 하면  그 부분만 잘라서 리턴을 하는거죠 comOpening 시점으로 앞뒤 100일치의 데이터를 말이죠!! 그래서 코드는 다음과 같네요.

beforeAndAfterComp <- function(s) {
    x <- train_store[Store == s]
    daysWithComp <- x$CompetitionOpenSince >= x$DateYearmon
    if (any(!daysWithComp)) {
        compOpening <- head(which(!daysWithComp), 1) - 1
        if (compOpening > timespan & compOpening < (nrow(x) - timespan)) {
           x <- x[(compOpening - timespan):(compOpening + timespan), ] 
            x$Day <- 1:nrow(x)
            return(x)
        }
    }
}

자 이제 r 함수를 만들었죠. 전에도 언급했으나 모르겠으나 여튼 여기 함수를 만든건 처음인듯 . 뭐 자바스크립트랑 별반 다르지 않네요. 벡터연산이 있다는 거 말고는

그리고 뭘해야할까요? 네 이 함수를 전체 데이터에 적용해서 가게별로 뽑아서 list를 만들어볼까합니다.   바로 unique()를 써서 store를 unique하게 뽑고 바로 우리가 위에 만든 함수를 돌려서 temp라는걸 만듭니다요.  그리고 이걸 row로 붙여줍니다. 뭐시냐.. do.call은 앞의 인자가함수고 그다음 인자가 함수에 들어갈 파라메터라고 보시면 됩니다. temp가 storeId별 list로 되어있는걸  하나의 list로 만들어주고  그 row가 147개 정도의 데이터가 되는걸 볼수 있습니다.

temp <- lapply(unique(train_store[!is.na(CompetitionOpenSince)]$Store), beforeAndAfterComp)
temp <- do.call(rbind, temp)
# 147 stores first had no competition but at least 100 days before the end
# of the data set
length(unique(temp$Store))
## [1] 147

자 한번 만든걸 뿌려보죠!


ggplot(temp[Sales != 0], aes(x = Day, y = Sales)) + 
    geom_smooth() + 
    ggtitle(paste("Competition opening around day", timespan))
## geom_smooth: method="auto" and size of largest group is >=1000, so using gam with formula: y ~ s(x, bs = "cs"). Use 'method = x' to change the smoothing method.


확실히 전후로 매출에 변화가 급감하였다가  다시 회복하는 기조를 보이네요..


그리고 마지막입니다. 드디어.. 후화 vote를 제일 많이 받은 녀석이기도 해서 그런지 길이도 어마어마하네요. 제가 본 exploratory analysis 중에 가장 length가 깁니다...

여튼 끝낼게요. 다른 plot을 가져옵니다. Seaonal plot(spsrini)이라고 합 대신에 missing value나 closed store 대신하여 더 값을 잘표현할수 있는 평균값으로 보여주는 plot이라고 합니다.

판매량 평균값으로 계절 추이를 볼수 있는거 같습니다. 

temp <- train
temp$year <- format(temp$Date, "%Y")
temp$month <- format(temp$Date, "%m")
temp[, StoreMean := mean(Sales), by = Store]
temp <- temp[, .(MonthlySalesMean = mean(Sales / (StoreMean)) * 100), 
             by = .(year, month)]
temp <- as.data.frame(temp)
SalesTS <- ts(temp$MonthlySalesMean, start=2013, frequency=12)
col = rainbow(3)
seasonplot(SalesTS, col=col, year.labels.left = TRUE, pch=19, las=1)



결론


우선 몇차례 올리진 않았지만 본 script중에 가장 잘 정리가 된 kaggle script인것 같습니다. 저도 인사이트도 얻고 지금 계획 중인 아이디어 하나에 실제 접목도 하고 싶은 생각이 드네요. 그럼 토요일이나 일요일쯤.. 뭐 Google calendar의 setting된 goal이 알려주는데로 또 글을 올리겠지만 여튼 수고하세요!!










저작자 표시
신고

'데이터분석' 카테고리의 다른 글

킥오프용 문서입니다  (0) 2017.04.24
Kaggler's Day #9  (0) 2017.01.12
Kaggler's Day #8  (0) 2016.06.10
Kaggler's Day #7  (0) 2016.06.08
Kaggler's Day #6  (0) 2016.05.31
Kaggler's Day #5  (0) 2016.05.27
Posted by 억사마