時間がかかる最も可能性の高い理由は、文字オブジェクトがあるためです。これは、サイズを決定するために文字数をカウントする必要があるためと思われますが、よくわかりません。
x<-rep(paste0(letters[1:3],collapse=""),1e8)
system.time(object.size(x))
## user system elapsed
## 1.608 0.592 2.202
x<-rep(0.5,1e9)
system.time(object.size(x))
## user system elapsed
## 0.000 0.000 0.001
次のように、より長い文字列が (少なくとも場合によっては) より多くのスペースを占めていることがわかります。
> x<-replicate(1e5,paste0(letters[sample(26,3)],collapse=""))
> x1<-replicate(1e5,paste0(letters[sample(26,2)],collapse=""))
> object.size(x)
1547544 bytes
> object.size(x1)
831240 bytes
正確なサイズが必要な場合、これを回避する方法は考えられません。ただし、多数の行をサンプリングobject.size()
し、サンプルを呼び出して行ごとのサイズの見積もりを取得し、行の合計数を掛けることで、サイズの非常に正確な見積もりを得ることができます。
例えば:
estObjectSize<-function(x,n=1e5){
length(x)*object.size(sample(x,n))/n
}
x0<-sapply(1:20,function(x) paste0(letters[1:x],collapse=""))
x<-x0[sample(20,1e8,T)]
> system.time(size<-object.size(x))
user system elapsed
1.632 0.856 2.495
> system.time(estSize<-estObjectSize(x))
user system elapsed
0.012 0.000 0.013
> size
800001184 bytes
> estSize
801184000 bytes
データ フレームで動作させるには、コードを少し調整する必要がありますが、これがアイデアです。
追加するには:文字列の配列を格納するための文字あたりのバイト数は、文字列のインターンや文字列の構築中に使用される余分な割り当てられたバッファメモリなど、いくつかの要因に依存するようです。確かに、文字列の数を掛けるほど単純ではありません。さらに時間がかかることは驚くべきことではありません。
> bytesPerString<-sapply(1:20,
+ function(x)
+ object.size(replicate(1e5,paste0(letters[sample(26,x)],collapse="")))/1e5)
> bytesPerString
[1] 8.01288 8.31240 15.47928 49.87848 55.71144 55.98552 55.99848 64.00040
[9] 64.00040 64.00040 64.00040 64.00040 64.00040 64.00040 64.00040 80.00040
[17] 80.00040 80.00040 80.00040 80.00040
> bytesPerChar<-(bytesPerString-8)/(1:20+1)
> bytesPerChar
[1] 0.0064400 0.1041333 1.8698200 8.3756960 7.9519067 6.8550743 5.9998100
[8] 6.2222667 5.6000400 5.0909455 4.6667000 4.3077231 4.0000286 3.7333600
[15] 3.5000250 4.2353176 4.0000222 3.7894947 3.6000200 3.4285905