目录

RStudio
R语言的好处
在做Teamfight Tactics分析时,我先通过Riot’s API收集到了许多场次的对局数据。如何将这些复杂的数据转换成可以直接使用的数据,方便进行分析呢?
之前一直用的是Python,思路是通过pymongo包连接MongoDB提取数据,再通过python内建函数进行转换和分析。这样需要不停使用Table["sub"]['subsub']这样的格式取得内部结构。这部分内容没有代码提示,需要程序员自行记忆每个Key对应的结构,不仅麻烦,而且容易出错。可以预计分析数据的时候会用到大量循环,而python的效率让人缺乏信心。再加上后续还有画图步骤,而matplotlib是一个非常麻烦的东西,我有点害怕。
也考虑过使用Matlab,它的好处是不少循环可以转为向量化运算,速度会快不少,而且画图容易。Matlab的附加功能里有一个Database Toolbox Interface for MongoDB。我甚至已经使用它进行了一段时间分析了,但后面发现默认生成的.mat格式转换为其他格式比较困难。而且运行速度也不是很理想,消耗资源很大,400MB的数据量在运算时常常卡死我的电脑。也可能是因为我不常使用它,所有代码本身编写的也不够好。
最后终于接触到了R语言,这真是个好工具。配合RStudio,顺手又高效。它解决了上面的所有问题,而且内建和社区的函数和包为分析过程提供了很大帮助,为我节省了很多时间。它的一些用法和其他语言显得有些奇怪,理解和熟悉需要一些时间,但R语言的学习绝对物超所值。
李东风老师的开源R语言教程很好,推荐一下:https://www.math.pku.edu.cn/teachers/lidf/docs/Rbook/html/_Rbook/index.html
R语言的数据类型
向量
向量是将若干个基础类型相同的值存储在一起,各个元素可以按序号访问。需要注意的是,R语言各种类型的数据结构的下标都是从1开始的。例如
# 数值型
marks <- c(10, 6, 4, 7, 8)
x <- c(1:3, 10:13)
# 逻辑型
c(1, 3, 5) > 2 # [1] FALSE TRUE TRUE
# 字符型
s1 <- c('abc', '', 'a cat', NA, '李明')
内建的大多数函数以向量为参数时,会对向量内的元素逐个运算,然后返回一个和原来一样长的向量。
sqrt(c(1, 4, 6.25)) # [1] 1.0 2.0 2.5
x <- c(33, 55, 11)
order(x) # [1] 3 1 2
x[order(x)] # [1] 11 33 55
列表
R中列表(list)类型来保存不同类型的数据。一个主要目的是提供R分析结果输出包装:输出一个变量,这个变量包括回归系数、预测值、残差、检验结果等等一系列不能放到规则形状数据结构中的内容。实际上,数据框也是列表的一种,但是数据框要求各列等长,而列表不要求。
列表可以命名,命名后类似字典,可以通过名字访问。
rec <- list(name="李明", age=30,
scores=c(85, 76, 90))
rec
## $name
## [1] "李明"
##
## $age
## [1] 30
##
## $scores
## [1] 85 76 90
rec$age # 或 rec[["age"]]
也可以通过下标访问,但需要两重中括号。如果使用单重方括号对列表取子集,结果还是列表而不是列表元素。
rec[[3]]
## [1] 85 76 90
rec[[3]][2]
## [1] 76
rec[3]
## $scores
## [1] 85 76 90
要删除某个元素,直接将该元素赋值为NULL;添加元素则是直接为该元素赋值。
rec[["age"]] <- NULL
rec[["身高"]] <- 178
## $name
## [1] "李明"
##
## $三科分数
## [1] 85 0 90
##
## $身高
## [1] 178
数据框
数据框类似于数据库表或Excel数据表的形式。这样形式的数据在R中叫做数据框(data.frame)。数据框类似于一个矩阵,有$n$个横行、$p$个纵列,但各列允许有不同类型:数值型向量、因子、字符型向量、日期时间向量。同一列的数据类型相同。数据框是一个特殊的列表,其每个列表元素都是一个长度相同的向量。
数据框可以说是处理数据的最佳方式,利用它可以轻松按列或按行取值,并且可以直接用向量化的方式计算。
d<-data.frame(TraitsComb=character(0),Top4=double(0),Winner=double(0),AvgPlacement=double(0),PickTimes=integer(0))
print(d)
## [1] TraitsComb Top4 Winner AvgPlacement PickTimes
## <0 行> (或0-长度的row.names)
d[1,]<-list("a", 1.2, 2.3, 3.4, 5)
print(d)
## TraitsComb Top4 Winner AvgPlacement PickTimes
## 1 a 1.2 2.3 3.4 5
colnames(d)
## [1] "TraitsComb" "Top4" "Winner" "AvgPlacement" "PickTimes"
d$Winner
## [1] 2.3
d[3]
## Winner
## 1 2.3
d[3][1]
## Winner
## 1 2.3
R语言函数
字符串
观察下面的例子,只用了1行代码就实现了我想要的字符串拼接。
tiers<-rev(c("DIAMOND","PLATINUM","GOLD","SILVER","BRONZE","IRON"))
ranks<-rev(c("I","II","III","IV","V"))
tire_order<-lapply(tiers,function(x) paste(x,ranks,sep="-")) %>% unlist
## [1] "IRON-V" "IRON-IV" "IRON-III" "IRON-II" "IRON-I" "BRONZE-V"
## [7] "BRONZE-IV" "BRONZE-III" "BRONZE-II" "BRONZE-I" "SILVER-V" "SILVER-IV"
## [13] "SILVER-III" "SILVER-II" "SILVER-I" "GOLD-V" "GOLD-IV" "GOLD-III"
## [19] "GOLD-II" "GOLD-I" "PLATINUM-V" "PLATINUM-IV" "PLATINUM-III" "PLATINUM-II"
## [25] "PLATINUM-I" "DIAMOND-V" "DIAMOND-IV" "DIAMOND-III" "DIAMOND-II" "DIAMOND-I"
这里lapply是对列表遍历,将每个元素先赋值为x,然后应用function(x)函数。paste函数是将两个参数连接起来,sep是连接符。
%>%是一个pipe,它将结果传递给另一个函数作为第一个参数。unlist是将列表转换为向量。
排序
对一张以下格式的数据框排序,可以使用order函数。倒序只需要在排序的列名前加-号。
head(traits_comp_discribe)
## TraitsComb Top4 Winner AvgPlacement PickTimes
## 1 Transformer 0.253 0.025 5.696 79
## 2 Bruiser,Cuddly,Glutton,Sister,Transformer 0.922 0.314 2.373 51
## 3 Arcanist,Cuddly 0.662 0.166 3.593 145
## 4 Socialite 0.217 0.024 6.133 83
## 5 Chemtech,Twinshot 0.462 0.154 4.231 13
## 6 Clockwork,Cuddly,Transformer 0.750 0.250 3.875 8
head(traits_comp_discribe[order(-traits_comp_discribe$Top4),])
## TraitsComb Top4 Winner AvgPlacement PickTimes
## 7 Academy,Cuddly,Imperial 1 0.500 3.000 4
## 11 Bruiser,Sister,Socialite 1 0.400 6.400 5
## 32 Cuddly,Glutton,Sister,Socialite 1 0.333 2.000 3
## 34 Mercenary 1 0.071 7.286 14
## 37 Bruiser,Sister,Transformer,Twinshot 1 0.333 3.000 3
## 38 Bodyguard,Cuddly,Syndicate 1 0.250 3.500 4
MongoDB
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富却最像关系数据库的。它提供了一个非常简单的接口,可以让你在简单的程序中操作数据库。
在R语言中,连接MongoDB可以使用mongolite库
install.packages("mongolite")
library(mongolite)
url <- "mongodb://user:pass@site:port"
db<- "tft" # 数据库名
# 连接数据库
s_con <- mongo(collection='summoner',
db=db,
url=url)
# 查询数据 (查询等级低于100的召唤师)
summoners <- s_con$find('{"summonerlevel": { "$lt": 100 }}')
head(summoners)
## id puuid summonerlevel summonertire summonerrank
## 1 4 ******** 66 PLATINUM I
## 2 5 ******** 1 DIAMOND II
## 3 6 ******** 85 MASTER I
## 4 8 ******** 1 PLATINUM IV
## 5 9 ******** 20 PLATINUM II
## 6 12 ******** 19 PLATINUM II
评论