Skip to content

Instantly share code, notes, and snippets.

@neoneo40
Created January 17, 2015 09:34
Show Gist options
  • Save neoneo40/6294bac4655f44aad81a to your computer and use it in GitHub Desktop.
Save neoneo40/6294bac4655f44aad81a to your computer and use it in GitHub Desktop.
kaggle_weather
# Kaggle.com
# Competition
# < Bike Sharing Demand >
# 세미나 시간 2시간
# 일자 : 1월 17일 토요일 갱남.
# 문제푸는 시간. 캐글 소개, 문제 설명, 데이터 주고, 도전
# 중간중간 미리 준비한 코드 보여주며 잡아주기. 전체 프로세스 경험
# 1. 상황 파악하기(데이터셋 불러오기)
sample_submission = read.csv("sampleSubmission.csv", header = TRUE)
test = read.csv("test.csv", header = TRUE)
train = read.csv("train.csv", header = TRUE)
head(sample_submission, 20) # 제출 형식을 확인해봅시다.
head(train, 20) # 모델 생성 데이터셋을 확인해봅시다.
head(test, 20) # 검증 데이터셋을 확인해봅시다.
summary(train)
summary(test)
summary(sample_submission)
# 2. 목표 정하기
# 우리가 예측해야 할 변수는?
head(sample_submission)
# count 입니다.
# 각 변수에 대한 이해!
# join $ -> take -> ride -> return
# datetime - hourly date + timestamp
# season - 1 = spring, 2 = summer, 3 = fall, 4 = winter
# holiday - whether the day is considered a holiday
# workingday - whether the day is neither a weekend nor holiday
# weather - 1: Clear, Few clouds, Partly cloudy
# 2: Mist + Cloudy, Mist + Broken clouds, Mist + Few clouds, Mist
# 3: Light Snow, Light Rain + Thunderstorm + Scattered clouds, Light Rain + Scattered clouds
# 4: Heavy Rain + Ice Pallets + Thunderstorm + Mist, Snow + Fog
# temp - temperature in Celsius
# atemp - "feels like" temperature in Celsius
# humidity - relative humidity
# windspeed - wind speed
# casual - number of non-registered user rentals initiated
# registered - number of registered user rentals initiated
# count - number of total rentals
# 좀 더 알아보자
sub_date = as.data.frame(substr(train[,"datetime"], 1, 10))
sub_unique_date = unique(sub_date)
start_end = c(as.character(sub_unique_date[1,]), as.character(sub_unique_date[nrow(sub_unique_date),]))
start_end # 시작일, 종료일 확인
difftime(sub_unique_date[nrow(sub_unique_date),1], sub_unique_date[1,1])
nrow(sub_unique_date) # 시작과 끝의 차이는 718일, 보유 데이터 456일. 약 40%정도의 데이터가 없다.
nchar(as.character(train[1,1])) # 몇 글자로 시간이 표현되었는지 확인해봅시다.
train_sub_date = as.data.frame(substr(train[,1], 1, 10)) # 날짜
train_sub_year = as.data.frame(as.numeric(substr(train[,1], 1, 4))) # 년도
train_sub_month = as.data.frame(as.numeric(substr(train[,1], 6, 7))) # 월
train_sub_day = as.data.frame(as.numeric(substr(train[,1], 9, 10))) # 일
train_sub_hour = as.data.frame(as.numeric(substr(train[,1], 12, 13))) # 시간
head(train_sub_date) # 시간 확인 ㄱㄱ
train_sub = cbind(train_sub_date, train_sub_year, train_sub_month, train_sub_day, train_sub_hour, train[,2:ncol(train)])
head(train_sub)
colnames(train_sub) = c("date", "year", "month", "day", "hour", colnames(train_sub)[6:ncol(train_sub)]) # 이름 바꿔주기
head(train_sub)
# 결측값에 대한 이해!
summary(train_sub) # 결측치(NA)가 없다.
year_unique = unique(train_sub$year)
month_unique = unique(train_sub$month)
year_unique
month_unique
table(train_sub$hour) # 시간 별로 숫자가 다름 -> 데이터가 조금씩 없음.
max(table(train_sub$hour)) # 최대값 = 456. 결측치가 없는 경우의 데이터 수량이 456일 수 있다.
# 데이터셋[ 열 번호 , 행 번호]
train_sub[1:24 , 1:4]
train_sub[25:35 , 1:4] # 다섯시의 데이터가 없다!!
# Calendar 붙이기
# 2011년, 2012년 달력을 불러온다.
calendar = read.csv("2011_2012_calendar.csv", header = TRUE)
head(calendar)
calendar_2 = as.data.frame(matrix(NA, nrow=nrow(calendar)*24, ncol=ncol(calendar)+1))
head(calendar_2)
# 0시 부터 23시 까지 숫자를 넣으면서 24배로 늘여야 한다.
matrix_hour = matrix(c(seq(0,23,1)), nrow=24, ncol=1)
for(n in 1:nrow(calendar))
{
if(n == 1)
{
calendar_2[1:24,1:10] = calendar[1,]
calendar_2[1:24,11] = matrix_hour
} else {
calendar_2[(24*(n-1)+1):(24*n), 1:10] = calendar[n,]
calendar_2[(24*(n-1)+1):(24*n), 11] = matrix_hour
}
}
head(calendar_2)
fix(calendar_2)
colnames(calendar_2) = c("year", "month", "day", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "hour")
head(calendar_2)
calendar_3 = calendar_2[,c(1,2,3,11,seq(4,10,1))] # 끝에 있던 "hour" column을 "day" 변수 뒤로 옮겨줍시다.
head(calendar_3)
# 데이터셋을 결합해봅시다.
# install.packages("plyr")
library("plyr")
head(train_sub)
head(calendar_3) # 공통되는 column을 확인.
train_calendar_join = join(calendar_3, train_sub, type = "left")
head(train_calendar_join, 50) # 30번째 row에 결측치(NA) 확인 가능
fix(train_calendar_join) # 전체를 살펴보면서 다시 확인
write.csv(train_calendar_join, "train_calendar_join.csv", row.names = FALSE)
# 이제 비어있는 결측치를 채워 넣어보자.
# Data Interpolation (Linear Interpolation) - sample
I_data = as.data.frame(matrix(c(1,2,3,4,5,6,3,NA,NA,10,2,NA,5,9,20), nrow = 5, ncol = 3))
colnames(I_data) = c("obs", "trend", "sales")
head(I_data)
for(col_no in 2:ncol(I_data))
{
NA_count = 0
for(row_no in 2:nrow(I_data))
{
value_check = I_data[row_no, col_no]
if(is.na(value_check))
{
NA_count = NA_count + 1
if(NA_count == 1)
{
value_prior = I_data[row_no-1, col_no]
}
}
value_later = value_check
if((is.na(I_data[row_no-1,col_no]) & (is.na(value_later) == FALSE)))
{
print("====Doing Interpolation====")
print(paste0("row number : ", (row_no-NA_count), "~", (row_no-1), " column number : ", col_no))
flush.console()
value_multi = (value_later - value_prior)/(NA_count+1)
for(Inter in 1:NA_count)
{
I_data[(row_no-NA_count+Inter-1), col_no] = value_prior + value_multi*Inter
}
}
}
}
head(I_data)
# 이제 주어진 데이터에 대한 Interpolation을 수행하자.
##########################################
head(train_calendar_join)
# 변수명 : season
# 이 변수는 월별로 고정적인 값을 가질 수 있다.
# ex. 봄 3~5월 / 여름 6~8월 등
#
# 특정 계절이 어떤 달이 포함되는지 알아보자.
# ※ 단순히 여름이 7~8월 언저리라고 단정하면 안되는 이유는, 이 데이터가 남반구의 것일 수 있다.
season_check = train_calendar_join[,c("month", "season")]
head(season_check)
table(season_check) # WOW!
# 이 경우는 위의 Interpolation 식을 사용 할 필요 없이 단순히 값을 대입해주면 된다.
test = train_calendar_join # 실수로 원 파일을 잘못 다룰 경우 앞의 코드를 다시 실행시켜야 되니 버퍼를 두자.
head(test)
table(test$season) # season = 1 의 개수를 잘 보자.
test[test$month == 3, "season"] = 1
table(test$season) # season = 1 의 개수가 증가 하였는가!?
fix(test) # 스크롤을 내려보면서 확인해 보자.
# 이제 위 코드를 train_calendar_join에 적용해보자!
table(season_check) # 다시 확인.
for(month in 1:12)
{
test[test$month == month, "season"] = ceiling(month/3) # 비슷한 함수 : round, floor
}
season_check_2 = test[,c("month", "season")]
table(season_check_2)
summary(season_check)
summary(season_check_2) # NA 개수 확인!
##########################################
head(train)
# 변수명 : holiday, workingday
# 공휴일에는 보통 일을 하지 않음으로 두 변수를 합칠 수 있을지도 모른다.
# ex. holiday = 1, workingday = 0
# 일단 분포를 보자.
holi_work_sub = train_calendar_join[,c("holiday", "workingday")]
head(holi_work_sub)
summary(holi_work_sub) # 결측치 6000개 이상...
table(holi_work_sub)
# 여기서 결측치를 어찌 처리할까?
# holiday와 workingday는 1일(24시간) 단위로 정해지는 숫자이다.
head(train_calendar_join)
sub_mode = train_calendar_join[,c("date", "holiday", "workingday")]
head(sub_mode)
summary(sub_mode)
# install.packages("doBy")
library("doBy")
summary_days = summaryBy(holiday + workingday ~ date, data = sub_mode, FUN = c(max), na.rm = TRUE)
summary_days[(nrow(summary_days)-4):nrow(summary_days),]
summary_days = summary_days[1:(nrow(summary_days)-1),]
head(summary_days)
fix(summary_days)
summary_days = cbind(as.numeric(substr(summary_days$date, 1, 4)), as.numeric(substr(summary_days$date, 6, 7)), as.numeric(substr(summary_days$date, 9, 10)), summary_days[,2:3])
colnames(summary_days) = c("year", "month", "day", "holiday_2", "workingday_2")
head(summary_days)
train_calendar_join = read.csv("train_calendar_join.csv", header = TRUE)
date_sub = train_calendar_join[,1:3]
head(date_sub)
date_days = join(date_sub, summary_days, type = "left")
head(date_days)
train_calendar_join[,c("holiday", "workingday")] = date_days[,4:5]
fix(train_calendar_join)
train_2 = train_calendar_join
train_2 = train_2[,-12]
head(train_2)
write.csv(train_2, "train_2.csv", row.names = FALSE)
#############################################
# 더 진행하기 전에 하루가 통째로 결측(NA)인 날은 날려버리자.
train_2 = train_2[is.na(train_2$holiday) == 0,]
fix(train_2)
##########################################
head(train_2)
# 변수명 : weather, temp, atemp
# Interpolation 수행, round 함수 사용
# 추가작업 : 그래프 그려보기
# Data Interpolation (Linear Interpolation) - weather, temp, atemp
colnames(train_2)
for(col_no in 15:17)
{
NA_count = 0
for(row_no in 2:nrow(train_2))
{
value_check = train_2[row_no, col_no]
if(is.na(value_check))
{
NA_count = NA_count + 1
if(NA_count == 1)
{
value_prior = train_2[row_no-1, col_no]
}
}
value_later = value_check
if((is.na(train_2[row_no-1,col_no]) & (is.na(value_later) == FALSE)))
{
print("====Doing Interpolation====")
print(paste0("row number : ", (row_no-NA_count), "~", (row_no-1), " column number : ", col_no))
flush.console()
value_multi = (value_later - value_prior)/(NA_count+1)
for(Inter in 1:NA_count)
{
train_2[(row_no-NA_count+Inter-1), col_no] = value_prior + value_multi*Inter
}
}
}
}
head(train_2)
summary(train_2[15:19])
train_3 = train_2[is.na(train_2$casual) == 0,]
plot(train_3$month, train_3$temp)
# 파생변수를 만들어보자!
# 습도가 높아도 바람이 많이 불면 나름 쾌적함 ㅇㅇ. 근데 겨울엔 좀 아님.
# 온도, 습도, 풍속을 고려하여 새로운 변수를 만들어보자. (1번)
# 사람들의 활동 시간대를 고려해보자.
# 0시부터 23시 까지 각각의 시각에 자전거를 많이 탈 것 같은 시간에 따라
# 점수를 1점에서 10점까지 매겨봄. 식사시간, 운동시간 등등 고려하여 점수 부여. (2번)
##########################################
# 파생변수명 : factor_x
# 온도, 습도, 풍속을 고려하여 만드는 새로운 변수
# 추가작업 : 그래프 그려보기
ncol(train_3)
train_3[,23] = round(train_3$temp * (train_3$humidity*0.01) * train_3$windspeed, 3)
colnames(train_3) = c(colnames(train_3)[1:22], "factor_x")
head(train_3)
plot(train_3$hour, train_3$factor_x)
plot(train_3$month, train_3$factor_x)
plot(1:nrow(train_3), train_3$factor_x)
##########################################
# 파생변수명 : h_score
# 온도, 습도, 풍속을 고려하여 만드는 새로운 변수
# 추가작업 : 그래프 그려보기
# hour_score = as.data.frame(matrix(c(seq(0,23,1), c( 시간별 점수를 넣어주세요 )),nrow = 24, ncol = 2))
# hour_score = as.data.frame(matrix(c(seq(0,23,1), c( ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, ■, )),nrow = 24, ncol = 2))
hour_score = as.data.frame(matrix(c(seq(0,23,1), c( 1, 1, 1, 1, 3, 2, 4, 5, 2, 6, 7, 8, 3, 8, 9, 8, 7, 6, 3, 4, 5, 8, 4, 2)),nrow = 24, ncol = 2))
colnames(hour_score) = c("hour", "h_score")
head(hour_score)
train_3_score_join = join(train_3, hour_score, by = "hour", type = "left")
head(train_3_score_join)
fix(train_3_score_join)
#install.packages("car")
library("car")
######################################
# 회귀회귀
lm_train = lm(count ~ season +holiday +workingday +weather +temp +atemp +humidity +windspeed +factor_x +h_score, data = train_3_score_join)
summary(lm_train)
vif(lm_train)
lm_train = lm(count ~ season +holiday +workingday +weather +temp +humidity +windspeed +factor_x +h_score, data = train_3_score_join)
summary(lm_train)
vif(lm_train)
######################################
# 알고리즘에 의한 변수 제거
step(lm_train, direction = "both")
lm_train_4 = lm(count ~ season + weather + temp + humidity + windspeed + factor_x + h_score, data = train_3_score_join) # <-- 수식을 입력하세요!
summary(lm_train_4)
vif(lm_train_4)
######################################
# 회귀식으로 예측하기.
# train 데이터로 만든 회귀식으로 test 데이터의 결과를 예측
# test = read.csv("test.csv", header = TRUE)
head(test)
summary(test)
test[,(ncol(test)+1)] = as.numeric(substr(test$date, 12,13))
test[,(ncol(test)+1)] = test$temp * (test$humidity*0.01) * test$windspeed
colnames(test)
colnames(test) = c(colnames(test)[1:9], "hour", "factor_x")
colnames(test)
test_score_join = join(test, hour_score, by = "hour", type = "left")
head(test_score_join)
prediction = predict(lm_train_4, test_score_join)
head(prediction)
prediction = round(prediction,0)
head(prediction)
prediction_cbind = cbind(test$datetime, as.data.frame(prediction))
head(prediction_cbind)
head(sample_submission)
colnames(prediction_cbind) = c("datetime", "count")
head(prediction_cbind)
######################################
# 대망의 제출 파일 만들기!!!
write.csv(prediction_cbind, "submission.csv", row.names = FALSE)
# 제출!!!
# 그리고.. 끝없는 반복...
# 사실 개인적으로 제대로 분석을 한다면?
# 두 개의 모델을 합칠 것.
#
# casual - number of non-registered user rentals initiated
# registered - number of registered user rentals initiated
# count - number of total rentals
#
# count = casual + registered
#
# 즉, casual 값을 예측하기 위한 모델과 registered 값을 예측하기 위한 모델을 따로 만들어서
# 그 결과 값을 더하여 submission 파일을 만들 것.
# 참고
# assign(), get()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment