阿里大数据 - 中国好大学

  最近阿里巴巴办了个数据挖掘竞赛-阿里巴巴大数据竞赛,题目是根据天猫用户4个月的行为记录来预测用户下一个月会买什么东西,参赛对象为高校在校学生。由于奖金数额十分巨大,因此比赛规模可以说是空前绝后的,短短2周就有4000多支队伍报名。比赛过程中,每队每周可以提交一次结果,组委会每周日统一计算各队的分数并公布排行榜(top 500)。

  噢,忘了说了这篇文章是关于R语言抓数据以及画图的,与比赛木有关系。本篇的内容纯粹just for fun,不具任何实际价值。是对我最近在cos.name上混来的一些R语言技巧的复习。

  好了继续。当然我也参加了比赛,但是很不幸第二周就被挤了出来,于是乎对着这个top 500看了好久,想了好久,睡了好久……

  由于参赛队员都是在校学生,而且又是规模空前,几乎全国稍微有点名气的学校都参加了,那么这些学校的表现如何呢?一所大学的综合排名能否很好的表现在比赛中呢?这次的文章就在尝试能否用数据来帮助理解前面这些问题。

  首先我们需要获取这份榜单,地址是:
  http://102.alibaba.com/competition/addDiscovery/totalRank.htm
  打开发现每页只能显示20支队伍,一共25页。一开始的想法是利用R的XML包,读取HTML TABLE,但是点击第2页的时候,发现网址居然是不会变化的,因此就没有办法根据网址一页一页下载下来。怀疑应该是在你点击下一页的时候,通过一个API获取下一页的信息,再利用javascript来更新表格。

  此时派chrome上场,在页面上点右键-审查元素,打开develop tools:

  选择Network,然后在排行榜的页面庄重的点”下一页”。然后developer tools就会抓到刚刚点了“下一页”之后发生的http请求。

  http://102.alibaba.com/competition/addDiscovery/queryTotalRank.json 就是网页获取排名数据的API了,使用POST方法,带上pageIndex以及pageSize两个参数,就可以获取排名信息。接下来就要请RCurl上场了。

1
2
3
library(RCurl)
library(rjson)
library(plyr)
1
2
3
4
5
6
7
8
9
10
api <- "http://102.alibaba.com/competition/addDiscovery/queryTotalRank.json"
# 发现其实可以抓到所有队伍的排名,不止是top 500,把pageSize设很大就行了
result <- postForm(api, pageIndex = 1, pageSize = 5000)
resjson <- fromJSON(result)
ranks <- (resjson$returnValue$datas)
leaderBoard <- ldply(ranks, unlist)
leaderBoard <- leaderBoard[, c("rank", "teamName", "university", "score", "dateString")]
leaderBoard$score <- as.numeric(leaderBoard$score)
leaderBoard$rank <- as.integer(leaderBoard$rank)
head(leaderBoard)
teamName university score dateString
1 cucyyyy 中国传媒大学 0.0717 2014-03-23
2 花莲 南京大学 0.0694 2014-03-23
3 CUCkdd 中国传媒大学 0.0692 2014-03-23
4 WYZ 清华大学 0.0685 2014-03-23
5 車輪戦 哈尔滨工业大学 0.0684 2014-03-16

  先来看看各个学校都有多少队参加比赛。

1
2
3
4
library(ggplot2)
# 因为这次想用刚学的ggplot2画图,这里设定下ggplot2的全局参数,
# 把字体设为宋体,以正常显示中文
theme_set(theme_grey(base_family = "Songti SC", base_size = 15))
1
2
3
4
5
6
7
8
school_summary <- ddply(leaderBoard, .(university), function(x) c(num_teams=nrow(x)))
school_summary <- school_summary[order(school_summary$num_teams,decreasing=T),]
school_summary$university <- factor(school_summary$university,levels=school_summary$university)
ggplot(school_summary[1:10,], aes(x=university, y=num_teams)) +
geom_bar(stat="identity", fill="steelblue") +
geom_text(aes(label=num_teams, vjust=-.3)) +
labs(title="参赛队伍数最多的10所大学\n",x="",y="参赛队伍数") +
theme(axis.text=element_text(size=14,angle=20))

  看来浙大很具主场优势啊,中科院也是来势汹汹。这里参赛队伍数是报名并且成功提交过结果的队伍数,截止3.23凌晨,共有1383队提交过结果。

  那么如何衡量学校的表现呢?先来看看哪些学校的牛人最牛。我这里用的方法是计算每个学校最强的5支队伍的平均分数。

1
2
3
4
5
6
7
8
9
10
mean_top5 <- ddply(leaderBoard,.(university), function(x){
scores <- x$score
scores <- scores[order(scores,decreasing=T)]
c(average=mean(scores[1:5],na.rm=T),
num_teams=nrow(x))
})
mean_top5 <- mean_top5[order(mean_top5$average,decreasing=T),]
mean_top5 <- mean_top5[mean_top5$num_team >= 5,]
rownames(mean_top5) <- 1:nrow(mean_top5)
mean_top5

  为了减少极端值的影响,这里把参赛队伍数少于5的学校给过滤掉了。

      根据每个学校前5名平均分排序

university average num_teams
1 哈尔滨工业大学 0.0662 45
2 浙江大学 0.0661 97
3 清华大学 0.0651 37
4 南京大学 0.0645 40
5 中国科学院大学 0.0645 76
6 中国科学技术大学 0.0643 47
7 北京邮电大学 0.0639 87
8 北京理工大学 0.0628 25
9 华中师范大学 0.0623 10
10 北京航空航天大学 0.0622 22
11 北京大学 0.0620 39
12 电子科技大学 0.0619 56
13 西南交通大学 0.0613 11
14 大连理工大学 0.0604 19
15 西安电子科技大学 0.0600 37
16 中山大学 0.0597 35
17 华南理工大学 0.0591 28
18 山东大学 0.0590 14
19 武汉大学 0.0588 19
20 香港科技大学 0.0574 15
21 东南大学 0.0571 27
22 中国人民大学 0.0570 9
23 厦门大学 0.0569 15
24 华东师范大学 0.0565 14
25 上海交通大学 0.0565 20
26 华中科技大学 0.0562 35
27 东北大学 0.0559 17
28 同济大学 0.0557 15
29 复旦大学 0.0530 25
30 南开大学 0.0520 11
31 天津大学 0.0498 12
32 西安交通大学 0.0480 12
33 东华大学 0.0467 11
34 广东工业大学 0.0460 8
35 北京交通大学 0.0459 7
36 北京师范大学 0.0459 6
37 湖南大学 0.0450 6
38 南京邮电大学 0.0440 8
39 西北农林科技大学 0.0430 5
40 西北工业大学 0.0426 8
41 南京航空航天大学 0.0413 6
42 中国科学院软件研究所 0.0403 5
43 燕山大学 0.0378 5
44 吉林大学 0.0366 6
45 北京工业大学 0.0358 5
46 哈尔滨工业大学(威海) 0.0356 6
47 中南大学 0.0315 6
48 浙江工商大学 0.0283 5
49 四川大学 0.0267 6
50 武汉理工大学 0.0209 6
51 福建师范大学 0.0041 5

  上面的学校排名符合您心目中的预期吗?

  那么如何去衡量一个学校所有队伍的综合表现呢?当分数的分布有偏的时候,不太好直接使用全部队伍得分的平均数来对比两个学校的表现,而且各个学校参赛队伍数差异很大。中位数是个不错的衡量指标,但它会忽略这个学校最强和最弱的这两群学生。

  一个比较直觉的想法是,如果这个学校所有队伍的排名整体比较靠前,则该学校整体实力较强。如果这个学校所有队伍的排名整体比较靠后,则该学校整体实力较弱。

  这里可以拿两所学校做个对比。为何会选这两所学校呢?很简单,博主来自于厦大,另外下面那所学校是随机挑的。

1
2
3
4
5
6
tsinghua <- leaderBoard[leaderBoard$university=="清华大学",]
xmu <- leaderBoard[leaderBoard$university=="厦门大学",]
ggplot(rbind(tsinghua,xmu),aes(rank,fill=university)) +
geom_density(color="transparent",alpha=0.5) +
labs(x="名次",y="密度",title="两个学校名次分布对比\n") +
facet_grid(university~.)

  两个学校的整体实力很容易就能看出来了。清华大学的队大部分集中在前500名,表现较好。

  另外还想到的就是可能可以利用ROC曲线来衡量一个学校的整体表现。关于ROC的具体介绍,可以看这里。继续以清华为例子,画出它的ROC曲线。

1
library(ROCR)
1
2
3
4
5
6
7
8
9
10
11
probs <- seq(1,0,length.out=nrow(leaderBoard))
labels <- rep(0,nrow(leaderBoard))
labels[tsinghua$rank] = 1
pred <- prediction(probs ,labels)
perf <- performance(pred,"tpr","fpr")
perf <- data.frame(FPR = perf@x.values[[1]], TPR = perf@y.values[[1]])
ggplot(perf, aes(FPR,TPR)) +
labs(title="ROC Curve\n") +
geom_density(stat="identity",
fill="steelblue",
color="transparent",alpha=0.6)

  这个ROC曲线下的面积成为AUC (area under curve),该部分面积越大,代表整体排名越前。可以利用ROCR包很容易的计算出AUC:

1
performance(pred,"auc")@y.values[[1]]
1
## [1] 0.6233

  AUC的值超过0.5,说明该校整体表现高于平均水准;小于0.5,说明整体表现低于平均水准。

  写一个function来计算所有学校的AUC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
auc <- function(ranks, n) {
probs <- seq(1, 0, length.out = n)
labels <- rep(0, n)
labels[ranks] <- 1
pred <- prediction(probs, labels)
perf <- performance(pred, "auc")
perf@y.values[[1]]
}
auc_leaderboard <- ddply(leaderBoard, .(university), function(x) {
c(auc = auc(x$rank, nrow(leaderBoard)), num_teams = nrow(x))
})
auc_leaderboard <- auc_leaderboard[order(auc_leaderboard$auc, decreasing = T), ]
auc_leaderboard <- auc_leaderboard[auc_leaderboard$num_teams >= 8, ]
rownames(auc_leaderboard) <- 1:nrow(auc_leaderboard)
auc_leaderboard

      根据AUC排序的榜单

university auc num_teams
1 西南交通大学 0.7116 11
2 华中师范大学 0.7084 10
3 中国人民大学 0.6417 9
4 清华大学 0.6233 37
5 香港科技大学 0.6228 15
6 北京航空航天大学 0.6092 22
7 东北大学 0.6062 17
8 华东师范大学 0.5975 14
9 中国科学技术大学 0.5848 47
10 北京大学 0.5785 39
11 武汉大学 0.5680 19
12 北京理工大学 0.5594 25
13 北京邮电大学 0.5489 87
14 浙江大学 0.5391 97
15 西北工业大学 0.5118 8
16 哈尔滨工业大学 0.5106 45
17 广东工业大学 0.5073 8
18 上海交通大学 0.5047 20
19 大连理工大学 0.5006 19
20 南京大学 0.4901 40
21 同济大学 0.4881 15
22 厦门大学 0.4865 15
23 南开大学 0.4817 11
24 电子科技大学 0.4809 56
25 东南大学 0.4769 27
26 中国科学院大学 0.4751 76
27 中山大学 0.4747 35
28 南京邮电大学 0.4724 8
29 天津大学 0.4632 12
30 山东大学 0.4617 14
31 东华大学 0.4585 11
32 西安交通大学 0.4277 12
33 复旦大学 0.4062 25
34 西安电子科技大学 0.4049 37
35 华南理工大学 0.4048 28
36 华中科技大学 0.3995 35

  上面的学校排名有更符合您心目中的预期吗?

喜欢就分享一下吧