Ternary Operator `?:` on a DataFrame :)

I’m trying to use the ternary operator and get an error message:

ERROR: ArgumentError: It is only allowed to pass a vector as a column of a DataFrame."

Here’s my code:

using DataFrames

# Sample DataFrame with two columns
df = DataFrame(column1 = [10, 5, 8, 3, 12],
               column2 = [7, 4, 9, 2, 15])
df.color = df.column1 < df.column2 ? "red" : "green"

I’ve tried

df.color .= df.column1 .< df.column2 ? "red" : "green"

and get this error message:

ERROR: TypeError: non-boolean (BitVector) used in boolean context

I can get the answers I want with

df.color = ifelse.(df.column1 .< df.column2, "red", "green")

but I’d like to use the ternary ? : operator. Can someone explain the error messages to me?

Thanks.

2 Likes

(I’ve edited the title of your question to be clearer to others what this topic is about :slight_smile: )

I suspect the first error occurs on the assignment; you presumably can’t assign a single value like "red" to a whole column in a dataframe. There is usually little to no implicit widening to arrays like that in Julia.

The ternary operator ? is not vectorized — the predicate must be a single (scalar) boolean value, not an array thereof.

5 Likes

This gives a result but I don’t think it’s what you’re looking for

df.color .= df.column1 < df.column2 ? "red" : "green"

you could use the ternary operator like this (to justify the title :smile:):

 transform(df,1:2=>ByRow((x,y)->x<y ? "red" : "green")=>"color")

or like this if you don’t like mini-lamguage

 df.color = [c1 < c2 ? "red" : "green" for (c1,c2) in zip(df.column1 , df.column2)]
 df.color = [whichcol ? "red" : "green" for whichcol in   (df.column1 .< df.column2)]

(df.column1 .< df.column2) .|> rog->rog ? "red" : "gren"



df.color=(c->c ? "red" : "gren").(df.column1 .< df.column2)
1 Like

DataFramesMeta.jl is useful here

@rtransform df :color = :column1 < :column2 ? "red" : "green"
4 Likes

Thanks. I tried the first bit of code and as you guessed, setting each row to the value of “green” isn’t what I’m looking for. I’ve learned something about Julia from your other suggestions.

Neat.

Sorry, this is a response to rocco_sprmnt21.

Pretty nice.

This is an issue in Base Julia not DataFrames.jl. In my opinion a standard translation, if we want to stay with Base Julia, that can be vectorized is the ifelse function:

ifelse.(df.column1 .< df.column2, "red", "green")
2 Likes

(Another thread about broadcasting the ternary operator: Is this an expected behavior of rand.()?)

Two more options:

df.color .= [c ? "red" : "green" for c in  (df.column1 .< df.column2)]

and

df.color .= map(df.column1 .< df.column2) do c
    c ? "red" : "green"
end
2 Likes