表中的因子的随机值

时间:2015-01-09 20:27:58

标签: r

使用glm的包来读取块中的数据帧。要求所有级别的因子都出现在每个块中。我正在寻找一个很好的策略来重新安排观察,以便最大化每个块中所有值的概率。

示例是

c(4,7,4,4,4,4,4,4,4,4,4,7,4,4,8,8,5,5)

对于大小为8的大小,最佳重排将是

c(4,7,5,8,4,4,4,4,4,4,4,7,4,4,8,8,4,5,8)

是否有一些优雅的方式来改变数据?

刚看到评论......库本身被称为bigglm(它以chunkwise方式读取数据)。载体应该是eqal lenegth。问题实际上只是重新安排大多数块中存在的数据

可以在此处找到数据帧的示例 (https://www.dropbox.com/s/cth8kwcq9ph5j0p/d1.RData?dl=0

在这种情况下,最重要的是尽可能多的级别存在于尽可能多的块中。块越小,读入时所需的内存就越少。我认为假设10个块是个好点。

1 个答案:

答案 0 :(得分:1)

我想我明白你要求的是什么,虽然我不熟悉通过块读取数据并使用stringsAsFactors = TRUE同时假设先验的功能数据(并没有提供叠加因子的其他特征的方法)。我提前提出的建议是,您要么误解了该功能,要么将其误用于您的特定数据问题。

我在这样的问题上很容易出错,所以无论如何我都会尝试解决推断的问题。

您声称该函数将在前8个元素中读取,并在其上进行处理。它必须知道(在这种情况下)有四个因素需要考虑;正如您所问,最简单的方法是在每个块中都存在这些因素。一旦它处理了前8行,它就会读取第2个8个元素。对于样本数据,这不起作用,因为后面的8个元素不包含5。

我稍后会定义略微增加的数据来解决这个问题。

假设/规则

  • 数据中整体唯一值的数量不得大于每个块的大小;

  • 每个因子的出现次数必须至少与要读取的块数一样多;以及

  • 所有块中都包含精确chunksize个元素(即完整),除了最后一个块将包含1到chunksize个元素之外;麦角,

  • 最后一个块的元素至少与唯一值一样多。

功能定义

鉴于这些规则,这里有一些代码。这肯定不是唯一的解决方案,并且对于大型数据集可能表现不佳(我还没有进行过大量的测试)。

myfunc <- function(x, chunksize = 8) {
    numChunks <- ceiling(length(x) / chunksize)
    uniqx <- unique(x)
    lastChunkSize <- chunksize * (1 - numChunks) + length(x)
    ## check to see if it is mathematically possible
    if (length(uniqx) > chunksize)
        stop('more factors than can fit in one chunk')
    if (any(table(x) < numChunks))
        stop('not enough of at least one factor to cover all chunks')
    if (lastChunkSize < length(uniqx))
        stop('last chunk will not have all factors')
    ## actually arrange things in one feasible permutation
    allIndices <- sapply(uniqx, function(z) which(z == x))
    ## fill one of each unique x into chunks
    chunks <- lapply(1:numChunks, function(i) sapply(allIndices, `[`, i))
    remainder <- unlist(sapply(allIndices, tail, n = -3))
    remainderCut <- split(remainder, ceiling(seq_along(remainder)/4))
    ## combine them all together, wary of empty lists
    finalIndices <- sapply(1:numChunks,
           function(i) {
               if (i <= length(remainderCut))
                   c(chunks[[i]], remainderCut[[i]])
               else
                   chunks[[i]]
           })
    x[unlist(finalIndices)]
}

支持执行

在您提供的数据中,您有18个元素需要三个块。您的数据将在两个帐户上失败:三个元素只出现两次,因此第三个块肯定不会包含所有元素;而你的最后一个块只有两个元素,不能包含四个元素。

我将增加您的数据以满足两个未命中,并使用:

dat3 <- c(4,7,5,7,8,4,4,4,4,4,4,7,4,4,8,8,5,5,5,5)
如果除了最后一个块之外没有其他原因,它将无法正常调整。

解决方案:

myfunc(dat3, chunksize = 8)
##  [1] 4 7 5 8 4 4 4 4   4 7 5 8 4 4 5 5   4 7 5 8

(为了便于检查,将空格添加到输出中)。每个块都有4, 7, 5, 8作为其前四个元素,因此每个块都包含所有因素。

击穿

快速演练(使用debug(myfunc)),假设x = dat3chunksize = 8。跳下代码:

## Browse[2]> uniqx
## [1] 4 7 5 8
## Browse[2]> allIndices
## [[1]]
## [1]  1  6  7  8  9 10 11 13 14
## [[2]]
## [1]  2  4 12
## [[3]]
## [1]  3 17 18 19 20
## [[4]]
## [1]  5 15 16

这显示了每个唯一元素的索引。例如,有4个位于索引1,6,7等

## Browse[2]> chunks
## [[1]]
## [1] 1 2 3 5
## [[2]]
## [1]  6  4 17 15
## [[3]]
## [1]  7 12 18 16

要填充三个块,此列表开始形成这些块。在这个例子中,我们在第一个块中放置了索引1,2,3和5。回顾allIndices,您会看到这些代表uniqx中每个的第一个实例,因此第一个块现在包含c(4, 7, 5, 8),其他两个块也是如此。

此时,我们已经满足了在每个块中找到每个唯一元素的基本要求。其余的代码填充了剩余的元素。

## Browse[2]> remainder
## [1]  8  9 10 11 13 14 19 20

这些是到目前为止已添加到块中的所有索引。

## Browse[2]> remainderCut
## $`1`
## [1]  8  9 10 11
## $`2`
## [1] 13 14 19 20

虽然我们有三个块,但我们这里只有两个列表。这很好,我们没有(并且不需要任何东西)添加到最后一个块。然后,我们将这些与chunks压缩合并,以形成索引列表列表。 (注意:您可能会尝试mapply(function(a, b) c(a, b), chunks, remainderCut),但您可能会注意到如果remainderCutchunks的大小不同,正如我们在此处看到的那样,则其值会被回收。试试吧。)

## Browse[2]> finalIndices
## [[1]]
## [1]  1  2  3  5  8  9 10 11
## [[2]]
## [1]  6  4 17 15 13 14 19 20
## [[3]]
## [1]  7 12 18 16

请记住,每个数字代表x(原dat3)内的索引。然后我们unlist这个分割向量并将索引应用于数据。