Join asof加入Julia数据工具
我希望能像《朱莉娅》中的熊猫或QuestDB那样做点什么关键是,我还需要按操作应用组 我很乐意使用Julia的Join asof加入Julia数据工具,join,julia,Join,Julia,我希望能像《朱莉娅》中的熊猫或QuestDB那样做点什么关键是,我还需要按操作应用组 我很乐意使用Julia的Table.jl工具。DataFrame的get很接近,但需要精确的键匹配,并且不进行分组(据我所知)。jl允许您传入自己的比较函数,但我不太明白如何使用该函数指定“最接近的小于”值或“最接近的大于”值 对于一个不需要分组的简单示例,在两个表left和right上,每个表都有一列time,我可以使用如下函数 function find_nearest_before(val, data)
Table.jl
工具。DataFrame的get很接近,但需要精确的键匹配,并且不进行分组(据我所知)。jl允许您传入自己的比较函数,但我不太明白如何使用该函数指定“最接近的小于”值或“最接近的大于”值
对于一个不需要分组的简单示例,在两个表left
和right
上,每个表都有一列time
,我可以使用如下函数
function find_nearest_before(val, data)
findlast(x -> x <= val, data)
end
[find_nearest_before(t, right.time) for t in left.time]
所需操作的最终结果如下所示
julia> Table(time=[4,5,7,8,9,10,11,13,15,16], sensor_id=[2,1,1,3,2,3,1,2,3,2], object_in_sensor_FOV=[:c,:b,:b,:b,:a,:b,:b,:a,:c,:a])
Table with 3 columns and 10 rows:
time sensor_id object_in_sensor_FOV
┌──────────────────────────────────────
1 │ 4 2 c
2 │ 5 1 b
3 │ 7 1 b
4 │ 8 3 b
5 │ 9 2 a
6 │ 10 3 b
7 │ 11 1 b
8 │ 13 2 a
9 │ 15 3 c
10 │ 16 2 a
这里有一种在数据帧中实现这一点的方法——这当然不是效率的顶峰,但是如果您的数据足够小,您可以负担得起第一个
leftjoin
,它可能就足够了
首先将传感器中的连接到传感器上
:
julia> df = leftjoin(sensor_pings, in_sensor_FOV, on = :sensor_id, makeunique = true);
之后,您将在传感器pings
中为每个传感器设置多行,如果您的数据很大,这种方法可能会失败
然后得到时差:
julia> transform!(df, [:time, :time_1] => ((x, y) -> x - y) => :time_diff);
julia> df = df[df.time_diff .> 0.0, :];
<>现在,你的<代码> FordStuts< /Cord>方法IIUC意味着我们只考虑具有正时差的行:
julia> transform!(df, [:time, :time_1] => ((x, y) -> x - y) => :time_diff);
julia> df = df[df.time_diff .> 0.0, :];
然后,我们按传感器和时间差排序,并为每个传感器选择第一行:
julia> res = combine(groupby(sort(df, [:sensor_id, :time_diff]), [:sensor_id, :time]), names(df[:, Not([:sensor_id, :time])]) .=> first .=> names(df[:, Not([:sensor_id, :time])]));
结果(排序以产生相同的输出):
写这样的东西很容易,只需要实现双游标
using TypedTables
using Setfield
sensor_pings = Table(time=[4,5,7,8,9,10,11,13,15,16], sensor_id=[2,1,1,3,2,3,1,2,3,2])
in_sensor_FOV = Table(time=[1.3,2.6,3.8,5.9,7.3,8.0,12.3,14.7], sensor_id=[3,1,2,3,2,2,3,1], object_in_sensor_FOV=[:a,:b,:c,:b,:c,:a,:c,:b])
function mergeasof(t1, t2)
objects = similar(t2.object_in_sensor_FOV, length(t1.time))
d = ntuple(_ -> :z, 3) # :z is a sentinel value, means that there were no objects up to this moment. Can be anything
i2 = 1
# Double cursor
for i1 in axes(t1, 1)
tm1 = t1.time[i1]
# updating `d` to the current time step
while i2 <= length(t2.time)
t2.time[i2] > tm1 && break
@set! d[t2.sensor_id[i2]] = t2.object_in_sensor_FOV[i2]
i2 += 1
end
objects[i1] = d[t1.sensor_id[i1]]
end
return Table(time = t1.time, sensor_id = t1.sensor_id, object_in_sensor_FOV = objects)
end
julia> mergeasof(sensor_pings, in_sensor_FOV)
Table with 3 columns and 10 rows:
time sensor_id object_in_sensor_FOV
┌──────────────────────────────────────
1 │ 4 2 c
2 │ 5 1 b
3 │ 7 1 b
4 │ 8 3 b
5 │ 9 2 a
6 │ 10 3 b
7 │ 11 1 b
8 │ 13 2 a
9 │ 15 3 c
10 │ 16 2 a
和@set代码>应该被删除
d[t2.sensor_id[i2]] = t2.object_in_sensor_FOV[i2]
而不是
objects[i1] = d[t1.sensor_id[i1]]
你应该使用
objects[i1] = get(d, t1.sensor_id[i1], :z)
为什么不能用这种不精确的匹配联接表,然后在左键上进行分组操作?这应该与一步完成相同。这是一个好主意,但必须先进行分组操作。假设我的右侧
表中有列时间
,区域
,项目
,我想按区域
分组。如果我先进行不精确匹配,我可以将一个区域的行与另一个区域的行进行匹配。
objects[i1] = get(d, t1.sensor_id[i1], :z)