我一直在研究Marchi和Albert的“用R分析棒球数据”这本书,我想知道他们没有解决的问题。
我需要导入的许多数据集相当大(虽然在“大数据”意义上并不是真正的“大”)。例如,Retrosheet Game Logs每年有1个csv文件可追溯到1871年,其中每个文件对于当年玩的每个游戏都有一行,以及161列。当我使用read.csv()
使用stringsAsFactors
上的默认设置将其读入数据框时,161列中的75个成为因子。其中一些列在概念上是因素(例如一个包含"D"
或"N"
白天或夜晚游戏的因素)但其他列可能更好地保留为字符串(许多列包含起始投手,闭门器,我知道如何将列从因子转换为字符串,反之亦然,但我不想扫描161列,明确决定其中的75列。
我认为重要的原因是我注意到,由于需要保留全部因子信息,因此通过对这些游戏日志进行子集化获得的小型数据帧非常大。例如,给定从下载,解压缩和文件读取中获得的数据帧GL2016
,object.size(GL2016)
大约为2.8 MB,当我使用时:
df <- with(GL2016,GL2016[V7 == "CLE" & V13 == "D",])
为了提取2016年克利夫兰印第安人队的主场比赛,我获得了26排的df。 26/2428(其中2428是整个数据帧中的行数)略高于1%,但object.size(df)
约为1.3 MB,远远超过GL2016
大小的1%
我想出了一个临时解决方案。我首先定义了一个函数:
big.factor <- function(v,k){is.factor(v) && length(levels(v)) > k}
然后使用来自mutate_if
的{{1}}:
dplyr
30是MLB中的球队数量,我有点随意决定任何超过30个等级的因素应该被视为一个字符串。
在运行此代码之后,因子变量的数量已从75减少到12.它的工作原理即使现在GL2016 %>% mutate_if(function(v){big.factor(v,30)},as.character) -> GL2016
大约为3.2 MB(比之前略大),如果我现在将数据框子集推出克利夫兰日游戏,结果数据帧只有0.1 MB。
问题:
1)在导入大型数据集时,决定哪些字符列应转换为因子是什么标准(希望不如我上面所使用的那样)?
2)我知道将所有字符数据转换为因子的内存占用成本,但是当我将大部分这些因素转换回字符串时,我是否会产生任何隐藏成本(例如处理时间)?
答案 0 :(得分:1)
基本上,我认为你需要做的是:
df <- with(GL2016,GL2016[V7 == "CLE" & V13 == "D",])
df <- droplevels(df)
droplevels
函数会删除所有未使用的因子级别,从而极大地减小df
的大小。