按julia中的公共列值合并数组
假设Julia中有以下3个数组:按julia中的公共列值合并数组,julia,array-merge,Julia,Array Merge,假设Julia中有以下3个数组: 5.03.5 6.0 3.6 7.0 3.0 5.04.5 6.0 4.7 8.0 3.0 5.04.0 6.0 3.2 8.0 4.0 我想将3个数组合并到一个数组中,通过第一列的公共值,对第二列的值求和。结果必须是以下数组: 5.0 12 6.0 11.5 7.0 3.0 8.0 7.0 我尝试了vcat和reduce,但没有得到假装的结果。是否有一种相对简单的方法来编写指令,避免耗时的代码?谢谢大家! 可能有很多方法可以做到这一点。如果您想避免编
5.03.5
6.0 3.6
7.0 3.0
5.04.5
6.0 4.7
8.0 3.0
5.04.0
6.0 3.2
8.0 4.0
我想将3个数组合并到一个数组中,通过第一列的公共值,对第二列的值求和。结果必须是以下数组:
5.0 12
6.0 11.5
7.0 3.0
8.0 7.0
我尝试了
vcat
和reduce
,但没有得到假装的结果。是否有一种相对简单的方法来编写指令,避免耗时的代码?谢谢大家! 可能有很多方法可以做到这一点。如果您想避免编码,可以使用DataFrames包。这不是最快的解决方案,但它很短
假设已将数组定义为变量:
x = [5.0 3.5
6.0 3.6
7.0 3.0]
y = [5.0 4.5
6.0 4.7
8.0 3.0]
z = [5.0 4.0
6.0 3.2
8.0 4.0]
然后你可以做:
using DataFrames
Matrix(aggregate(DataFrame(vcat(x,y,z)), :x1, sum))
:x1
部分是因为在默认情况下,数据帧
的第一列被称为:x1
,如果您没有给它一个明确的名称。在此配方中,我们将矩阵转换为数据帧,将其聚合并将结果转换回矩阵。无需额外包装,可能的解决方案如下
function aggregate(m::Array{<:Number,2}...)
result=sortrows(vcat(m...))
n = size(result,1)
if n <= 1
return result
end
key_idx=1
key=result[key_idx,1]
for i in 2:n
if key==result[i,1]
result[key_idx,2:end] += result[i,2:end]
else
key = result[i,1]
key_idx += 1
result[key_idx,1] = key
result[key_idx,2:end] = result[i,2:end]
end
end
return result[1:key_idx,:]
end
印刷品:
4×2 Array{Float64,2}:
5.0 12.0
6.0 11.5
7.0 3.0
8.0 7.0
注:鉴于以下两个假设,此解决方案也适用于任意数量的列:
function f_ag(x::Matrix{T}...)::Matrix{T} where {T<:Number}
isempty(x) && error("Empty input")
any([ size(y,2) != 2 for y in x ]) && error("Input matrices must have two columns")
length(x) == 1 && return copy(x[1]) #simple case shortcut
nxmax = [ size(y,1) for y in x ]
nxarrinds = find(nxmax .> 0)
nxrowinds = ones(Int, length(nxarrinds))
z = Tuple{T,T}[]
while !isempty(nxarrinds)
xmin = minimum(T[ x[nxarrinds[j]][nxrowinds[j], 1] for j = 1:length(nxarrinds) ])
minarrinds = Int[ j for j = 1:length(nxarrinds) if x[nxarrinds[j]][nxrowinds[j], 1] == xmin ]
rowsum = sum(T[ x[nxarrinds[k]][nxrowinds[k], 2] for k in minarrinds ])
push!(z, (xmin, rowsum))
for k in minarrinds
nxrowinds[k] += 1
end
for j = length(nxarrinds):-1:1
if nxrowinds[j] > nxmax[nxarrinds[j]]
deleteat!(nxrowinds, j)
deleteat!(nxarrinds, j)
end
end
end
return [ z[n][j] for n = 1:length(z), j = 1:2 ]
end
function f_ag(x::Matrix{T}...)::Matrix{T} where {T<:Number}
isempty(x) && error("Empty input")
any([ size(y,2) != 2 for y in x ]) && error("Input matrices must have two columns")
length(x) == 1 && return copy(x[1]) #simple case shortcut
nxmax = [ size(y,1) for y in x ]
nxarrinds = find(nxmax .> 0)
nxrowinds = ones(Int, length(nxarrinds))
z = Tuple{T,T}[]
while !isempty(nxarrinds)
xmin = minimum(T[ x[nxarrinds[j]][nxrowinds[j], 1] for j = 1:length(nxarrinds) ])
minarrinds = Int[ j for j = 1:length(nxarrinds) if x[nxarrinds[j]][nxrowinds[j], 1] == xmin ]
rowsum = sum(T[ x[nxarrinds[k]][nxrowinds[k], 2] for k in minarrinds ])
push!(z, (xmin, rowsum))
for k in minarrinds
nxrowinds[k] += 1
end
for j = length(nxarrinds):-1:1
if nxrowinds[j] > nxmax[nxarrinds[j]]
deleteat!(nxrowinds, j)
deleteat!(nxarrinds, j)
end
end
end
return [ z[n][j] for n = 1:length(z), j = 1:2 ]
end
为此:
rowsum = input_func(T[ x[nxarrinds[k]][nxrowinds[k], 2:end] for k in minarrinds ])
现在你可以输入任何你喜欢的函数,并且在你的输入矩阵中有任意数量的附加列
这里可能还可以添加一些额外的优化,例如预分配
z
,只有两个输入矩阵时的专用例程,等等,但我不打算为它们操心。太棒了!很好的解决方案!正在创建聚合函数。将对所有3个数组中的第一列进行排序。这是事故吗?如果没有,那么有些算法比目前提供的两种算法都要快得多。是的,第一列总是被排序的!:-)真的吗?是的,一个while
循环,它同时向下推进所有输入数组的第一列。但条件逻辑会有点混乱。我今天没时间,但我明天会回来试试。好吧,我很好奇:-)做完了。我假设了排序顺序和唯一性,因为这使它不那么复杂。只是一点注释:排序的是每个数组的第一列,而不是第一行。无论如何,我可以转置每个数组。否则,谢谢你的辛勤工作@酷啊!代码本身是正确的,只是我的文本错了。我不打电话的时候会修好的。如果我的回答是有帮助的,那么给这个回答投上一票可能是个好主意(其他回答也是如此)。干杯。已经修复了文本OK!谢谢我刚刚检查了代码,事实上,这只是一个文本问题。。。对不起,麻烦了。。。。谢谢你的精彩工作!!我觉得有趣的是,你提到我们可以根据自己喜欢的功能调整线条。我想实现它是为了计算值的平均值,而不是它们的总和;-)
rowsum = input_func(T[ x[nxarrinds[k]][nxrowinds[k], 2:end] for k in minarrinds ])