Обход R 'Ошибка в if (nbins> .Machine $ integer.max) ` - PullRequest
1 голос
/ 02 апреля 2011

Это сага, которая началась с проблемы как сделать взвешивание опроса . Теперь, когда мне кажется, что я делаю это правильно, я наткнулся на небольшую стену (подробности процесса импорта и откуда взялась переменная strata см. В предыдущем посте):

> require(foreign)
> ipums <- read.dta('/path/to/data.dta')
> require(survey)
> ipums.design <- svydesign(id=~serial, strata=~strata, data=ipums, weights=perwt)
Error in if (nbins > .Machine$integer.max) stop("attempt to make a table with >= 2^31 elements") : 
  missing value where TRUE/FALSE needed
In addition: Warning messages:
1: In pd * (as.integer(cat) - 1L) : NAs produced by integer overflow
2: In pd * nl : NAs produced by integer overflow
> traceback()
9: tabulate(bin, pd)
8: as.vector(data)
7: array(tabulate(bin, pd), dims, dimnames = dn)
6: table(ids[, 1], strata[, 1])
5: inherits(x, "data.frame")
4: is.data.frame(x)
3: rowSums(table(ids[, 1], strata[, 1]) > 0)
2: svydesign.default(id = ~serial, weights = ~perwt, strata = ~strata, 
       data = ipums)
1: svydesign(id = ~serial, weights = ~perwt, strata = ~strata, data = ipums)

Эта ошибка, похоже, происходит от функции tabulate, которая, как я надеялся, будет достаточно простой, чтобы обойти, сначала изменив .Machine$integer.max

> .Machine$integer.max <- 2^40

и когда это не сработало, весь исходный код tabulate:

> tabulate <- function(bin, nbins = max(1L, bin, na.rm=TRUE))
{
    if(!is.numeric(bin) && !is.factor(bin))
    stop("'bin' must be numeric or a factor")
    #if (nbins > .Machine$integer.max)
    if (nbins > 2^40) #replacement line
        stop("attempt to make a table with >= 2^31 elements")
    .C("R_tabulate",
       as.integer(bin),
       as.integer(length(bin)),
       as.integer(nbins),
       ans = integer(nbins),
       NAOK = TRUE,
       PACKAGE="base")$ans
}

Никто не обошел проблему. Очевидно, это одна из причин, по которой был создан пакет ff, но меня беспокоит то, в какой степени это проблема, которую я не могу избежать в R. Этот пост , кажется, указывает на то, что даже если бы я использовал пакет, который бы избежал этой проблемы, я был бы в состоянии получить доступ только к 2 ^ 31 элементам одновременно. Я надеялся использовать sql (или sqlite или postgresql), чтобы обойти проблемы с памятью, но я боюсь, что потрачу некоторое время, чтобы заставить это работать, только чтобы достичь того же фундаментального предела.

Попытка вернуться к Stata также не решает проблему. Снова смотрите предыдущий пост о том, как я использую svyset, но вычисление, которое я хотел бы выполнить, приводит к зависанию Stata:

svy: mean age, over(strata)

Решит ли вопрос, что потратить больше памяти, я не знаю. Я запускаю R на своем рабочем столе, который имеет 16 гигабайт, и использую Stata через сервер Windows, в настоящее время устанавливая выделение памяти на 2000 МБ, но я теоретически мог бы поэкспериментировать с его увеличением.

Итак, в сумме:

  1. Это жесткий предел в R?
  2. Решит ли sql мои R проблемы?
  3. Если я разделю его на множество отдельных файлов, это исправит это (много работы ...)?
  4. Будет ли выбрасывать много памяти при Stata сделать это?
  5. Я серьезно как-то лаю не на том дереве?

Ответы [ 3 ]

2 голосов
/ 02 апреля 2011
  1. Да, R использует 32-битные индексы для векторов, поэтому они могут содержать не более 2 ^ 31-1 записей, и вы пытаетесь создать что-то с 2 ^ 40. Говорят о введении 64-битных индексов, но до появления в R. это будет несколько раньше. Векторы имеют установленный жесткий предел, и это касается базовой базы R.

Я не знаком с деталями того, что вы делаете, чтобы дать какие-либо дальнейшие советы по другим частям вашего вопроса.

Почему вы хотите работать с полным набором данных? Разве меньший образец, который может вписаться в ограничения R мест на вас, не будет столь же полезным? Вы можете использовать SQL для хранения всех данных и запросить их у R, чтобы получить случайное подмножество более подходящего размера.

0 голосов
/ 12 сентября 2016

Так как этот вопрос был задан некоторое время назад, я хотел бы отметить, что мой ответ здесь использует версию 3.3 пакета survey.

Если вы проверите код svydesign,, вы увидите, что функция, которая вызывает все проблемы, находится внутри шага проверки, который проверяет, следует ли установить для параметра nest значение ИСТИНА или нет. Этот шаг можно отключить, установив параметр check.strata=FALSE.

Конечно, вы не должны отключать шаг проверки, если не знаете, что делаете. В этом случае вы сможете сами решить, нужно ли установить для параметра nest значение TRUE или FALSE. nest должен быть установлен в ИСТИНА, когда один и тот же идентификатор блока питания (кластера) перерабатывается в разных слоях.

Конкретно для набора данных IPUMS, поскольку вы используете переменную serial для идентификации кластера, а serial уникален для каждого домохозяйства в данной выборке, вы можете установить nest в FALSE.

Итак, ваша линия дизайна опроса будет:

ipums.design <- svydesign(id=~serial, strata=~strata, data=ipums, weights=perwt, check.strata=FALSE, nest=FALSE)

Дополнительный совет: даже после обхода этой проблемы вы обнаружите, что код работает довольно медленно, если вы не перенастроите страты на диапазон от 1 до length(unique(ipums$strata)):

ipums$strata <- match(ipums$strata,unique(ipums$strata))
0 голосов
/ 06 апреля 2011

И @Gavin, и @Martin заслуживают похвалы за этот ответ или, по крайней мере, ведут меня в правильном направлении. В основном я отвечаю на него отдельно, чтобы его было легче читать.

В порядке, который я спросил:

  1. Да, 2 ^ 31 является жестким ограничением в R, хотя, кажется, имеет значение, какой это тип (что немного странно, учитывая, что это длина вектора, скорее чем объем памяти (которой у меня много), которая является заявленной проблемой. не конвертируйте strata или id переменные в factors, которые просто исправят их длину и сведут на нет эффекты подмножества (что является способом обойти эту проблему).

  2. sql, вероятно, может помочь, если я научусь правильно его использовать. Я сделал следующий тест:

    library(multicore) # make svy fast!
    ri.ny <- subset(ipums, statefips_num %in% c(36, 44))
    ri.ny.design <- svydesign(id=~serial, weights=~perwt, strata=~strata, data=ri.ny)
    svyby(~incwage, ~strata, ri.ny.design, svymean, data=ri.ny, na.rm=TRUE, multicore=TRUE)
    
    ri <- subset(ri.ny, statefips_num==44)
    ri.design <- svydesign(id=~serial, weights=~perwt, strata=~strata, data=ri)
    ri.mean <- svymean(~incwage, ri.design, data=ri, na.rm=TRUE)
    
    ny <- subset(ri.ny, statefips_num==36)
    ny.design <- svydesign(id=~serial, weights=~perwt, strata=~strata, data=ny)
    ny.mean <- svymean(~incwage, ny.design, data=ny, na.rm=TRUE, multicore=TRUE)
    

    И нашел средства одинаковыми, что кажется разумным испытанием.

    Итак: теоретически, если я могу разделить вычисления, используя plyr или sql, результаты все равно должны быть в порядке.

  3. См. 2.

  4. Сброс большого количества памяти на Stata определенно помогает, но теперь я сталкиваюсь с досадными проблемами форматирования. Кажется, я могу выполнить большую часть необходимых мне вычислений (гораздо быстрее и с большей стабильностью), но я не могу понять, как привести их в нужную форму. Наверное, задам отдельный вопрос по этому вопросу. Я думаю, что короткая версия заключается в том, что для больших данных опроса Stata намного лучше из коробки.

  5. Во многих отношениях да. Попытки провести анализ с такими большими данными - это не то, что я должен был бы принять слегка, и я далек от того, чтобы понять это даже сейчас. Я правильно использовал функцию svydesign, но я не знал, что происходит. Теперь у меня есть (чуть-чуть) лучшее понимание, и отрадно знать, что я в целом правильно понял, как решить проблему. Общее предложение @ Gavin о том, чтобы опробовать небольшие данные с внешними результатами для сравнения, неоценимо, что я должен был начать давным-давно. Большое спасибо @Gavin и @ Martin.

...