Spark學習筆記(19)—— 遊戲日誌分析
阿新 • • 發佈:2018-11-06
1 資料
0 管理員登入
1 首次登入
2 上線
3 下線
1|2016年2月1日,星期一,10:01:08|10.51.4.168|李明剋星|法師|男|1|0|0/800000000 1|2016年2月1日,星期一,10:01:12|10.117.45.20|風道|道士|男|1|0|0/800000000 4|2016年2月1日,星期一,10:01:27|10.51.4.168|李明剋星|法師|男|2|0|0/800000000 4|2016年2月1日,星期一,10:01:30|10.117.45.20|風道|道士|男|2|0|0/800000000 4|2016年2月1日,星期一,10:01:35|10.51.4.168|李明剋星|法師|男|3|0|273/800000000 1|2016年2月1日,星期一,10:01:37|10.171.198.176|主宰|武士|男|1|0|0/800000000 4|2016年2月1日,星期一,10:01:37|10.117.45.20|風道|道士|男|3|0|0/800000000 4|2016年2月1日,星期一,10:01:42|10.51.4.168|李明剋星|法師|男|4|0|538/800000000 4|2016年2月1日,星期一,10:01:45|10.117.45.20|風道|道士|男|4|0|157/800000000 4|2016年2月1日,星期一,10:01:47|10.51.4.168|李明剋星|法師|男|5|0|750/800000000 1|2016年2月1日,星期一,10:01:49|10.168.8.103|潮流哥|法師|男|1|0|0/800000000 4|2016年2月1日,星期一,10:01:54|10.51.4.168|李明剋星|法師|男|6|0|872/800000000 4|2016年2月1日,星期一,10:01:54|10.117.45.20|風道|道士|男|5|0|340/800000000 4|2016年2月1日,星期一,10:02:00|10.51.4.168|李明剋星|法師|男|7|0|987/800000000 4|2016年2月1日,星期一,10:02:01|10.117.45.20|風道|道士|男|6|0|453/800000000 4|2016年2月1日,星期一,10:02:05|10.51.4.168|李明剋星|法師|男|8|0|1243/800000000 4|2016年2月1日,星期一,10:02:06|10.117.45.20|風道|道士|男|7|0|684/800000000 4|2016年2月1日,星期一,10:02:14|10.51.4.168|李明剋星|法師|男|9|0|1375/800000000 4|2016年2月1日,星期一,10:02:16|10.117.45.20|風道|道士|男|8|0|905/800000000 1|2016年2月1日,星期一,10:02:22|10.168.8.103|潮流鍋|武士|男|1|0|0/800000000 4|2016年2月1日,星期一,10:02:23|10.117.45.20|風道|道士|男|9|0|1120/800000000 4|2016年2月1日,星期一,10:02:24|10.51.4.168|李明剋星|法師|男|10|0|1500/800000000 ........
2 程式碼
TimeUtils .scala
package gamelog import java.text.SimpleDateFormat import java.util.Calendar object TimeUtils { val simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") val calendar = Calendar.getInstance() def apply(time: String) = { calendar.setTime(simpleDateFormat.parse(time)) calendar.getTimeInMillis } def getCertainDayTime(amount: Int): Long ={ calendar.add(Calendar.DATE, amount) val time = calendar.getTimeInMillis calendar.add(Calendar.DATE, -amount) time } }
package gamelog
/**
* 事件型別列舉
* 0 管理員登陸
* 1 首次登陸
* 2 上線
* 3 下線
* 4 升級
*/
object EventType {
val REGISTER = "1"
val LOGIN = "2"
val LOGOUT = "3"
val UPGRADE = "4"
}
FilterUtils.scala
package gamelog import org.apache.commons.lang3.time.FastDateFormat object FilterUtils { val dateFormat = FastDateFormat.getInstance("yyyy年MM月dd日,E,HH:mm:ss") def filterByTime(fields: Array[String], startTime: Long, endTime: Long): Boolean = { val time = fields(1) val logTime = dateFormat.parse(time).getTime logTime >= startTime && logTime < endTime } def filterByType(fields: Array[String], evenType: String): Boolean = { val _type = fields(0) evenType == _type } def filterByTypes(fields: Array[String], eventTypes: String*): Boolean = { val _type = fields(0) for(et <- eventTypes){ if(_type==et) return true } false } def filterByTypeAndTime(fields: Array[String], eventType: String, beginTime: Long, endTime: Long): Boolean = { val _type = fields(0) val _time = fields(1) val logTime = dateFormat.parse(_time).getTime eventType == _type && logTime >= beginTime && logTime < endTime } }
2.1 新增使用者
package gamelog
import org.apache.spark.{SparkConf, SparkContext}
object GameKPI {
def main(args: Array[String]): Unit = {
val queryTime = "2016-02-01 00:00:00"
val beginTime = TimeUtils(queryTime)
val endTime = TimeUtils.getCertainDayTime(+1)
val conf = new SparkConf().setAppName("GameKPI").setMaster("local[*]")
val sc = new SparkContext(conf)
//切分後的資料
val splitedLogs = sc.textFile("d://Gamelog.txt").map(_.split("\\|"))
//過濾後並快取
val filteredLogs = splitedLogs.filter(fields => FilterUtils.filterByTime(fields,beginTime,endTime))
.cache()
//日新增使用者
val dnu = filteredLogs.filter(fields => FilterUtils.filterByType(fields,EventType.REGISTER))
.count()
println(dnu)
//
sc.stop()
}
}
2.2 活躍使用者
//Daily Active Users
val dau = filteredLogs.filter(fields => FilterUtils.filterByTypes(fields,EventType.REGISTER,EventType.LOGIN))
.map(_(3))
.distinct()
.count()
println(dau)
sc.stop()
2.3 留存率
// 留存率:某段時間的新增使用者數記為A,經過一段時間後,仍然使用的使用者佔新增使用者A的比例即為留存率
// 次日留存率(Day 1 Retention Ratio) Retention Ratio
// 日新增使用者在+1日登陸的使用者佔新增使用者的比例
val t1 = TimeUtils.getCertainDayTime(-1)
val lastDayRegUser = splitedLogs.filter(fields => FilterUtils.filterByTypeAndTime(fields, EventType.REGISTER, t1, beginTime))
.map(x => (x(3), 1))
val todayLoginUser = filteredLogs.filter(fields => FilterUtils.filterByType(fields, EventType.LOGIN))
.map(x => (x(3), 1))
.distinct()
val d1r: Double = lastDayRegUser.join(todayLoginUser).count()
println(d1r)
val d1rr = d1r / lastDayRegUser.count()
println(d1rr)