Join asof加入Julia数据工具

Join asof加入Julia数据工具,join,julia,Join,Julia,我希望能像《朱莉娅》中的熊猫或QuestDB那样做点什么关键是,我还需要按操作应用组 我很乐意使用Julia的Table.jl工具。DataFrame的get很接近,但需要精确的键匹配,并且不进行分组(据我所知)。jl允许您传入自己的比较函数,但我不太明白如何使用该函数指定“最接近的小于”值或“最接近的大于”值 对于一个不需要分组的简单示例,在两个表left和right上,每个表都有一列time,我可以使用如下函数 function find_nearest_before(val, data)

我希望能像《朱莉娅》中的熊猫或QuestDB那样做点什么关键是,我还需要按操作应用组

我很乐意使用Julia的
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)