Using . on a function where one of the parameters should not be iterated

I’m trying to do the following. I have a function foo(x, d::DataFrame) and a 1 dimensional array a of data for which I want to call the function for each element. Problem is I want to pass a DataFrame df too but when I execute:

.foo(a, df)

It’s not the dataframe that is used but, logically, the elements in the dataframe.

I tried to work around this by creating a one dimensional array as follows:

dfa = Array{DataFrame}(undef, 1, length(a))
dfa .= df

But then I get the following error upon assignment:
ERROR: DimensionMismatch: array could not be broadcast to match destination

When I do the same with an Integer type

ia = Array{Integer}(undef, 1, length(a))
ia .= 2

everything works just fine.

So why does the same type of code raise an error when the type is a DataFrame???

Optionally, is there a way to pass the DataFrame without putting it in an Array?

1 Like

When you have a function f(scalar, iterable), and you want to use broadcasting to call it for a collection of scalars and a single iterable, you need to signal that the iterable should not be broadcasted over. The standard way to do it is to wrap your iterable in Ref:

f(x::Integer, a::Vector) = x + length(a)

xs = [1, 2, 3, 4, 5]
a = [1, 2, 3]

julia> f.(xs, Ref(a))
5-element Vector{Int64}:
 4
 5
 6
 7
 8
5 Likes

If I understand correctly you just want to protect the df argument from broadcasting, the standard solutions are a 1-element tuple (as that doesn’t allocate) - foo.(a, (df, )) - or a ref: foo.(a, Ref(df)).

5 Likes