【问题标题】:checking whether a value of a variables belong to a set bootstrap检查变量的值是否属于集合引导程序
【发布时间】:2017-07-09 15:55:01
【问题描述】:

我有一个整数数组说

theIndex = [ 1 2 6 7 17 2]

我有一个数据框,其中一列 dataset[:id] 包含整数说

dataset = DataFrame(id=[ 1, 1, 2, 2, 3, 3, 3, 4, 4, 4])

我想选择数据集中属于索引的所有观察值。如果它们在索引中出现两次(或更多),我想选择它们两次(或更多)

目前,我正在以愚蠢的方式做这件事。

theIndex = [ 1 2 6 7 17 2]
dataset = DataFrame(id=[ 1, 1, 2, 2, 3, 3, 3, 4, 4, 4])
dataset2 = DataFrame(id=Int64[])
for ii1=1:size(theIndex,2)
    for ii2=1:size(dataset[:id],1)
        any(i->i.==dataset[ii2,:id],theIndex[ii1]) ? 
        push!(dataset2,dataset[ii2,:id]) : nothing
    end
end

还有更优雅的解决方案吗?

【问题讨论】:

  • dataset[vcat([[j for j in 1:nrow(dataset) if dataset[j, :id] == i] for i in theIndex]...),:]跨度>
  • dataset[vcat(map(i->filter(j->dataset[j,:id]==i, 1:nrow(dataset)), theIndex)...),:]
  • 非常感谢它更紧凑/优雅。但对于大型数据集来说相当慢。有没有什么命令。这可以避免做两个循环。
  • 如果你想处理重复的值,我相信你必须做两个循环(显式或隐式)。如果theIndex 的唯一值基数较低,您可以缓存内部循环的结果以避免多次执行。
  • 其实我刚刚意识到你可以做一个嵌套理解[j for i in theIndex for j in 1:nrow(dataset) if dataset[j, :id] == i]

标签: dataframe subset julia bootstrap-4 any


【解决方案1】:

本质上,问题是要计算theIndexdataset 之间的SQL JOIN。不幸的是,DataFrames 内部并未完全实现此功能。因此,这里有一个快速(高效)的 JOIN 模拟,用于此目的:

using DataStructures

sort!(dataset, cols=:id]
j = 1
newvec = Vector{Int}() 
for (val,cnt) in SortedDict(countmap(theIndex))
    while j<=nrow(dataset)
        dataset[j,:id] > val && break
        dataset[j,:id] == val && append!(newvec,fill(j,cnt))
        j += 1
    end
end
dataset2 = dataset[newvec,:]

DataStructures 包用于 SortedDict。这种实现应该比其他多循环方法更有效。

【讨论】:

  • 丹。非常感谢。它非常快,但是,它仅适用于我给您的特定示例。在我的“真实”示例中。 newvec 不包含足够的值。有些 id 在新数据集中只重复一次,有些可以出现多次。这可能是问题吗?
  • @grandemundo 是的,忘记了排序 dataset 的一行(用它更新了答案)。算法必须工作,并且可能需要最长的运行时间。
【解决方案2】:

根据我之前的评论,您正在寻找 findin 函数。

julia> Ind = findin( dataset[:id], theIndex); # return indices of elements in
                                              # dataset[:id] that occur in
                                              # theIndex

julia> dataset[:id][Ind]
4-element DataArrays.DataArray{Int64,1}:
 1
 1
 2
 2

(或者,如果您希望结果以 SubDataFrame 的形式返回到您的数据集中,您可以这样做 SubDataFrame(dataset, Ind) 等)

编辑:根据 cmets,为确保考虑到 theIndex 中的重复,每个元素的样本需要单独附加:

Ind = []; for i in theIndex; append!(Ind, findin(dataset[:id], i)); end

Ind 然后可用于创建一个数组或 SubDataFrame,如上所述。

编辑 2

julia> @time dataset2 = DataFrame(id=Int64[])
       for ii1=1:size(theIndex,2)
           for ii2=1:size(dataset[:id],1)
               any(i->i.==dataset[ii2,:id],theIndex[ii1]) && 
               push!(dataset2,dataset[ii2,:id])
           end
       end
  0.000016 seconds (24 allocations: 1.594 KiB)

julia> @time Ind = []; for i in theIndex; append!(Ind, findin(dataset[:id], i)); end
  0.000002 seconds (5 allocations: 240 bytes)

(关于全球范围内基准测试的常见警告性咆哮)

【讨论】:

  • 感谢您的回答。那很快。问题是如何处理重复。如何调整 findin 以使其返回 [1 1 2 2 2 2]。在此特定示例中,2 在theIndex 中出现了两次。如果您熟悉它,那就是在引导程序中使用替换进行重新采样。
  • 嗯。我明白你在说什么。我现在无法更新我的答案,但您可以通过列表理解或 map 操作分别对索引的每个元素执行 findin 来实现这一点,然后将生成的子列表附加到一个.稍后我会在 julia 终端前更新我的答案。
  • 话虽如此,如果您想要一个 正确 引导操作,也许您应该查看sample,而不是在给定概率分布的情况下这样做。不记得具体是哪个包裹了……我会尽可能告诉你。
  • 这个:juliastats.github.io/StatsBase.jl/stable/…(从加权数组中替换或不替换的样本,我认为这是你想要做的)
  • 感谢您的链接。我实际上是在做块引导(基于公共 id 对行块进行采样),那里似乎不支持。会考虑你的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
  • 1970-01-01
  • 2020-07-17
  • 2011-01-13
相关资源
最近更新 更多