'분류 전체보기'에 해당되는 글 40건

  1. 2016.06.08 Kaggler's Day #7
  2. 2016.05.31 Kaggler's Day #6
  3. 2016.05.27 Kaggler's Day #5
  4. 2016.05.26 Kaggler's Day #4
  5. 2016.05.16 Kaggler's Day #3
  6. 2016.05.13 Kaggler's Day #2
  7. 2016.05.12 Kaggler's Day #1
  8. 2015.05.06 Windows 특정폴더 하위 모든 파일 대상 특정문자열 변환
  9. 2015.03.13 Polyglot Programming
  10. 2015.03.03 PowerShell 익숙해지기.
데이터분석2016. 6. 8. 17:33

7일차네요!!!

저번의 Rossman 가게 마케팅 분석 3번째로 이어서 진행을 하는군요 이번 차수에서는 끝을 봐야 또 새로운 스크립트를 맛볼텐데.. 


저번까지 박스플롯으로 학교 휴일이냐 아니냐에 따라서 Rossman 가게들의 판매 실적을 보았구요.

이번에는 이어서 ggplot으로 Sales & Customers가 0 이 아닌 train 데이터를 가지고  scatter plot을 그려보겠습니다.


ggplot(train[train$Sales != 0 & train$Customers != 0],
       aes(x = log(Customers), y = log(Sales))) + 
    geom_point(alpha = 0.2) + geom_smooth()
## 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.

당연한 얘기지만 역시 Customers가 많아야 Sales가 많다는 건 당연한건가보네요. 마치 y=x같은 그래프와 유사한 모습을 보여주네요. 상관분석을 했는데 이렇게 이쁘게 나오면 참 기분이 좋을텐데 여튼 넘어가겟습니다.


이번에는 Promo  행사여부에 따른 판매량 추이를 보죠

ggplot(train[train$Sales != 0 & train$Customers != 0],
       aes(x = factor(Promo), y = Sales)) + 
    geom_jitter(alpha = 0.1) +
    geom_boxplot(color = "yellow", outlier.colour = NA, fill = NA)


그릐고 바로 Customers는 얼마나 끌어들이나도 같이 보죠  -> 바로 전 boxplot과 비교를 할 목적인줄 알았는데 한단계 더 나가네요.. 위의 scatter plot 대신에 box plot으로 Cutomers를 카운트해보네요.


ggplot(train[train$Sales != 0 & train$Customers != 0],
       aes(x = factor(Promo), y = Customers)) + 
    geom_jitter(alpha = 0.1) +
    geom_boxplot(color = "yellow", outlier.colour = NA, fill = NA)


절대적이진 않지만 학교휴무여부보다 프로모션여부가 확실히 판매량 차이가 더 극명하네요  그리고 한번 더 강조합니다. Sales와 Customers가 0인것은 제외를 함으로써 biased될 가능성이 있기 때문이라고 합니다.  판매량은 고객수와 꽤 연관이 있다고 언급했고.. 그런데 여기에서 Promo가 보면 고객수의 차이가 그닥 없죠잉? 즉 뭐냐면  Promo가 결국 온 손님들이 물건을 더 사게 만드는 효과가 있지 더 끌어들이는 효과는 없다는걸 알수가 있죠. Promo의 factor 변수값이 0인 boxplot과 1의 boxplot은 상당히 overlap되니깐요.. Customers는 그닥 변화가 없지만 Sales은 꽤 차이나는걸 보고 우린 알수가 있어야 합니다. 고객별 소비금액을 봅시다!

with(train[train$Sales != 0 & train$Promo == 0], mean(Sales / Customers))
## [1] 8.941128
with(train[train$Sales != 0 & train$Promo == 1], mean(Sales / Customers))
## [1] 10.17896

이게 유로인데요 한 1유로 이상을 더 지갑에서 여는걸 볼수가 있습니다


여기에서 테이블로 가게 오픈여부와 프로모션 여부에 대한 카운팅 테이블을 봅시다.

table(ifelse(train$Sales != 0, "Sales > 0", "Sales = 0"),
      ifelse(train$Promo, "Promo", "No promo"))
##            
##             No promo  Promo
##   Sales = 0   161666  11205
##   Sales > 0   467463 376875

가게들이 문을 닫았을 때 프로모션기간인 경우가 좀 있네요 그리고 가게 문을 열었을 경우 45프로의 가게가 프로모션 진행중이구요

다음은 웃픈 얘기인데 오픈해서 손님이 있어도 판매가 없는 가게가 54곳이나 뽑히네요.

table(ifelse(train$Open == 1, "Opened", "Closed"),
      ifelse(train$Sales > 0, "Sales > 0", "Sales = 0"))
##         
##          Sales = 0 Sales > 0
##   Closed    172817         0
##   Opened        54    844338

그 54개를 자세히 보죠....


# That tends to happen on consecutive days. Some stores even had customers
# (who bought nothing?)
train[Open == 1 & Sales == 0]
##     Store DayOfWeek       Date Sales Customers Open Promo StateHoliday
##  1:   762         4 2013-01-17     0         0    1     0            0
##  2:   232         4 2013-01-24     0         0    1     1            0
##  3:   339         3 2013-01-30     0         0    1     0            0
##  4:   339         4 2013-01-31     0         0    1     0            0
##  5:   259         4 2013-02-07     0         0    1     1            0
##  6:   353         6 2013-03-16     0         0    1     0            0
##  7:   948         4 2013-04-25     0         5    1     1            0
##  8:   589         1 2013-04-29     0         0    1     1            0
##  9:   364         2 2013-05-07     0         0    1     0            0
## 10:   364         3 2013-05-08     0         0    1     0            0
## 11:   681         5 2013-05-10     0         0    1     0            0
## 12:   700         3 2013-06-05     0         0    1     1            0
## 13:   665         5 2013-06-28     0         0    1     0            0
## 14:   665         6 2013-06-29     0         0    1     0            0
## 15:  1039         2 2013-07-09     0         0    1     0            0
## 16:  1039         3 2013-07-10     0         0    1     0            0
## 17:   927         4 2013-08-08     0         0    1     0            0
## 18:   391         3 2013-08-28     0         0    1     1            0
## 19:   663         1 2013-09-02     0         0    1     0            0
## 20:   983         5 2014-01-17     0         0    1     0            0
## 21:   983         6 2014-01-18     0         0    1     0            0
## 22:   623         5 2014-01-24     0         0    1     1            0
## 23:   623         6 2014-01-25     0         0    1     0            0
## 24:    25         3 2014-02-12     0         0    1     0            0
## 25:    25         4 2014-02-13     0         0    1     0            0
## 26:   327         3 2014-03-12     0         0    1     0            0
## 27:   986         2 2014-03-18     0         0    1     1            0
## 28:   850         6 2014-03-29     0         0    1     0            0
## 29:   661         5 2014-04-04     0         0    1     1            0
## 30:  1100         2 2014-04-29     0         3    1     1            0
## 31:  1100         3 2014-04-30     0         0    1     1            0
## 32:  1017         3 2014-06-04     0         0    1     1            0
## 33:  1017         4 2014-06-05     0         0    1     1            0
## 34:    57         2 2014-07-01     0         0    1     1            0
## 35:   925         4 2014-07-03     0         0    1     1            0
## 36:   102         6 2014-07-12     0         0    1     0            0
## 37:   882         3 2014-07-23     0         0    1     0            0
## 38:   887         3 2014-07-23     0         0    1     0            0
## 39:   102         4 2014-07-24     0         0    1     0            0
## 40:   238         4 2014-07-24     0         0    1     0            0
## 41:   303         4 2014-07-24     0         0    1     0            0
## 42:   387         4 2014-07-24     0         0    1     0            0
## 43:    28         2 2014-09-02     0         0    1     1            0
## 44:    28         3 2014-09-03     0         0    1     1            0
## 45:    28         4 2014-09-04     0         0    1     1            0
## 46:   548         5 2014-09-05     0         0    1     1            0
## 47:   835         3 2014-09-10     0         0    1     0            0
## 48:   227         4 2014-09-11     0         0    1     0            0
## 49:   835         4 2014-09-11     0         0    1     0            0
## 50:   357         1 2014-09-22     0         0    1     0            0
## 51:   708         3 2014-10-01     0         0    1     1            0
## 52:   699         4 2015-02-05     0         0    1     1            0
## 53:   674         4 2015-03-26     0         0    1     0            0
## 54:   971         5 2015-05-15     0         0    1     0            0
##     Store DayOfWeek       Date Sales Customers Open Promo StateHoliday
##     SchoolHoliday
##  1:             0
##  2:             0
##  3:             0
##  4:             0
##  5:             0
##  6:             0
##  7:             0
##  8:             0
##  9:             0
## 10:             0
## 11:             0
## 12:             0
## 13:             0
## 14:             0
## 15:             0
## 16:             0
## 17:             1
## 18:             1
## 19:             1
## 20:             0
## 21:             0
## 22:             0
## 23:             0
## 24:             0
## 25:             0
## 26:             0
## 27:             0
## 28:             0
## 29:             0
## 30:             0
## 31:             0
## 32:             0
## 33:             0
## 34:             0
## 35:             0
## 36:             0
## 37:             1
## 38:             0
## 39:             1
## 40:             1
## 41:             1
## 42:             1
## 43:             1
## 44:             1
## 45:             0
## 46:             1
## 47:             0
## 48:             0
## 49:             0
## 50:             0
## 51:             0
## 52:             0
## 53:             0
## 54:             1
##     SchoolHoliday

가슴 아프지만 우리는 이 가게들을 캐내서 판매부진 아니.. 판매불능의 상황을 따져봅시다...!! 우선 Store의 리스트를 가져와 sales가 0인것들이 많은 순대로 sort를 했네요. 여기에서 sort는 별로 무의미해보이고요 여튼 zeroPerStore의 가게를



zerosPerStore <- sort(tapply(train$Sales, list(train$Store), function(x) sum(x == 0)))
hist(zerosPerStore,100)

여기에서 histogramd 한참 봤습니다 ㅜ.ㅜ  Exploratory Analysis의 경우는 왔다갔다 합니다. 여튼 위에 zeroStore에서 구한 가게별 문닫는 일수에 대한 데이터를 놓고 보네요. 가게별 판매가 0인 날로 그치는 날수가 제일 많은게 160~200일 동안 장사가 안되는 날이 있네요..  자세히 들여다볼까요?


여기에서는 이 구한 zerosPerStore은 sort가 되어 있죠 default가 ascending order라 판매가 0인 날이 가장 많은 가게들 10개를 가져와봅니다.  그리고 그 가게별로 plot을 찍어보네요 Sales에 대한 ploat을 찍고 보니  특정 구간에 판매량이 0으로 몰린다는겁니다. 중간에 뻥 아니면 시작부분에 뻥

# Stores with the most zeros in their sales:
tail(zerosPerStore, 10)
## 105 339 837  25 560 674 972 349 708 103 
## 188 188 191 192 195 197 240 242 255 311
# Some stores were closed for some time, some of those were closed multiple times
plot(train[Store == 972, Sales], ylab = "Sales", xlab = "Days", main = "Store 972")

plot(train[Store == 103, Sales], ylab = "Sales", xlab = "Days", main = "Store 103")

plot(train[Store == 708, Sales], ylab = "Sales", xlab = "Days", main = "Store 708")

물론 판매량에 있어 0을 안 찍은 가게들도 있고 일요일/휴무일날 오픈해서 판매한 exceptions들도 있다고 합니다. 특히 일요일은 판매가 잘된다고 하네요.. 


ggplot(train[Store == 85], 
       aes(x = Date, y = Sales, 
           color = factor(DayOfWeek == 7), shape = factor(DayOfWeek == 7))) + 
    geom_point(size = 3) + ggtitle("Sales of store 85 (True if sunday)")

ggplot(train[Store == 262], 
       aes(x = Date, y = Sales, 
           color = factor(DayOfWeek == 7), shape = factor(DayOfWeek == 7))) + 
    geom_point(size = 3) + ggtitle("Sales of store 262 (True if sunday)")


그리고 주일별로 한번 판매량을 boxplot찍어보니!!! 일요일은 판매량의 변동성이 꽤 높네요 ㄷㄷㄷㄷ


ggplot(train[Sales != 0],
       aes(x = factor(DayOfWeek), y = Sales)) + 
    geom_jitter(alpha = 0.1) + 
    geom_boxplot(color = "yellow", outlier.colour = NA, fill = NA)


자 이제 train데이터는 그만 잠시 접어두고 주어진 데이터 셋중에 store 즉   가게 자체애 대한 정보를 받았죠. 가게 대장이라고 부를께요.

이데이터를summary()함수를 통해서 살펴보겠습니다.


summary(store)
##      Store         StoreType          Assortment       
##  Min.   :   1.0   Length:1115        Length:1115       
##  1st Qu.: 279.5   Class :character   Class :character  
##  Median : 558.0   Mode  :character   Mode  :character  
##  Mean   : 558.0                                        
##  3rd Qu.: 836.5                                        
##  Max.   :1115.0                                        
##                                                        
##  CompetitionDistance CompetitionOpenSinceMonth CompetitionOpenSinceYear
##  Min.   :   20.0     Min.   : 1.000            Min.   :1900            
##  1st Qu.:  717.5     1st Qu.: 4.000            1st Qu.:2006            
##  Median : 2325.0     Median : 8.000            Median :2010            
##  Mean   : 5404.9     Mean   : 7.225            Mean   :2009            
##  3rd Qu.: 6882.5     3rd Qu.:10.000            3rd Qu.:2013            
##  Max.   :75860.0     Max.   :12.000            Max.   :2015            
##  NA's   :3           NA's   :354               NA's   :354             
##      Promo2       Promo2SinceWeek Promo2SinceYear PromoInterval     
##  Min.   :0.0000   Min.   : 1.0    Min.   :2009    Length:1115       
##  1st Qu.:0.0000   1st Qu.:13.0    1st Qu.:2011    Class :character  
##  Median :1.0000   Median :22.0    Median :2012    Mode  :character  
##  Mean   :0.5121   Mean   :23.6    Mean   :2012                      
##  3rd Qu.:1.0000   3rd Qu.:37.0    3rd Qu.:2013                      
##  Max.   :1.0000   Max.   :50.0    Max.   :2015                      
##                   NA's   :544     NA's   :544


1115개의 가게별로 StoreType / Assortment 같은 구분이 있고 경쟁업체 위치 그리고 경쟁업체 오픈 년월과 Promotion 에대한 추가 정보가 있네요. 프로모션2는 뭐지? 흠흠..

table(store$StoreType)
## 
##   a   b   c   d 
## 602  17 148 348
table(store$Assortment)
## 
##   a   b   c 
## 593   9 513
# There is a connection between store type and type of assortment
table(data.frame(Assortment = store$Assortment, StoreType = store$StoreType))
##           StoreType
## Assortment   a   b   c   d
##          a 381   7  77 128
##          b   0   9   0   0
##          c 221   1  71 220

이렇게 구분 변수 2개는 살펴보았습니다.  넘어가죠!


hist(store$CompetitionDistance, 100)

경쟁업체거리는 있다면 뭐 가까운데 제일 많이 있다라는거죠 거리가 멀수록 경쟁업체가 있어도 없다고 체크하겠죠 뭐 정보관리할때 말이죠..


뭐 이건 년월을 "-"로 묶어서 CompetitoinOpenSince라는 값에 담았습니다. 그리고 2015년 10월 기준으로 오픈한 년수를 구해서 historgram으로 찍어봤을때 보통 20년 이내의 역사를 가지고 있는 가게가 대부분이네요.

# Convert the CompetitionOpenSince... variables to one Date variable
store$CompetitionOpenSince <- as.yearmon(paste(store$CompetitionOpenSinceYear, 
                                               store$CompetitionOpenSinceMonth, sep = "-"))
# One competitor opened 1900
hist(as.yearmon("2015-10") - store$CompetitionOpenSince, 100, 
     main = "Years since opening of nearest competition")


그다음은 promo2가 시작된 이후의 날수를 계산하네요... 이건 머여 날수를 구해서 머하자는건지....넘어가거씁니다. 아마 제가 데이터셋 설명을 다시 봐서 업데이트하든가 해야겠네요.

 Convert the Promo2Since... variables to one Date variable
# Assume that the promo starts on the first day of the week
store$Promo2Since <- as.POSIXct(paste(store$Promo2SinceYear, 
                                   store$Promo2SinceWeek, 1, sep = "-"),
                             format = "%Y-%U-%u")
hist(as.numeric(as.POSIXct("2015-10-01", format = "%Y-%m-%d") - store$Promo2Since), 
     100, main = "Days since start of promo2")


프로모션 주기구요.

table(store$PromoInterval)
## 
##                   Feb,May,Aug,Nov  Jan,Apr,Jul,Oct Mar,Jun,Sept,Dec 
##              544              130              335              106


이건 프로모션 주기별로 boxplot을 그렸는데 글쎄요 뭐 둘쑥날쑥하네요 프로모션기별마다.

# Merge store and train 
train_store <- merge(train, store, by = "Store")
ggplot(train_store[Sales != 0], aes(x = factor(PromoInterval), y = Sales)) + 
    geom_jitter(alpha = 0.1) + 
    geom_boxplot(color = "yellow", outlier.colour = NA, fill = NA)


그다음으로  store type과 assortment types을 시각분석을 통해 한번 뭔지 보자. 

그래프가 마치 지렁이같이 그려지는건 geom_smooth 때문이고 여튼 factor를 storeType과 assortment type을 넣고 돌려봤더니 뭔가 차이가 확실히 있네요. 


ggplot(train_store[Sales != 0], 
       aes(x = as.Date(Date), y = Sales, color = factor(StoreType))) + 
    geom_smooth(size = 2)
## 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.

ggplot(train_store[Customers != 0], 
       aes(x = as.Date(Date), y = Customers, color = factor(StoreType))) + 
    geom_smooth(size = 2)
## 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.

ggplot(train_store[Sales != 0], 
       aes(x = as.Date(Date), y = Sales, color = factor(Assortment))) + 
    geom_smooth(size = 2)
## 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.

ggplot(train_store[Sales != 0], 
       aes(x = as.Date(Date), y = Customers, color = factor(Assortment))) + 
    geom_smooth(size = 2)
## 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.



storetype과 assortment type을 보면 b가 우세하네요. 고객수면이나 판매량측면에서 말이죠!!

그리고 경쟁업체와의 거리는 좀 보면 직관적이지 못합니다. 여기에서 이러네요. 아마 자기 추측에는 다음 경쟁업체와의 거리가 가까운 가게의 경우는 일반적으로 도심안과 같은 이미 붐비는 지역이라 그럴거라고. 그러니 경쟁업체가 몰려있겠죠... 그래서 good bad를 가리기엔 그냥 뭐.cancel out 즉 상쇄된다는 말인듯합니다.

salesByDist <- aggregate(train_store[Sales != 0 & !is.na(CompetitionDistance)]$Sales, 
               by = list(train_store[Sales != 0 & !is.na(CompetitionDistance)]$CompetitionDistance), mean)
colnames(salesByDist) <- c("CompetitionDistance", "MeanSales")
ggplot(salesByDist, aes(x = log(CompetitionDistance), y = log(MeanSales))) + 
    geom_point() + geom_smooth()
## geom_smooth: method="auto" and size of largest group is <1000, so using loess. Use 'method = x' to change the smoothing method.




CompetitionOpenSinceYear값이 없을 경우때문인지 걍 CompetitionOpenSinceYear의 값 존재여부를 가지고 체크한거같습니다. 보시죠. 

ggplot(train_store[Sales != 0],
       aes(x = factor(!is.na(CompetitionOpenSinceYear)), y = Sales)) +
    geom_jitter(alpha = 0.1) +
    geom_boxplot(color = "yellow", outlier.colour = NA, fill = NA) +
    ggtitle("Any competition?")



별차이가 없어보이는데 우선 뭐.. Sales가 있는경우가 더 높네요. 방금 말한 그런 이유의 연장선인거같습니다.


이 다음은 아주 쪼금남았는데 시간 나면 바로 업데이트하는걸로하고. 마칩니다.

캐글도 뭔가 완전하진 않습니다. 결국 데이터 모델을 만들어내느걸 해야하는데 그런건 안다뤄지고 Exploratory Analysis 단계까지만 공개되는거 같네요.  금주와 다음달부터 빅데이터/통계스터디를 하게 되는데 심화해서 진행되는건 업데이트해서 공유를 하도록 하겠슴니다. 그럼 조만간 업데이트할게요~~

















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

Kaggler's Day #9  (0) 2017.01.12
Kaggler's Day #8  (0) 2016.06.10
Kaggler's Day #6  (0) 2016.05.31
Kaggler's Day #5  (0) 2016.05.27
Kaggler's Day #3  (0) 2016.05.16
Posted by 억사마
데이터분석2016. 5. 31. 17:23

Google Calendar에 추가한 Goal Alarm이 오질 않네요 여튼 그래서 수동으로 다시 시작합니다. 5일차때 다룬 Rossmann Store Sales 풀이 이어서 나가도록 하겠습니다.  저번에 제공 데이터를 str. summary 등의 함수를 가지고 한번 훑어보았데 train데이터만 보여줬는데 마저 test 데이터도 조회해보죠

summary(test)
##        Id            Store          DayOfWeek          Date           
##  Min.   :    1   Min.   :   1.0   Min.   :1.000   Min.   :2015-08-01  
##  1st Qu.:10273   1st Qu.: 279.8   1st Qu.:2.000   1st Qu.:2015-08-12  
##  Median :20544   Median : 553.5   Median :4.000   Median :2015-08-24  
##  Mean   :20544   Mean   : 555.9   Mean   :3.979   Mean   :2015-08-24  
##  3rd Qu.:30816   3rd Qu.: 832.2   3rd Qu.:6.000   3rd Qu.:2015-09-05  
##  Max.   :41088   Max.   :1115.0   Max.   :7.000   Max.   :2015-09-17  
##                                                                       
##       Open            Promo        StateHoliday       SchoolHoliday     
##  Min.   :0.0000   Min.   :0.0000   Length:41088       Length:41088      
##  1st Qu.:1.0000   1st Qu.:0.0000   Class :character   Class :character  
##  Median :1.0000   Median :0.0000   Mode  :character   Mode  :character  
##  Mean   :0.8543   Mean   :0.3958                                        
##  3rd Qu.:1.0000   3rd Qu.:1.0000                                        
##  Max.   :1.0000   Max.   :1.0000                                        
##  NA's   :11
test[is.na(test$Open), ] # Only store 622
##        Id Store DayOfWeek       Date Open Promo StateHoliday SchoolHoliday
##  1: 10752   622         6 2015-09-05   NA     0            0             0
##  2:  9040   622         1 2015-09-07   NA     0            0             0
##  3:  8184   622         2 2015-09-08   NA     0            0             0
##  4:  7328   622         3 2015-09-09   NA     0            0             0
##  5:  6472   622         4 2015-09-10   NA     0            0             0
##  6:  5616   622         5 2015-09-11   NA     0            0             0
##  7:  4760   622         6 2015-09-12   NA     0            0             0
##  8:  3048   622         1 2015-09-14   NA     1            0             0
##  9:  2192   622         2 2015-09-15   NA     1            0             0
## 10:  1336   622         3 2015-09-16   NA     1            0             0
## 11:   480   622         4 2015-09-17   NA     1            0             0
test$Open[test$Store == 622]
##  [1]  1  0  1  1  1  1  1  1  0  1  1  1  1  1  1  0  1  1  1  1  1  1  0
## [24]  1  1  1  1  1  1  0  1  1  1  1  1 NA  0 NA NA NA NA NA NA  0 NA NA
## [47] NA NA


여기에서 보면 위에 제가 볼드체로 표시한 부분 즉 실제 rows수를 보면 train데이터가 월등히 많네요. 1017209rows에 비해 test데이터는 턱없이 부족하고 그리고 dashboard에 issue로 올라온 것보면 622개의 데이터가 Open 컬럼이 NA로 되어있어 못쓴다라고 올라와있는데요. 하지만 이 row를 못쓰는건 아닙니다.  여기를 보면 아시다시피 Sale라는 컬럼이 닫혀있다면 0일수가 없으니 1로 간주하면 될거 같습니다. 이런걸 data munging이라고도 하는데 저희가 도메인을 파악하고 어떤 이유에서인지 알수 없거나 정리가 안된걸 직접 수정하여 trim처리를 하는 센스는 있어야 합니다.  게다가 테스트 데이터에는 Customers컬럼이 아예 빠져있는걸 알수 있습니다. 사후 데이터이기 때문이라네요 ?


여튼  그래서 아래와 같은 처리 합니다. NA인 녀석들을 싹다!!!!  1로 만들어버립시다


test[is.na(test)] <- 1

위의 문법은 test의 컬럼중 NA를 다 1로 채우는걸로 이해하면 됩니다


그다음에 다시

test[is.na(test$Open), ]
하면 결과가 0이 나올겁니다 테스트 데이터에는 Easter Day나 크리스마스 휴일가 없지만 방학은 44프로나 있네요. 하지만 그에 비해 train data의 18프로만의 방학이 있다는거 뭔가 데이터가 참 bias된것 같습니다. 이 점을 참고해야겠죠??

# Unique values per column
train[, lapply(.SD, function(x) length(unique(x)))]
##    Store DayOfWeek Date Sales Customers Open Promo StateHoliday
## 1:  1115         7  942 21734      4086    2     2            4
##    SchoolHoliday
## 1:             2
test[, lapply(.SD, function(x) length(unique(x)))]
##       Id Store DayOfWeek Date Open Promo StateHoliday SchoolHoliday
## 1: 41088   856         7   48    2     2            2             2
.SD가 여기서 궁금한 분은 이 링크를 보세요. 보면 SchoolHoliday가 test에는 2 train에는 4(부활절, 크리스마스 포함)인 걸 알수가 있네요. 그리고 Store의 각 개수가 1115, 856개 각각 인거도 보시구요~

그리고 아래는 train의 데이터들에 있는 상점들이 test의 상점들을 다 포함하는걸로 볼수 있죠 

# All test stores are also in the train data
sum(unique(test$Store) %in% unique(train$Store)) 
## [1] 856

하지만 반대의 경우는 성립하지가 않네요. 고작 259개만 커버를 하네요 나머지 1115에서 259개를 뺀건 포함을 못한다는 얘기죠?!
# 259 train stores are not in the test data
sum(!(unique(train$Store) %in% unique(test$Store))) 
## [1] 259
그리고 아래는 참 유용한 표현식입니다. factor형일 경우 전체 row에서 %를 알고 싶을때 자주 쓰죠
table(train$Open) / nrow(train) # Percent Open Train
## 
##         0         1 
## 0.1698933 0.8301067
train 데이터의 경우 열려있는경우가 83%나 되는걸 볼수가 있습니다..

table(test$Open) / nrow(test) # Percent Open Test 
## 
##         0         1 
## 0.1456386 0.8543614
테스트 데이터에서도 비슷하게 85%네요

table(train$Promo) / nrow(train) # Percent of the time promo in train
## 
##         0         1 
## 0.6184855 0.3815145
흠 train데이터에서는 프로모션을 38%나 하네요

table(test$Promo) / nrow(test) # Percent of the time promo in test
## 
##         0         1 
## 0.6041667 0.3958333
39프로 역시나 test데이터에서도 유사합니다

table(train$StateHoliday) / nrow(train) # Percent of the time holiday in train
## 
##           0           a           b           c 
## 0.969475300 0.019917244 0.006576820 0.004030637
흠 그리고 State 휴일이 아닌게 97%  당연하죠.. a,b,c는 데이터셋 설명 다시 보시길 ㅋ

table(test$StateHoliday) / nrow(test) # no b and c = no easter holiday and no christmas
## 
##           0           a 
## 0.995619159 0.004380841
핫 여기 보면 test데이터는 뭔가 bias되었네요 확실히.. bc 데이터가 없네요... 아 이게 부활절하고 크리스마스를 bc라고 지칭한건가 싶네요..

table(train$SchoolHoliday) / nrow(train) # Percent of the time school holiday in train
## 
##         0         1 
## 0.8213533 0.1786467
table(test$SchoolHoliday) / nrow(test) # Percent of the time school holiday in test
## 
##         0         1 
## 0.5565129 0.4434871
여기서도 차이가 아까 말한것처럼 발견되죠..... 이건 위에 언급했으니 넘어가겠습니다..ㅎㅎ 
데이터가 뭔가 구린건 없네요. test 데이터의 기간은 2015년 8월 1일부터 2015년 9월 17일 즉 우리 이 과제의 목표는 48일간을 예측해야하는거네요. train데이터의 기간은 2013/1/1~ 2015/7/31 한... 2.5년치의 데이터를 가지고 있다고 보면 되겠네요... 뭔가 흥미진진하죠? 그런데 테스트데이터가 적어서 좀 그렇네요?? 자 봅시다..

plot(train$Date, type = "l")

plot(test$Date, type = "l")
이런거를 plot으로 찍어서 기간을 산정해보기도하는군요 -ㅅ- min max를 plot으로 쉽게 알수 있으니 걍 쓰는가봅니다 --a

아래는 테스트의 unique  store개수가 856 였던거 기억하죠? 그 spread기간동안 데이터가 온전히 다 있나 체크하는고

# As expected all 856 stores to be predicted daily
all(table(test$Date) == 856) 
## [1] TRUE

흠 그다음은 train 데이터에서 특정 컬럼 값 분포를 봅시다. 
Sales라는 컬럼보면 대충 값들이 5000정도에서 맥스 찍고 20000이 되면서 줄어드는게 좌편향 정규분포 비슷하게 그리네요 

hist(train$Sales, 100)

다음은 historgram을 또 그리는데 "가게 문을 안닫았을때의 가게별 평균 sales"를 봅시다.  즉 Store별로  Sales를 평균 낸 데이터를 가지고 다시 히스토그램을 100분위로 나타낸것이다.
아래는 hist와 aggregate를 두개로 split해서 보시면 될듯합니다. 자세한 건 documentation 보면서 이해하는수밖에 없습니다 ^^

hist(aggregate(train[Sales != 0]$Sales, 
               by = list(train[Sales != 0]$Store), mean)$x, 100, 
     main = "Mean sales per store when store was not closed")

그다음은 custormers수의 분포를 봅시다.
hist(train$Customers, 100)



그리고 그다음은 아까 sales를 100분위로 histogram으로 나타낸것과 똑같이 고객수를 나타내보겠습니다.
hist(aggregate(train[Sales != 0]$Customers, 
               by = list(train[Sales != 0]$Store), mean)$x, 100,
     main = "Mean customers per store when store was not closed")

가게 넘버가 500~1000으로 부여된것이 실적이 좋네요 ㅎㅎ

그리고 ggplot으로 이제 뿌릴건데요  boxplot도 안에 껴서 그릴수가있습니다.

학교 휴일이냐 아니냐에 따라서 판매량을 한번 볼게요 

ggplot(train[Sales != 0], aes(x = factor(SchoolHoliday), y = Sales)) +
    geom_jitter(alpha = 0.1) +
    geom_boxplot(color = "yellow", outlier.colour = NA, fill = NA)

box plot으로는 차이가 별로 없고 판매량은 휴일이 아닌경우 가 확실히 더 많네요. 까만영역이 더 높죠?!


후배님께서 술먹자고 가자고 하네요. 후아. 오늘도 여기까지. 아직 반도 안왔네요. 이거 !!  그래도 다음 차에는 확 끝내겠습니다!


































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

Kaggler's Day #8  (0) 2016.06.10
Kaggler's Day #7  (0) 2016.06.08
Kaggler's Day #5  (0) 2016.05.27
Kaggler's Day #3  (0) 2016.05.16
Kaggler's Day #1  (0) 2016.05.12
Posted by 억사마
데이터분석2016. 5. 27. 16:56

벌써 5번째 Kaggler Day이군요 쨌든 오늘은 가장 kaggle script중에 가장 많은 관심을 받은 script 하나를 들고 왔습니다. 물론 이문제 또한 kaggle competition이 이루어진 문제구요. 


문제 설명을 하자면,, 가게, 프로모션, 그리고 경쟁자 정보를 가지고 판매량을 예측하는 겁니다. Rossman이라는 브랜드가 있나봅니다 여튼 여기서 아마 competition 문제를 의뢰한거 같구요.    이 회사가 머하는 곳이냐면 7개의 유럽 국가에 3000개의 약국을 운영하고 있는 회사입니다. 현재 Rossmann 가게 매니저들은 미리 6주되기까지 그들의 daily 판매량을 예상하는 일을 받았다고 합니다. 가게 판매는 많은 인자 즉 프로모션, 경쟁 업체, 학교, 그리고 주의 휴일, 계절, 지역특성에 등등 많은 인자에 의해 영향을 받고  수천명의 개별 매니저들과 그들의 특정 환경을 토대로 판매량을 예측하는함에 있어 결과의 정확성은 꽤 변동이 클것이라고 합니다.


그래서!! 캐글에서 Rossman은 독일에 있는 1,115개의 약국의 6개월간의 판매량을 예측하는걸 목표로 한다고 하네요? 신뢰할만한 판매 예측은 가게 매니저에게 생산성과 동기부여를 증가시킬수 있는 효율적인 직원 스케쥴을 만들수 있게 해준다고 하네요. Rossmann이 견고한 예측 모델을 만들도록 도와주면서 우리는 그들에게 고객과 그들의 팀에게 무엇이 가장 중요한지 알려주고자 합니다. 


자 문제 설명은 마쳤구요.. 여기 가보면 데이터셋을 확보할수 있습니다.


데이터셋을 보니 


손님 수, 가게 오픈여부, 주휴일, 학교휴일, 가게타입. assortment(무슨 factor중의 하나겠죠?) 그리고 경쟁업체와의 거리, 그리고 가장가까운 경쟁업체의 오픈 년월일. 프로모션, 프로모션2, 프로모션 주기가 주어져있습니다..


과연 이걸로 얻을수 있을까... 궁금하시죠? 그럼 award를 흠 그러니까 1등한분거는 공개가 안되는거 같으니.. 35k달러의 후보가 될뻔 한 소스를 한번 살펴볼까요.....!!!!



탐색전 분석(Exploratory Analysis)을 해보죠!!


사용한 라이브러리 들이 나오고요 data.table을 사용하여 속도를 높였다고 합니다. 특정 해석을 가능케 하기 위해 unmasked data가 중요하다합니다.


library(data.table)
library(zoo)
## 
## Attaching package: 'zoo'
## 
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(forecast)
## Loading required package: timeDate
## Loading required package: methods
## This is forecast 6.2

저번에는 ggplot을 보았는데 이번엔 ggplot2가 나왔습니다. 그리고 문제에서 주어지는 데이터가 이번엔 아예 test / train 으로 나뉘어져 있군요. 그리고 별도로 store라는 데이터셋이 있어서 가게 대장 정보가 별도로 잇네요.

library(ggplot2)
test <- fread("../input/test.csv")
train <- fread("../input/train.csv")
store <- fread("../input/store.csv")

아래는 입력받은 데이터셋을 간략하게 보기 좋은 함수죠~~

str(train)
## Classes 'data.table' and 'data.frame':   1017209 obs. of  9 variables:
##  $ Store        : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ DayOfWeek    : int  5 5 5 5 5 5 5 5 5 5 ...
##  $ Date         : chr  "2015-07-31" "2015-07-31" "2015-07-31" "2015-07-31" ...
##  $ Sales        : int  5263 6064 8314 13995 4822 5651 15344 8492 8565 7185 ...
##  $ Customers    : int  555 625 821 1498 559 589 1414 833 687 681 ...
##  $ Open         : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Promo        : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ StateHoliday : chr  "0" "0" "0" "0" ...
##  $ SchoolHoliday: chr  "1" "1" "1" "1" ...
##  - attr(*, ".internal.selfref")=<externalptr>
str(test)
## Classes 'data.table' and 'data.frame':   41088 obs. of  8 variables:
##  $ Id           : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Store        : int  1 3 7 8 9 10 11 12 13 14 ...
##  $ DayOfWeek    : int  4 4 4 4 4 4 4 4 4 4 ...
##  $ Date         : chr  "2015-09-17" "2015-09-17" "2015-09-17" "2015-09-17" ...
##  $ Open         : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ Promo        : int  1 1 1 1 1 1 1 1 1 1 ...
##  $ StateHoliday : chr  "0" "0" "0" "0" ...
##  $ SchoolHoliday: chr  "0" "0" "0" "0" ...
##  - attr(*, ".internal.selfref")=<externalptr>
str(store)
## Classes 'data.table' and 'data.frame':   1115 obs. of  10 variables:
##  $ Store                    : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ StoreType                : chr  "c" "a" "a" "c" ...
##  $ Assortment               : chr  "a" "a" "a" "c" ...
##  $ CompetitionDistance      : int  1270 570 14130 620 29910 310 24000 7520 2030 3160 ...
##  $ CompetitionOpenSinceMonth: int  9 11 12 9 4 12 4 10 8 9 ...
##  $ CompetitionOpenSinceYear : int  2008 2007 2006 2009 2015 2013 2013 2014 2000 2009 ...
##  $ Promo2                   : int  0 1 1 0 0 0 0 0 0 0 ...
##  $ Promo2SinceWeek          : int  NA 13 14 NA NA NA NA NA NA NA ...
##  $ Promo2SinceYear          : int  NA 2010 2011 NA NA NA NA NA NA NA ...
##  $ PromoInterval            : chr  "" "Jan,Apr,Jul,Oct" "Jan,Apr,Jul,Oct" "" ... 
##  - attr(*, ".internal.selfref")=<externalptr>
# head(train); tail(train)
# head(test); tail(test)
train[, Date := as.Date(Date)]
test[, Date := as.Date(Date)]
store
##       Store StoreType Assortment CompetitionDistance
##    1:     1         c          a                1270
##    2:     2         a          a                 570
##    3:     3         a          a               14130
##    4:     4         c          c                 620
##    5:     5         a          a               29910
##   ---                                               
## 1111:  1111         a          a                1900
## 1112:  1112         c          c                1880
## 1113:  1113         a          c                9260
## 1114:  1114         a          c                 870
## 1115:  1115         d          c                5350
##       CompetitionOpenSinceMonth CompetitionOpenSinceYear Promo2
##    1:                         9                     2008      0
##    2:                        11                     2007      1
##    3:                        12                     2006      1
##    4:                         9                     2009      0
##    5:                         4                     2015      0
##   ---                                                          
## 1111:                         6                     2014      1
## 1112:                         4                     2006      0
## 1113:                        NA                       NA      0
## 1114:                        NA                       NA      0
## 1115:                        NA                       NA      1
##       Promo2SinceWeek Promo2SinceYear    PromoInterval
##    1:              NA              NA                 
##    2:              13            2010  Jan,Apr,Jul,Oct
##    3:              14            2011  Jan,Apr,Jul,Oct
##    4:              NA              NA                 
##    5:              NA              NA                 
##   ---                                                 
## 1111:              31            2013  Jan,Apr,Jul,Oct
## 1112:              NA              NA                 
## 1113:              NA              NA                 
## 1114:              NA              NA                 
## 1115:              22            2012 Mar,Jun,Sept,Dec
train <- train[order(Date)]
test <- test[order(Date)]
summary(train)
##      Store          DayOfWeek          Date                Sales      
##  Min.   :   1.0   Min.   :1.000   Min.   :2013-01-01   Min.   :    0  
##  1st Qu.: 280.0   1st Qu.:2.000   1st Qu.:2013-08-17   1st Qu.: 3727  
##  Median : 558.0   Median :4.000   Median :2014-04-02   Median : 5744  
##  Mean   : 558.4   Mean   :3.998   Mean   :2014-04-11   Mean   : 5774  
##  3rd Qu.: 838.0   3rd Qu.:6.000   3rd Qu.:2014-12-12   3rd Qu.: 7856  
##  Max.   :1115.0   Max.   :7.000   Max.   :2015-07-31   Max.   :41551  
##    Customers           Open            Promo        StateHoliday      
##  Min.   :   0.0   Min.   :0.0000   Min.   :0.0000   Length:1017209    
##  1st Qu.: 405.0   1st Qu.:1.0000   1st Qu.:0.0000   Class :character  
##  Median : 609.0   Median :1.0000   Median :0.0000   Mode  :character  
##  Mean   : 633.1   Mean   :0.8301   Mean   :0.3815                     
##  3rd Qu.: 837.0   3rd Qu.:1.0000   3rd Qu.:1.0000                     
##  Max.   :7388.0   Max.   :1.0000   Max.   :1.0000                     
##  SchoolHoliday     
##  Length:1017209    
##  Class :character  
##  Mode  :character  
##                    
##                    
## 
summary(test)
##        Id            Store          DayOfWeek          Date           
##  Min.   :    1   Min.   :   1.0   Min.   :1.000   Min.   :2015-08-01  
##  1st Qu.:10273   1st Qu.: 279.8   1st Qu.:2.000   1st Qu.:2015-08-12  
##  Median :20544   Median : 553.5   Median :4.000   Median :2015-08-24  
##  Mean   :20544   Mean   : 555.9   Mean   :3.979   Mean   :2015-08-24  
##  3rd Qu.:30816   3rd Qu.: 832.2   3rd Qu.:6.000   3rd Qu.:2015-09-05  
##  Max.   :41088   Max.   :1115.0   Max.   :7.000   Max.   :2015-09-17  
##                                                                       
##       Open            Promo        StateHoliday       SchoolHoliday     
##  Min.   :0.0000   Min.   :0.0000   Length:41088       Length:41088      
##  1st Qu.:1.0000   1st Qu.:0.0000   Class :character   Class :character  
##  Median :1.0000   Median :0.0000   Mode  :character   Mode  :character  
##  Mean   :0.8543   Mean   :0.3958                                        
##  3rd Qu.:1.0000   3rd Qu.:1.0000                                        
##  Max.   :1.0000   Max.   :1.0000                                        
##  NA's   :11

데이터가 흠 가게 Id는 정수형이고 다 주 5일제고 뭐...손님수는 다양하네요 500~1500명까지.... 휴일여부는 0,1로 나뉘어져있고 네..

여튼 데이터 구경은 이정도면 충분하고. 넘어갑니다.   그리고 summary함수를 통해서 또 최대/최소/최빈값등등을 보면서 대략적이나마 data distribution 형태를 좀 예측할 수 가 있지요... 




앗!!! 다음에 이어하겠습니다.

좀 더 해야하는데.. 다음 6일차때 추가하겠습니다.






























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

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 #3  (0) 2016.05.16
Kaggler's Day #1  (0) 2016.05.12
Posted by 억사마
카테고리 없음2016. 5. 26. 18:33

Kaggler 4번째 시도입니다. 이번에는 RF(Random Forest)를 가지고 Facebook competition에서 Awards를 받은 팀의 스크립트에 대해서 정리하고자 합니다. 


간단하게 문제는 페이스북데이터(평방 10km 그리드안에 약 30만개의 check-ins 정보)가 주어지고 시공간 정보에 의존하여 유저가 무슨 비지니스에 체크인하는지를 파악하는 문제이라고 합니다. 웃긴 부분은 place id를 기준으로 분류하면 100k 개의 종류가 있어서 대부분의 supervised learning 기술은 전체 dataset에서 안먹힐 거라고 합니다. 하지만 다행히 대부분의 종류들이 그리드의 특정 지역에서 cluster가 되어서 여기 팀은 그리드안의 작은 직사각형을 선택해서 그 범위안에서 검증을 해보았다고 합니다. 그래서 더 작은 스퀘어에서 약간의 실험적인 데이터 분석을 하고나면 예측을 위해서 random forest를 사용하여 결과 분석할 것이다라고 합니다.


아래는 사용한 라이브러리


library(data.table) #reading in the data
library(dplyr) #dataframe manipulation
library(ggplot2) #viz
library(ranger) #the random forest implementation
library(plotly) #3D plotting
library(tidyr) #dataframe manipulation

fb에 training dataset을 집어넣습니다.

fb <- fread("../input/train.csv", integer64 = "character", showProgress = FALSE)

그리고 나서 아까 말한 부분집하을 데이터에 선택합니다. 그 기준은  250 x 250meters 크기의 특정 직사각형의 데이터를 뽑고


fb %>% filter(x >1, x <1.25, y >2.5, y < 2.75) -> fb
head(fb, 3)
##    row_id      x      y accuracy   time   place_id
## 1:    600 1.2214 2.7023       17  65380 6683426742
## 2:    957 1.1832 2.6891       58 785470 6683426742
## 3:   4345 1.1935 2.6550       11 400082 6889790653

place_id와 시간, x,y는 좌표일테고... 그리고 accuracy는 뭘까요? 



small_train = fb[fb$time < 7.3e5,]
small_val = fb[fb$time >= 7.3e5,] 

여튼 kaggle에서 test 데이터로 돌려서 scoring을 할텐데 좀 더 유사하기 위해서 최근 데이터를 validation으로 두었다고 합니다.


자 분석을 시작해봅시다!!!


ggplot(small_train, aes(x, y )) +
    geom_point(aes(color = place_id)) + 
    theme_minimal() +
    theme(legend.position = "none") +
    ggtitle("Check-ins colored by place_id")




그림이 이쁘게 plotting이 ggplot으로 그려지긴 하나 겹쳐지는 부분이 꽤 있어 보여서 place_id군들이 잘 구분이 안되어질거 같습니다. 그래서!!! 공간에 시간 개념을 넣어서 plot을 그려보자고 하는군요... 즉 x,y말고도 3차원을 만들기위해 z좌표로 hour을 쓰겠다는거군요.. 여튼 아래 소스로 직접 보면 우선 500개 이하인 place_id들은 날리고 place_id list를 ids에 담네요 그리고 small_trainz라는 subset을 만듭니다. 그리고 그걸로 그리는데...


small_train %>% count(place_id) %>% filter(n > 500) -> ids
small_trainz = small_train[small_train$place_id %in% ids$place_id,]

plot_ly(data = small_trainz, x = x , y = y, z = hour, color = place_id,  type = "scatter3d", mode = "markers") %>% layout(title = "Place_id's by position and Time of Day")

type을 scatter3d로 줘서 그런지 이쁘네요...  kaggle에서 plot을 못가져오겠네요. 동적이라서!!!  여기에서 직접 보세요..

그렇지만 캡쳐해서 올리면.. 이렇습니다. 캬..




 중간에 Place_id's by position and Time of Day라고.. 차트가 hovering하면 3차원의 plot을 동적으로 보여주네요.. ㄷㄷㄷ  시간단위는 먼지 모르겠지만 여튼... hour를 넣고 안겹치게 잘 그려지네요!! 와우!! 시간 dimension을 넣었더니 이렇게 clear가 되는군요..  특정 지점에서 체크인이 몇시간 동안 멈췄다가 다시 체크인이 이뤄지고 있는 모습도 보이고요. 어떤 비지니스들은 꽤 낮 내내 높은 사용률이 보이고 비지니스마다 꽤 서로 다른 peaks를 가지고 있는 경향이 있네요. 또한 z=0과 z=24인 시점은 같은 것이라는 것도 유의해서 3d plot을 보라고 하는군요.  

 

하지만 아직 우리는 매우 많은 클래스들이 있습니다. (아까 많이 제외를 했기때문에..)

다시 small_train set을 가지고 와서 unique로 종류를 보면 770개의 business들이 있고요. 

length(unique(small_train$place_id))
## [1] 770

여기에서 빈도가 낮은 녀석들은 날리고 ...  3개 이하로 일어나는것들은 날리면 종류가 그래도 많이 준다고 합니다.  우리는 validation set을 가지고 있기 때문에 우리는 항상 다시 돌아와서 filter level을 조절할수 있죠. 더 나은 정교한 모델을 만들기 위해서 말이지요~~



small_train %>% count(place_id) %>% filter(n > 3) -> ids
small_train = small_train[small_train$place_id %in% ids$place_id,]

이렇게 필터링하고 나면 15595 트레이닝 샘플과 224개의 클래스를 가지고 이제 ML을 할 준비를 했다고 합니다..... 자 숲으로!!



원래 RF보다 ranger라는모듈(별도의 RF를 구현)을 사용했다고 합니다. 약 5배의 빠른 성능과 메모리 효율성이 좋다고 합니다. 여튼 이건 중요한 얘긴 아니고..

seed는 넘어가고 place_id를 classification의 factor로 사용을 했고 ranger를 이용하여 model_rf라는 RF모듈을 만드네요.  x와 y, accuracy, hour를 넣고 돌립니다. 그리고 random sampling은 100개를 해서 decision tree를 만드네요.


set.seed(131L)
small_train$place_id <- as.factor(small_train$place_id) # ranger needs factors for classification
model_rf <- ranger(place_id ~ x + y + accuracy + hour,
                   small_train,
                   num.trees = 100,
                   write.forest = TRUE,
                   importance = "impurity")
## Growing trees.. Progress: 48%. Estimated remaining time: 33 seconds.
pred = predict(model_rf, small_val)
pred = pred$predictions
accuracy = mean(pred == small_val$place_id) 

오래 걸리는군요.  만든 모델을 가지고 실제 small_val에서 돌려보면 accuracy가 0.5240919라고 하네요. 나쁘지 않다고 합니다. 물론 처음치고 나쁜 건 아니죠.  이 competition의 평가 metric은 3개의 test set의 mean average precision이라고 하네요. 그래서 class에 의한 votes/probabilities을 예측하고 점수를 개선하기 위해 보증된 top 3개의 id를 카운팅한다?? 뭔말인지.. 여튼.. 넘어갑니다 ㅡ.ㅡ


small_val$Correct = (pred == small_val$place_id)

ggplot(small_val, aes(x, y)) +
    geom_point(aes(color = Correct)) + 
    theme_minimal() +
    scale_color_brewer(palette = "Set1") +
    ggtitle("RF Results")



위의 plot은 모델을 가지고 우리가 맞은것과 틀린것을 표시한건데 accuray가 50% 살짝 넘엇었죠?보기에 correct한 checkin이 더 클러스터링이 된거 같다고 합니다. uncorrect한건 보면 균일하게 분배되어있는거 같고. 


그래서.. 어떤 종류의 RF가 잘못되는지 보자고 합니다. 이를 위해서 우리는 id별 accuracy를 보고 또한 id기준의  plot, validation set에 그것들이 얼마나 자주 나타나는지를 기준으로 한 걸 나타낼려고 합니다. 이 모델이 더 인깅가 있을 수록 더 정확하고 아닐 경우는 accuracy가 줄어드는걸 확인할수 있네요.. 봅시다.


#reordering the levels based on counts:
small_val$place_id <- factor(small_val$place_id,
                             levels = names(sort(table(small_val$place_id), decreasing = TRUE)))

small_val %>% 
    ggplot(aes(x = place_id)) + geom_bar(aes(fill = Correct)) + 
    theme_minimal() +
    theme(axis.text.x = element_blank()) +
    ggtitle("Prediction Accuracy by ID and Popularity") +
    scale_fill_brewer(palette = "Set1")


그럼 변수들의  중요성을.. 또한 보면...

data.frame(as.list(model_rf$variable.importance)) %>% gather() %>% 
    ggplot(aes(x = reorder(key, value), y = value)) +
    geom_bar(stat = "identity", width = 0.6, fill = "grey") +
    coord_flip() +
    theme_minimal() +
    ggtitle("Variable Importance (Gini Index)") +
    theme(axis.title.y = element_blank()) 


 흥미로운 점은 x보다 y가 중요하다는 것. 이건 다른 스크립트에서도 많이 관찰이 된다. place_id의 variaince는 y방향보다 x방향에서 더 크다. 이것은 y축이 더 place_id의 predictior로 좋고  RF가  그 스스로 이것을 알아낸다라는 것이다. hour또한 좋은 predictor이고 공간적인 지표보다는 못하다.  마지막으로 accuracy가 중요하다고 하빈다. 이것은 좀 미스테리하다고 합니다. 왜냐하면 우리는 실제 정의를 얻지 못하나 모델은 이게 중요하다고 한다. 마지막까지도... accuracy의 변수가 데이터에서 뭘 뜻하는지 모르고 종료합니다.


그리고.... 여기 아이디어에서 추가로 제안을 아래와 같이 하네요. 이것은 귀찮으니 걍 영어로... --a

한마디로 뭐.. grid사이즈를 다르게 주거나 다른 모델을 써보자는 얘기죠...


Here are a few sugesstions:

  • play with how big the grid size is and see if you can get better validation results
  • try different areas on the map
  • try different models (maybe xgboost or somehing simple like logistic regression)
  • split the grid into n*n little squares and run you algorithm in each of the squares - this might take a while though.




이상입니다.

Posted by 억사마
데이터분석2016. 5. 16. 11:36

Kaggler가 되어도 분석할 데이터, 도메인 지식이 없으면 아무 소용이 없다. 그래서 Kaggler가 되기 위한 시도로써 또 나는 분석할 대상, 도메인 지식도 쌓고 그리고 관련 데이터도 어디서 확보하면 좋을까를 목표로 또 하나의 습관을 들이기로 한다.


데이터 도메인은 부동산쪽이며 주제는 아파트가격 분석이 되겠다. 예측까지가면 좋을것 같지만 우선 과거 데이터를 가지고 분석정도를 목표로 한다. 


RAW 데이터 source는 다음이 되겠다.

국토부 실거래사이트(rt.molit.go.kr)  

 realtime은 아니지만 최대 3달 이내의 실거래가 데이터를 얻을수 있다. 동호수까지는 모르는게 단점

 한국산업단지공단( )www.kicox.or.kr) :

 인구 유입율

 부동산114(or 닥터아파트)

 매년 아파트 브랜드 선호도 발표 

 www.apt2you.com 

 청약접수 경쟁률 조회

 통계청 국가포털(http://kosis.kr) / 통계청 http://kostat.go.kr

 

 서울시 재개발/재건축 클린업시스템 cleanup.seoul.go.kr

 


아래는 데이터 분석 관련 통계청 데이터 목록 


1. 가계동향조사 : 가구의 생활수준실태와 그 변동사항을 파악하기 위해서 가계의 수입과 지출을 조사하여 - 국민소비수준 변화의 측정 및 분석 - 소비자물가지수 편제에 필요한 가중치 모집단 자료 등 각종 경제, 사회정책에 필요한 자료를 제공 - 공공사업 시행으로 인한 세입자의 주거대책비 산정 및 국민주택 공급대상의 기준설정 자료


2. 장래인구추계 : 2010년 인구주택총조사 결과를 기초로, 인구동태(출생․사망)와 국제인구이동통계를 활용, 코호트 요인법 ( Cohort components method)에 의해 2060년까지 향후 50년간의 인구규모 및 성․연령별 구조를 추계 ㅇ 2010년 인구주택총조사(11월 1일자)의 성․연령별 인구 보정 - 성․연령별 기준인구(2010년 7월 1일자) 확정 - 인구변동요인(출생․사망․국제이동) 분석 - 출산력․사망력․국제이동 모형 및 장래 변동 수준에 대한 가정설정 - 가정별 인구추계 시산 및 결과 분석


3. 국내인구이동통계 : 인구 이동 상황을 주기적으로 파악하여 인구정책 및 지역간 균형개발을 위한 기초자료로 활용


4. 한국도시통계 : - 전국 시·읍의 인구, 재정, 건설, 사회복지 및 문화 등 각 분야의 주요통계 자료를 수록하여 도시 변화양태 파악 및 도시행정을 위한 기초자료 제공 - 중앙부처, 지방자치단체, 유관기관 등에서 도시행정 수행에 활용


5. 노인(65세 이상)의 연간 총수입, 소득항목별 금액 및 구성비 

  - 일반특성별 (30개)

:전체, 지역별, 동부, 읍·면부, 성별, 남자, 여자, 연령별, 65~69세, 70~74세.....

- 소득항목별 (8개)

: 총수입, 근로소득, 사업소득, 재산소득, 사적이전소득, 공전이전소득, 기타수입, 기타소득

- 항목 (2개)

: 금액, 구성비



6.  각종 지수(통계청 발표)

    아파트 실거래가격지수(2006.1=100.0) 수록주기 월 2006.01~2016.03  아파트 실거래가격지수(2006.1=100.0) 파일 다운로드  아파트 실거래가격지수(2006.1=100.0) 구성정보

    규모별 아파트 실거래가격지수 전월대비 증감률(%) 수록주기 월 2006.02~2016.02  규모별 아파트 실거래가격지수 전월대비 증감률(%) 파일 다운로드  규모별 아파트 실거래가격지수 전월대비 증감률(%) 구성정보

    규모별 아파트 실거래가격지수(2006.1=100.0) 수록주기 월 2006.01~2016.02  규모별 아파트 실거래가격지수(2006.1=100.0) 파일 다운로드  규모별 아파트 실거래가격지수(2006.1=100.0) 구성정보

    아파트 실거래가격지수 전월대비 증감률(%) 수록주기 월 2006.02~2016.03  아파트 실거래가격지수 전월대비 증감률(%) 파일 다운로드  아파트 실거래가격지수 전월대비 증감률(%) 구성정보

 부동산시장 소비자심리  

    부동산시장 소비심리지수 수록주기 월 2011.07~2016.03  부동산시장 소비심리지수 파일 다운로드  부동산시장 소비심리지수 구성정보

    주택시장 소비심리지수 수록주기 월 2011.07~2016.03  주택시장 소비심리지수 파일 다운로드  주택시장 소비심리지수 구성정보

    주택매매시장 소비심리지수 수록주기 월 2011.07~2016.03  주택매매시장 소비심리지수 파일 다운로드  주택매매시장 소비심리지수 구성정보

    주택전세시장 소비심리지수 수록주기 월 2011.07~2016.03  주택전세시장 소비심리지수 파일 다운로드  주택전세시장 소비심리지수 구성정보





UPDATE ( 2016.05.27. "아는만큼 번다 돈이 되는 빅데이터" 책 내용 추가)


데이터를 다루는 기본 지식

비(ratio) : 분자 / 분모 독립적

비율(proportion)  : 분자가 분모에도 포함

율(rate) : 시간개념이 같이 있어 "속도"개념이 추가된 것.

기저효과(base effect) : 기준/비교 시점의 차이로 왜곡이 되는 현상.

%, %p : p가 붙으면 퍼센테이지의 차이를 얘기한다.

INDEX는 기준시점 + 가중치 + 지수식으로 결정


한국은행 경제 통계시스템

 국가별 통화량 추이(M1,M2) 가계부채상황, 부채지표등 각종 지표 파악 가능

 ※ 처분가능소득 대비 금융부채 비율, 처분가능소득 대비 원리금 상환액 비율등...

 온나라 부동산 정보종합포탈 

 행정구역별 최초 주택 거래량, 월별 매입자 거주지별(실거주자와 매입자의 일치 여부)

 월별 거래주체별 / 거래규모별 / 건물유형별 

 한국거래소

 

 금융투자협회 전자공지서비스

 

 KB부동산 알리지

 

 R-ONE 부동산통계정보시스템

 상업용 부동산 거래 정보, 미분양 정보(준공후 미분양까지), 연령별(아파트나이별)매매가격지수, 자가점유비율, 자가보유율(주택 보유 가구 / 일반가구수)












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

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
Kaggler's Day #1  (0) 2016.05.12
Posted by 억사마
카테고리 없음2016. 5. 13. 14:10

오늘은 Kaggler 되기 두번째 날입니다. 금일 다루는 내용은 어려운 내용이 될듯.. 털썩.  brief하게 더듬고 넘어가는 걸로 하겠습니다.  문제는 3달전 있었던 한 competition에서 우승한 팀의 how to solvec입니다. 1764개의 팀(1925명 참가)중에서 우승을 차지한 팀의 내용을 가져왔습니다.  해설로는 600개의 베이스 모델을 멋지게 혼합하여 우승을 할거라고 확신했다 하는데 봅시다.


문제 요약

Homesite라는 Home Insurance회사에서 어떤 고객이 특정 보험 상품을 구매할거냐를 분석하여 마케팅에 활용하고자 competition을 연거구요.  데이터는 여기에 트레이닝/테스트 데이터가 주어진답니다. 그리고 분석 후 제출할 샘플 양식까지 주어집니다.  제출하면 여기에서 점수가 주어지고 랭킹까지 되네요. 하지만 소스코드를 볼려고 했더니... 코드는 비공개인거 같습니다. 하긴 1등이 천만원의 상금이 걸려 있고 뭔가 이 회사에서 실제로 분석 모델로 사용할 거라 당연히 비공개일듯.. 


하지만 how to solve는 제가 보기에 나름(?) 정리가 잘 되어져 있습니다.  봅시다!!



Feature Engineering라는 것은 ML이 작동하기 위해서 도메인 지식을 가지고 features를 만드는 과정이라고 볼수 있습니다. 그럼 여기에서 feature는 머냐고 하면 관찰하고 있는 object/phenomenon에 대한 individual measurable property를 말하구요.  하지만 이 feature engineering을 사용하기에는 어려웠다고 합니다. feature를 잡아내기 위한 과정을 통하여 feature를 선별하긴 했으나 결국엔 극수의 engineered features를 얻었다고 합니다.  

- Count of 0, 1 and N/A row-wise

- PCA top component features

- TSNE 2D

- Cluster ID generated with k-means

- Some differences among features (especially the “golden” features found in a public script)


TSNE과 마지막은은 이해가 잘 안가고. 나머지는 봅시다.  AUC가 처음부터 높게 나와서 신났다고 하네요. 


아래 그림은 PCA로  Red(부정)/Green(긍정)으로 Classification이 되서 말이죠.

Dataset plotted against the top 2 components of PCA (negative in green, positive in red)


그 다음 그림은 TSNE로 한거라고 합니다.


Dataset plotted against the top 2 dimensions of TSNE (negative in green, positive in red)



Dataset Modeling

Python Sklearn의 label encoder를 이용하여 categoriclal features를 인코딩하였다고 합니다. 간단하지만 막강한 이 녀석으로 트리 분류기에서도 작동이 꽤 잘 되었다고 합니다. 하지만 linear한 것들에게는 추천하지 안흔다고 합니다. 왜냐하면 우리 또한 one hot encoded features를 생성했기 때문이라고 합니다.. ( 이 말은.. 저도 이해가 안가네요) 결국 우리는 타겟에 영향을 주는 categorical features의 ratio를 구하기 위해서 target encoding도 시도했다고 합니다. 하지만 개선이 되지 않았다고 합니다.  <-- 결국 label encoding의 불편함을 얘기한거 같습니다 trial and error죠.



Training & Ensembling


여기에서부터 흥미진진한데요.  데이터셋의 다른 버젼들에다가 아래와 같은 ML 모델을 돌렸다고 합니다. 정말 잘 알려져있는것들 잔뜩이네요. 저한텐 밑에 3개는 또 모르지만..

- Logistic Regression

- Regularized Greedy Forest

- Neural Networks

- Extra Trees

- XGBoost

- H2O Random Forest (just 1 or 2 models into our first stage: not really important)

위의 3개는 알겠으나 그 밑에 3개는 모르겠습니다. 마지막껀 H20는 뭔가 RF의 새로운 버젼인거 같은데.. 좀 봐야겠고.. ^^ 여튼 약 600개의 모델로 1레벨이 이루어져 있다고 합니다. 100개는 수작업으로 위의 기술한 기술들의 different features와 hyperparameters를 가지고 만들어졌다고 합니다. 그리고 나서 다양성을 고려하여 500개의 나머지 모델을 만드는 로봇(?)을 만들었다고 합니다. 이 로봇은 자동으로 XGBoost, 로지스틱 회귀, NN가지고 임의로 선택된 features를 기반으로 하여 model을 훈련시킨다고 하네요...  -> 이부분은 신기하네요.. feature가 고정적인것도 아닌가봅니다.


여튼 우리의 모델은 5 fold stratified CV로 만들어졌으며(테스트한 train/test 데이터를 5개로 쪼개서 또 트레이닝 시킨다는 말입니다 CV= Cross Validation)  이로써 우리가 개선을 꾀하고 overfitting을 피할수 있게 도와준다 합니다. 게다가 CV로다가 앙상블 모델을 사용할 수 있었다 합니다(자세한 내용은 여기 뭔가 난해합니다. 여기까진 시간관계상 빠지는걸로..)



아래는 앙상블 예인거 같은데  RGF와 XGB의 관계도.. CORRELATION이 꽤 높죠?

Predictions of an RGF model plotted against predictions of a XGB model

그런데 전 이해가 잘안가네요... 그래서 어쩌라고?? 여튼  600개의 모델을 혼합하기 위해서 다양한 방법을 사용했고 몇번의 실패후에 3개의 멋진 조합을 발견했다고 합니다. 바로 고전적인 로지스틱 회귀와 XGB, NN의 조합이었다합니다.. 후아.. 끝....


그래서 요약하자면...


Model ensemble


그리고 노하우를 알려주네요. 저는 아래 팁들이 상당히 공유가 꺼려질정도로 마음에 듭니다. 내 머리속에만 넣어두고 나만 활용하고 싶다는...

데이터 사이언스의 영역은 쉬운길이 아니고 어렵습니다. 하지만 아래와 같은 방식과 마인드셋으로 하면 언젠가.. 나도 FAMOUS DATA EXPERT가 될겁니다. 그럼 오늘 연재 끝..


  • Read forums, there are lots of useful insights
  • Use the best script as a benchmark
  • Don’t be afraid to generate lot of models and keep all the data created this way. You could still select them later in order to blend them… Or let the blender take the decision for you 🙂
  • Validate the behavior of your CV. If you have a huge jump in local score that doesn’t reflect on the leaderboard there is something wrong
  • Grid search in order to find hyperparameters works fine
  • Blending is a powerful tool. Please read the following post if you haven't have already: http://mlwave.com/kaggle-ensembling-guide/
  • Be aware of the standard deviation when blending. Increasing the metric is good but not that much if the SD increases
  • Neural nets are capricious 🙁 bag them if necessary
  • Merging is totally fine and helps each teammates to learn from others
  • If you are a team, use collaborative tools: Skype, Slack, svn, git...

Recommendations to those just starting out

As written just above, read the forums. There are nice tips, starter codes or even links to great readings. Don’t hesitate to download a dataset and test lot of things on it. Even if most of the tested methods fail or give poor results, you will acquire some knowledge about what is working and what is not.

Merge! Seriously, learning from others is what makes you stronger. We all have different insights, backgrounds or techniques which can be beneficial for your teammates. Last but not least, do not hesitate to discuss your ideas. This way you can find some golden thoughts that can push you to the top!









Posted by 억사마
데이터분석2016. 5. 12. 18:49

난 일주일에 세번!!!! Kaggle에 올라온 Famous Script를 따라서 해보고 감상평과 내용요약을 하고자 한다.


1. 주제

Kaggle에서는 사용자들이 Public Dataset을 가지고 분석한 스크립트와 보고서를 보고 Voting을 한다. 그중 가장 많은 아마존의 Find Food의 리뷰 분석 실습이다.. 데이터는 스탠포드에서 제공하고 2012년 10월에 아마존 사용자들의 568,454 리뷰 데이터를 모은것이다.

데이터 구성은 csv로 아래와 같다.

  • Id
  • ProductId - unique identifier for the product
  • UserId - unqiue identifier for the user
  • ProfileName
  • HelpfulnessNumerator - number of users who found the review helpful
  • HelpfulnessDenominator - number of users who indicated whether they found the review helpful
  • Score - rating between 1 and 5
  • Time - timestamp for the review
  • Summary - brief summary of the review
  • Text - text of the review

그리고 내가 선정한 스크립트는 바로 Ben Hamner이란 분이 올린 script가 되시겠다. 참고로 8개의 voting을 받았다. 


library(RSQLite)
library(tm)
library(wordcloud)

library(RSQLite)
db <- dbConnect(dbDriver("SQLite"), "../input/database.sqlite")

reviews <- dbGetQuery(db, "
SELECT *
FROM Reviews
LIMIT 10000")

make_word_cloud <- function(documents) {
  corpus = Corpus(VectorSource(tolower(documents)))
  corpus = tm_map(corpus, removePunctuation)
  corpus = tm_map(corpus, removeWords, stopwords("english"))
  
  frequencies = DocumentTermMatrix(corpus)
  word_frequencies = as.data.frame(as.matrix(frequencies))
  
  words <- colnames(word_frequencies)
  freq <- colSums(word_frequencies)
  wordcloud(words, freq,
            min.freq=sort(freq, decreasing=TRUE)[[400]],
            colors=brewer.pal(8, "Dark2"),
            random.color=TRUE)  
}

png("wordcloud.png")
make_word_cloud(reviews$Text) 
dev.off()


분명 데이터도 sqlite에서 잘 뽑아와서 corpus를 munging하고 wordcloud함수도 잘 생성되었으나... 쉬운예제임에도불구하고 그림이 안 나옴.. 

실패되시겠습니다. 그래도 여튼 원래장소에서 가져와서붙이고 내가 한걸로.. ㅡ.ㅡ

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

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
Kaggler's Day #3  (0) 2016.05.16
Posted by 억사마
카테고리 없음2015. 5. 6. 18:58

파워셀을 이용하면 되고 스크립트는 다음과 같다.


아래 &match는 바꿀 문자열  &replacement는 변환할 문자열로 입력하되 하위에도 *slf* 라고 되어있는 부분은 직접 넣어줘야하는듯.


$match = "swtichstr" 

$replacement = "convertedstr"


$files = Get-ChildItem $(get-location) -filter *sif* -Recurse


$files |

    Sort-Object -Descending -Property { $_.FullName } |

    Rename-Item -newname { $_.name -replace $match, $replacement } -force




$files = Get-ChildItem $(get-location) -include *.* -Recurse 


foreach($file in $files) 

    ((Get-Content $file.fullname) -creplace $match, $replacement) | set-content $file.fullname 

}


read-host -prompt "Done! Press any key to close."

Posted by 억사마
IT/후기2015. 3. 13. 13:51

아주 간만에 흥미로운 책을 읽었다. Polyglot 이라고 프로그래밍을 여러개 할 줄 아는 능력을 갖추라는 메시지가 담긴 책이다.

저자 임백준씨의 책은 대학교때 한손으로 뽑을 정도로 적게 읽었던 책중에 행복한 프로그래밍의 책부터 한권도 빠짐없이 보고 있다. 

아는 것이 참 많으신듯. 람다와 클로저의 개념도 쉽게 설명을 해주시고 많은 레퍼런스도 공유를 해주셨다.



스택오버플로우 사이트는 개발자면 다 아는 사이트이다. 이 사이트를 만든 사람 중 아트우드는 조엘 온 소프트웨어 저자 ,조엘 스폴스키와    stackoverflow를 만들고 이곳을  떠나서 대화 담화 의견의 교환 등을 의미하는 discourse.org 라는 웹사이트를 개발한다. 위키북스라는 책도 찾아보자. 



ㅇ Podcast

  'ted neward podcast'라고 검색하면 여럿 나옴.


ㅇ 람다와 클로저 

람다는 익명 메서드라고 보며, 코드조각 혹은 표현을 다른 객체나 메서드에 전달하기 위한 표현식이고. 

클로저는 외부에서 정의된 변수를 참조하는 코드조각 혹은 표현


public void foo()  {

int i = 0;

JButton  button = new JButton("Click me");

button.addActionListener( new ActionListener() {

// 이책에선 아래의 함수 정의 자체가 행사코드 

라고 표현

@Override

public void actionPerformed(ActionEvent e) {

System.out.println(i);

}

});

}


에서,  System.out.println(i);에서 i가 빠지면 람다이긴 하나 클로저가 아닌거라는 말이다.


ㅇ 코드의 변경불가능성 (블로흐 effective java)

 - 객체의 상태를 변경시키는 메서드를 제공하지 마라 

 - 클래스가 상속되지 못하도록 하라 

 - 모든 필드를 final로 선언하라

 - 모든 필드를 private로 선언하라

 - 변경불가능성을 만족시키지 못하는 컴포넌트에  대한 접근을 통제하라.

-  닐 게프터 vs 블로흐  (닐 게프터는 자바는 꽁꽁 얼어붙은 심해였다.)



ㅇ Scala 사용예

사회적 그래프를 역정규화된 사용자 ID의 리스트 형태로 저장하기 위해 Flock이라는 도구를 사용 

Hawkwind라는 스칼라로 구현된 서비스를 사용 : 트위터 사용자 검색엔진

호스버드 Hosebird : 공공 검색엔진에게 스트림으로 전송, http 기반의 지속적인 연결 시스템. 스칼라를 이용해서 jETTY 위에 우리만의 시스템 구현


시라는 것은 궁국의 압축이다. 감정의 철학과 깨달음과 메시지와 소통을, 치열한 사색과 고민으로 여과하여 간결한 언어 안에 압축시킨 것이라는 글귀에 시 한권 읽어야겠다는 생각도 들었다. 프로그래밍과 참 유사해야한다라는 말에 공감이 간다.



[형식 언어의 정의를 위한 새로운 접근법과 오테론에서의 응용] 라는 논문도 찾아서 보면 프로그래밍의 원리 이해에 도움이 될것 같다.




아래의 함수 프로그래밍 개념을 "Functional Programming for Java Developer(저자 Dean Wampler)"라는 책을 보고 익히자.

- 변경불가능성

- 일급함수

- 람다와 클로저

- 고차함수

- 재귀

- 게으른 평가

- 함수 합성

- 모나드


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

PyconKR 2016 정리  (0) 2016.08.16
2013 JCO 후기  (0) 2013.02.23
Posted by 억사마
IT/Tool2015. 3. 3. 10:32

PowerShell 익숙해지기.


- 비공개로 시작

- 필자는 자바 프로젝트를 git으로 갈아타면서 기존의 svn의 .svn폴더들을 일괄 삭제를 하고 싶어졌다.

svn export로 간단히 해결되지만 svn이 설치가 안되어 있어서 구글에서 커맨드라인에서 일괄 삭제할수 있는 배치 성격의 스크립트가 있나서 찾아보았으나 "파워쉘" 많이도 들어봤지만 써보지도 못한 그녀석의 스크립트 발견. native application으로  이미 윈도우에 포함이 되어 있어서 아래의 스크립트로 간단히 실행하여 일괄 삭제를 하였다. 

gci -fil '.svn' -r -force | ri -r -force

-참고

http://stackoverflow.com/questions/4889619/command-to-recursively-remove-all-svn-directories-on-windows



'IT > Tool' 카테고리의 다른 글

Git  (0) 2013.04.01
캡쳐부터 자동 웹업로드되는 막강 툴! Cropper!  (0) 2013.03.25
JMeter  (0) 2013.02.26
JMeter - Java Request  (0) 2013.02.18
Posted by 억사마