如何在R中绘制非常大的数据集?
我想使用箱形图或小提琴情节或类似情节。所有数据都无法放入内存中。我可以逐步读入并计算制作这些图所需的摘要吗?如果是这样的话?
答案 0 :(得分:10)
作为我对Dmitri answer的评论的补充,这是一个使用ff
大数据处理包计算分位数的函数:
ffquantile<-function(ffv,qs=c(0,0.25,0.5,0.75,1),...){
stopifnot(all(qs<=1 & qs>=0))
ffsort(ffv,...)->ffvs
j<-(qs*(length(ffv)-1))+1
jf<-floor(j);ceiling(j)->jc
rowSums(matrix(ffvs[c(jf,jc)],length(qs),2))/2
}
这是一个精确的算法,因此它使用排序 - 因此可能需要花费很多时间。
答案 1 :(得分:8)
问题是你无法将所有数据加载到内存中。所以你可以对数据进行抽样,如前面的@Marek所示。在如此庞大的数据集上,即使只占1%的数据,也可以得到基本相同的结果。对于小提琴情节,这将给你一个不错的密度估计。逐步计算分位数是不可能的,但这应该给出一个非常好的近似值。它基本上与@aix给出的链接中描述的“随机方法”相同。
如果您不能在R之外对日期进行子集化,则可以使用与sample()
组合的连接来完成。以下函数是我用来从文本格式的数据框中采样过大的函数。如果您对连接稍微玩一下,您可以轻松地将其转换为socketConnection或其他从服务器,数据库等中读取它。只需确保以正确的模式打开连接。
好,拿一个简单的.csv文件,然后跟随函数样本得到数据的一小部分:
sample.df <- function(f,n=10000,split=",",p=0.1){
con <- file(f,open="rt",)
on.exit(close(con,type="rt"))
y <- data.frame()
#read header
x <- character(0)
while(length(x)==0){
x <- strsplit(readLines(con,n=1),split)[[1]]
}
Names <- x
#read and process data
repeat{
x <- tryCatch(read.table(con,nrows=n,sep=split),error = function(e) NULL )
if(is.null(x)) {break}
names(x) <- Names
nn <- nrow(x)
id <- sample(1:nn,round(nn*p))
y <- rbind(y,x[id,])
}
rownames(y) <- NULL
return(y)
}
用法示例:
#Make a file
Df <- data.frame(
X1=1:10000,
X2=1:10000,
X3=rep(letters[1:10],1000)
)
write.csv(Df,file="test.txt",row.names=F,quote=F)
# n is number of lines to be read at once, p is the fraction to sample
DF2 <- sample.df("test.txt",n=1000,p=0.2)
str(DF2)
#clean up
unlink("test.txt")
答案 2 :(得分:4)
您还应该查看RSQLite,SQLiteDF,RODBC和biglm软件包。对于大型数据集,可以将数据存储在数据库中,并且只将数据拉入R中。数据库也可以为您进行排序,然后计算排序数据的分位数要简单得多(然后只需使用分位数来绘制数据)
还有hexbin包(bioconductor)用于处理具有非常大的数据集的散点图等价物(可能仍然希望使用数据样本,但可以使用大样本)。
答案 3 :(得分:4)
您可以将数据放入数据库并使用SQL计算分位数。请参阅:http://forge.mysql.com/tools/tool.php?id=149
答案 4 :(得分:3)
箱形图所需要的只是分位数,“胡须”极值和异常值(如果显示),这些都很容易预先计算。看一下boxplot.stats
函数。
答案 5 :(得分:2)
您可以从可管理的数据样本中制作图表。例如。如果您只使用10%随机选择的行,则此样本上的boxplot不应与all-data boxplot不同。
如果您的数据存在于某个数据库中,则可以创建一些随机标记(因为我知道几乎每个数据库引擎都有某种随机数生成器)。
第二件事是你的数据集有多大?对于箱线图,您需要两列:值变量和组变量。这个例子:
N <- 1e6
x <- rnorm(N)
b <- sapply(1:100, function(i) paste(sample(letters,40,TRUE),collapse=""))
g <- factor(sample(b,N,TRUE))
boxplot(x~g)
需要100MB的RAM。如果N=1e7
那么它使用&lt; 1GB的RAM(仍然可以管理现代机器)。
答案 6 :(得分:2)
这是一个有趣的问题。
箱形图需要分位数。在非常大的数据集上计算分位数很棘手。
在您的情况下可能或可能不起作用的最简单的解决方案是首先对数据进行下采样,然后生成样本图。换句话说,一次读取一堆记录,并将其中的一部分保留在内存中(确定性地或随机地选择。)最后,根据已保留在内存中的数据生成绘图。同样,这是否可行在很大程度上取决于数据的属性。
或者,存在能够以“在线”方式经济地和近似地计算分位数的算法,这意味着它们一次呈现一个观察,并且每个观察恰好显示一次。虽然我对这些算法的经验有限,但我还没有看到任何现成的R实现。以下文章简要介绍了一些相关算法:Quantiles on Streams。
答案 7 :(得分:0)
也许您可以考虑在运行绘图之前先使用disk.frame
对数据进行汇总?