从Julia的数据中标记密钥的最后记录

时间:2015-08-23 17:13:09

标签: julia

在Julia中处理大数据时,人们认为标记组或ID的最后记录的最佳方法是什么?

示例数据:

ID|some_value
1011|200
1011|250
1011|100  # <-- I want to flag when I am here...
1012|450
....

我目前的想法是使用矢量化解决方案,例如:

if data[i,1] != data[i+1, 1]
     #do something cool
end 

我不认为这是非常有效的。有没有更好的办法?

2 个答案:

答案 0 :(得分:3)

目前还不清楚您是如何迭代/正在使用的数据结构。但最简单的方法是迭代并跟踪前一行*:

current_row = data[1, 1:end]  # first row
previous_row = current_row
for i in 2:size(data, 1)  # for each row
    current_row = data[i, 1:end]
    if current_row[1] != previous_row[i]  # or however you access "ID"
        # do something cool with previous_row
    end
    previous_row = current_row
end
# do something cool with previous_row (last row)

注意:由于数组按列顺序存储,而不是按行,YMMV取决于数据结构,因此存在性能警告。也许你可以使用一些技巧......

*假设数据按ID排序。

如果您正在使用包含未排序数据的DataFrame,请参阅split-apply-combine,或许您希望将ID分组并将last应用于每个组。

答案 1 :(得分:1)

这取决于您的优先事项。您是否想要最省力的解决方案?或者你想要超快的版本?

请注意,在Julia中,迭代解决方案(为循环编写)通常是计算某些东西的最快方法。假设您的ID列已排序(或至少已分组),快速而脏的方法将是使用diff:

julia> data = [1011 200
       1011 250
       1011 100  # <-- I want to flag when I am here...
       1012 450]
4x2 Array{Int64,2}:
 1011  200
 1011  250
 1011  100
 1012  450

julia> last_values1(A) = A[push!(diff(A[:,1]), 1) .!= 0, 2]
last_values1 (generic function with 1 method)

julia> last_values1(data)
2-element Array{Int64,1}:
 100
 450

沿着第一列计算diff返回0,其中ID相同,并且当索引改变时返回非零值。我添加了一个最终的非零元素来捕获最后一个组的最后一个元素。这当然不是最快的方法,但它是最简单的,最不可能包含错误。它不是Julia中最快的解决方案,因为它需要几个临时数组,但它应该与Matlab / python相当竞争。

您也可以迭代地找到这些结果,但需要更多代码:

julia> function last_values2(A)
           values = eltype(A)[]
           for i=1:size(A,1)-1
               if A[i,1] != A[i+1,1]
                   push!(values, A[i, 2])
               end
           end
           push!(values, A[end, 2])
           return values
       end
last_values2 (generic function with 1 method)

julia> last_values2(data)
2-element Array{Int64,1}:
 100
 450

现在我们只是将元素直接推送到不断增长的阵列上(这甚至可以进一步优化)。这也可以很容易地扩展到其他分析。我们可以将效果与更大的虚假数据集进行比较:

julia> data = [rand(1:1000, 100_000) rand(1:100_000, 100_000)];
       idxs = sortperm(data[:, 1])
       data = data[idxs, :];

julia> @time last_values1(data);
  0.002753 seconds (20 allocations: 2.321 MB)

julia> @time last_values2(data);
  0.000551 seconds (14 allocations: 16.500 KB)

julia> last_values1(data) == last_values2(data)
true

所以在这种情况下,除非您的数据集绝对是巨大的,否则确实没有那么大的优势。