EDIT: Код, который я скопировал, не был конечной функцией, поэтому в нем были ошибки.Исправлены ошибки.
Я не совсем согласен с голосами, чтобы закрыть, но ваш вопрос нуждается в чтении.Как я понял, проблема в представлении даты.Числовые это просто сумасшедшая идея, в этом случае используйте целое число.Так же, как обзор различных форматов и их относительного пространства (используя функцию lsos из , этот вопрос :)
Dates <- rep(seq.Date(as.Date("2010-04-01"),
as.Date("2011-04-01"),by='day'),each=100)
chardates <- as.character(Dates)
POSIXctDates <- as.POSIXct(Dates)
POSIXltDates <- as.POSIXlt(Dates)
integerDates <- as.integer(Dates)
chronDates <- as.chron(Dates)
numericDates <- as.numeric(Dates)
> lsos()
Type Size PrettySize Rows Columns
POSIXltDates POSIXlt 1464976 1.4 Mb 36600 NA
chronDates dates 293400 286.5 Kb 36600 NA
POSIXctDates POSIXct 292976 286.1 Kb 36600 NA
Dates Date 292944 286.1 Kb 36600 NA
numericDates numeric 292824 286 Kb 36600 NA
charDates character 161064 157.3 Kb 36600 NA
integerDates integer 146424 143 Kb 36600 NA
Внутренний Date
может довольно хорошо конкурировать с числовым представлением,character
вызывает проблемы со всей остальной функциональностью, поэтому забудьте об этом.Я просто использую Date
, это будет делать и сохраняет функциональность в порядке.Обратите внимание на размер POSIXlt
: все функции для извлечения месяцев, недель, дня года и т. Д. Работают в этом формате.Это верно для format()
и для функций weekdays()
, months()
, ... в пакете base
или chron
.
Некоторые замечания:
- В Vista теоретический предел 3Gb на машине с 4Gb.Вы пробовали
memory.limit(3000)
: См. ?memory.limit
. - Пожалуйста, обновите как можно скорее до Windows 7, если вам что-нибудь нужно для достойного управления памятью.Виста просто отстой.Долгое время.Если возможно, получите 64-битный компьютер, если вы работаете с этими данными.
- Периодически очищайте рабочее пространство .Я могу без проблем запустить ваш код на 32-битной R с ограничением памяти 2 Гб на приведенном ниже кадре данных (14+ миллионов строк).
На ваш код.Я работаю с форматом Date
, размер которого примерно равен числовому формату.Давайте попробуем это со следующими данными (которые вы могли бы предоставить ...) с 14,6 миллионами строк.Я использую Windows7 (64-битную) с общей памятью 4 ГБ.
n <- 40000
tr <- data.frame(
customer_id = rep(1:366,n),
visit_date = rep(seq.Date(as.Date("2010-04-01"),
as.Date("2011-04-01"),by='day'),each=n),
visit_spend =runif(366*n,3,12)
)
Сначала ваша недельная функция.Как уже говорилось, функция format
использует базовый формат POSIXlt, который, как показано, требует большого объема памяти.Тем не менее, вы можете вырезать около половины памяти, просто обращаясь к ней напрямую (см. ?POSIXlt
).Он возвращает целые числа, которые занимают примерно половину памяти возвращаемых вами чисел:
dayofweek2 <- function(dt) {
as.POSIXlt(dt)$wday
}
monthofyear2 <- function(dt){
as.POSIXlt(dt)$mon +1L
}
weekofyear2 <- function(dt) {
n <- length(dt)
lt <- as.POSIXlt(dt)
yearstart <- c(0,which(diff(lt$year)!=0))
fday <- rep(lt[yearstart+1L]$wday,
diff(c(yearstart,n)+1L)
)
as.integer((lt$yday+fday-1L)%/%7)
}
> lsos()
Type Size PrettySize Rows Columns
tr data.frame 733128 715.9 Kb 36600 3
Dates Date 293048 286.2 Kb 36600 NA
x1 numeric 292840 286 Kb 36600 NA # from your function
x2 integer 146440 143 Kb 36600 NA # from my function
Если вам нужно еще меньше, вам придется делать математику самостоятельно.Но я советую вам не испытывать это и определенно не основываться на представлении персонажа.Строковые операции, такие как strsplit()
и substr()
, наверняка разрушат вашу память.Как и функция month.day.year()
пакета chron
. Держитесь подальше от chron
с большими данными.Фактически, независимо от огромного пространства, необходимого объектам POSIXlt, использование POSIXlt по-прежнему является лучшим вариантом для извлечения памяти.
На aggregate
.Это предназначено для фреймов данных, и, следовательно, aggregate
вызов снова делает много копий данных.Делая вызов более вручную, можно снова сохранить копии.Предложение для функции:
my.agg <- function(x,d,AGGFUN=NULL,FUN="sum"){
FUN <- match.fun(FUN)
if(!is.null(AGGFUN)) {
AGGFUN <- match.fun(AGGFUN)
d <- AGGFUN(d)
}
ud <- sort(unique(d))
xout <- sapply(ud,function(i){
id <- which(d==i) # find which values respond to a certain value of d
FUN(x[id]) # apply the function to only those values
},USE.NAMES=FALSE)
data.frame(d=ud,x=xout)
}
Теперь, если мы применим это и посмотрим использование памяти:
gc(TRUE,reset=TRUE)
x1 <- aggregate(tr$visit_spend,
list('weekofyear'=weekofyear(tr$visit_date)), FUN="sum")
rm(x1)
gc(TRUE,reset=TRUE)
Sys.sleep(5)
x2 <- my.agg(tr$visit_spend,tr$visit_date,weekofyear2,sum)
gc(TRUE,reset=TRUE)
, я получу следующий результат:
Красный квадрат - ваш совокупный вызов, желтый квадрат - мое предложение.Первым ударом в использовании памяти вашего совокупного вызова является функция weekofyear
, которую вы используете.Мое предложение экономит как на использовании памяти weekofyear
, так и на вызове aggregate
, и работает также немного быстрее.Я никогда не получал более 2,6 ГБ общей памяти, используя мое предложение.
Надеюсь, это поможет.