How to filter a tuple by the first element

I made a tuple with vectors and I want to filter and plot it by the first vector

function gen_data()
    a = collect(0:.1:200)
    b = rand(length(a))
    c = [ rand()*i*0.001 for i in 1:length(a)]
    return a,b,c
end

d = gen_data()

typeof(d)
using Plots
plot(d[1],d[2])
plot!(d[1],d[3])

This is fine but if try to filter it

d1 = filter( i -> i[1]>100, d )

but the result is empty

I am not sure what you are trying to accomplish here, but it is possible, that you are making a mistake and intended to do something else.

When you are filtering d, you are iterating over (d[1], d[2], d[3]), and then checking if d[1][1] > 100, d[2][1] > 100 and d[3][1] > 100, neither of which is true, because d[1][1] is 0.0, d[2][1] is a number in the interval [0, 1) and d[3][1] is a number in the interval [0, 0.001).

2 Likes

Imagine d[1] is time and d[2], d[3] are some kind of model, then I whish to plot the values for d[2] d[3] with time > 100. So I would like to iterate only over d[1]. Maybe this should be done with a DataFrame.

First you need to obtain an array marking the elements that you want, and then use that array to index the arrays (you have three independent arrays, and the fact that they are in a tuple does not help much):

julia> data = (rand(5),rand(5));

julia> inds = data[1] .> 0.5 # bool array
5-element BitVector:
 0
 1
 1
 1
 1

julia> data[2][inds]
4-element Vector{Float64}:
 0.3156756681271574
 0.3046881119816406
 0.6945063237653067
 0.8492254807551606

julia> plot(data[1][inds],data[2][inds])

A least general way, if the data[1] is always increasing, is to use something like:

julia> data = (sort(rand(5)),rand(5));

julia> data[1]
5-element Vector{Float64}:
 0.03852598530448814
 0.18616226772164635
 0.25586337027799577
 0.3970926196952723
 0.8350821471218625

julia> i = findfirst(x -> x > 0.2, data[1])
3

julia> plot(data[1][i:end],data[2][i:end])

(or if it is just plotting what you want, adjust the xlims of the plot)

1 Like

It can be cleaner and more convenient to use a table such as a StructArray:

julia> function gen_data()
           a = collect(0:.1:200)
           b = rand(length(a))
           c = [ rand()*i*0.001 for i in 1:length(a)]
           return StructArray(;a,b,c)
       end

julia> d = gen_data()

julia> plot(d.a, d.b)

julia> d1 = filter(i -> i.a > 100, d)

julia> plot(d1.a, d1.b)