If, elseif, else vs Case When

I was trying to get a multiple conditional statement running and I keep hitting an error.

df1 = @chain df begin
    @transform(:Business_Type = if :Business_Type .== "Corporate Travel Department (CTD)"
                                   :Business_Type ="Corporate"
                                elseif :Business_Type .== "Cruise" 
                                   :Business_Type = "Leisure"
                                elseif :Business_Type .== "Corporate"  
                                    :Business_Type ="Corporate"
                                elseif :Business_Type .== "Leisure" 
                                    :Business_Type = "Leisure"
                                elseif :Business_Type .== "Travel Management Company" 
                                    :Business_Type ="Unkown"
                                elseif :Business_Type .== "Tour Operator"
                                    :Business_Type ="Unknown"
                                else "Unknown"
                                end)
    @select(:Business_Type, :trip_type, :travellers, :haul, :cabin_class, :legs, :travel_dow, :businessday
    ,:trip_length_days, :lead_time, :businessdaytotal, :travel_month, :DBA_Name, :iata, :pcc)
end

The error message is:

ERROR: TypeError: non-boolean (Vector{Union{Missing, Bool}}) used in boolean context

The example I used was:

if g == 0
        0
    elseif g == 1 
        10
    elseif g == 2
        20
    elseif g == 3
        30
    elseif g == 4
        40
    else
        50
    end

I think the complication I’m having is dealing with casting it to every row and doing it within a @transform statement… I was looking at the @byrow command but it seems like it can only use one argument:

@transform(df, @byrow :y = :x == 1 ? true : false)

@byrow accepts a single argument and creates an anonymous function wrapped in ByRow

Thoughts?

Why are you trying to use a dot here? That will return a vector, and this is the cause of the error.

2 Likes

Ah I tried it earlier and it only produced the else part of the code, i.e. all of the results ended up as β€œunknown” when I know that there should be β€œcorporate” or β€œleisure”

julia> levels(df1.Business_Type)
1-element Vector{String}:
 "Unknown"

There are a few tweaks to your code in DataFramesMeta that will make this easier

  1. @rtransform instead of @transform. This operates row-wise (else-if stuff doesn’t work on vectors.
  2. No need to use parentheses. IMO it’s easier with a begin...end block. The non-parentheses part is most important when it comes to skipping over missing values.

julia> @chain df begin 
           @rtransform :Business_Type = begin 
               if :Business_Type == "Corporate" 
                   1
               elseif :Business_Type == "Leisure"
                   2
               elseif :Business_Type == "Cruise"
                   3
               end
           end
       end
1 Like

You may also want to consider a Dict instead of a large if-else block, e.g.

julia> departments = Dict("Corporate Travel Department (CTD)" => "Corporate",
                          "Cruise" => "Leisure",
                          "Corporate" => "Corporate",
                          "Travel Management Company" => "Unknown",
                          "Tour Operator" => "Unknown")

julia> df = DataFrame(Business_Type = rand(["Corporate Travel Department", "Cruise", "Corporate", "Leisure", "Tour Operator"], 5), 
                      id=rand(UInt8, 5))
5Γ—2 DataFrame
 Row β”‚ Business_Type                id
     β”‚ String                       UInt8
─────┼────────────────────────────────────
   1 β”‚ Cruise                          10
   2 β”‚ Corporate                      178
   3 β”‚ Corporate                      199
   4 β”‚ Corporate                      131
   5 β”‚ Corporate Travel Department    152

julia> @rtransform(df, :Business_Type = get(departments, :Business_Type, "Unknown"))
5Γ—2 DataFrame
 Row β”‚ Business_Type  id
     β”‚ String         UInt8
─────┼──────────────────────
   1 β”‚ Leisure           10
   2 β”‚ Corporate        178
   3 β”‚ Corporate        199
   4 β”‚ Corporate        131
   5 β”‚ Unknown          152
2 Likes

Unfortunately I can’t mark multiple solutions but thank you!