在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
我不认为这是非常有效的。有没有更好的办法?
答案 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
所以在这种情况下,除非您的数据集绝对是巨大的,否则确实没有那么大的优势。