# Ifelse in a DataFrame

**URL:** https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463
**Category:** New to Julia
**Tags:** dataframes
**Created:** [February 14, 2022, 10:31pm UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463 "2022-02-14T22:31:38Z")
**Posts on this page:** 14
**Page:** 1

<div class="post-metadata">

### Author: ![CompulsoryCoffee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/compulsorycoffee/32/30434_2.png) [@CompulsoryCoffee](https://discourse.julialang.org/u/CompulsoryCoffee)
#### Post date: [February 14, 2022, 10:31pm UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/1 "2022-02-14T22:31:38Z")

</div>

I recently found out about the ifelse statement in Julia.

```julia
test = DataFrame(a = 1:10, b = rand(10), c=[2,2,2,2,2,5,5,5,5,5])

 Row │ a b c d     
     │ Int64 Float64 Int64 Int64 
─────┼───────────────────────────────
   1 │ 1 0.604762 2 1
   2 │ 2 0.329433 2 2
   3 │ 3 0.491057 2 3
   4 │ 4 0.468994 2 4
   5 │ 5 0.359621 2 5
   6 │ 6 0.16639 5 6
   7 │ 7 0.259958 5 7
   8 │ 8 0.591549 5 8
   9 │ 9 0.48926 5 9
  10 │ 10 0.110892 5 10

f(x) = (x==5) ? 1 : 0
test.d = f.(test.c)

10×4 DataFrame
 Row │ a b c d     
     │ Int64 Float64 Int64 Int64 
─────┼───────────────────────────────
   1 │ 1 0.604762 2 0
   2 │ 2 0.329433 2 0
   3 │ 3 0.491057 2 0
   4 │ 4 0.468994 2 0
   5 │ 5 0.359621 2 0
   6 │ 6 0.16639 5 1
   7 │ 7 0.259958 5 1
   8 │ 8 0.591549 5 1
   9 │ 9 0.48926 5 1
  10 │ 10 0.110892 5 1

```

Is there a way to get the if without the else to keep the same column values?

to get something like this:

```julia
 Row │ a b c d     
     │ Int64 Float64 Int64 Int64 
─────┼───────────────────────────────
   1 │ 1 0.604762 2 1
   2 │ 2 0.329433 2 2
   3 │ 3 0.491057 2 3
   4 │ 4 0.468994 2 4
   5 │ 5 0.359621 2 5
   6 │ 6 0.16639 5 1
   7 │ 7 0.259958 5 1
   8 │ 8 0.591549 5 1
   9 │ 9 0.48926 5 1
  10 │ 10 0.110892 5 1

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [February 14, 2022, 10:38pm UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/2 "2022-02-14T22:38:19Z")

</div>

> [@CompulsoryCoffee](#):
>
> `test.d = f.(test.c)`

```julia
test.d = [(t.c == 5 ? 1 : t.a) for t in eachrow(test)];

```

---

<div class="post-metadata">

### Author: ![DataFrames](https://avatars.discourse-cdn.com/v4/letter/d/e19b73/32.png) [@DataFrames](https://discourse.julialang.org/u/DataFrames)
#### Post date: [February 15, 2022, 3:46am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/3 "2022-02-15T03:46:45Z")

</div>

don’t use `eachrow`

```julia
test = DataFrame(a = 1:10, b = rand(10), c=[2,2,2,2,2,5,5,5,5,5], d = 1:10)
test[test.c .== 5, :d] .= 1

```

---

<div class="post-metadata">

### Author: ![digital\_carver](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/digital_carver/32/33818_2.png) [@digital\_carver](https://discourse.julialang.org/u/digital_carver)
#### Post date: [February 15, 2022, 3:59am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/4 "2022-02-15T03:59:21Z")

</div>

This method mentioned by @DataFrames is the way. The `test.c .== 5` specifies which rows to choose, and the `:d` specifies which column to change within that row.

By the way, the `(x==5) ? 1 : 0` syntax you mention is called the “ternary operator”. `ifelse` is something different, that’s also present in Julia (`?ifelse` will describe the difference, though the ternary operator and normal `if` are much more common than `ifelse`).

---

<div class="post-metadata">

### Author: ![CompulsoryCoffee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/compulsorycoffee/32/30434_2.png) [@CompulsoryCoffee](https://discourse.julialang.org/u/CompulsoryCoffee)
#### Post date: [February 15, 2022, 9:17am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/5 "2022-02-15T09:17:29Z")

</div>

I found that I can use another variable to the function to do the trick (even though I will be using the ticked solution).

```julia
f(x,y) = (x==5) ? 1 : y
test.d = f.(test.c, test.d)

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [February 15, 2022, 9:25am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/6 "2022-02-15T09:25:07Z")

</div>

Well this creates temporary mask array, so depending on how large is your problem…

---

<div class="post-metadata">

### Author: ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)
#### Post date: [February 15, 2022, 9:28am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/7 "2022-02-15T09:28:07Z")

</div>

```julia
@. test.d = ifelse(test.c == 5, 1, test.d)

```

---

<div class="post-metadata">

### Author: ![CompulsoryCoffee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/compulsorycoffee/32/30434_2.png) [@CompulsoryCoffee](https://discourse.julialang.org/u/CompulsoryCoffee)
#### Post date: [February 15, 2022, 9:32am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/8 "2022-02-15T09:32:31Z")

</div>

> [@bkamins](#):
>
> `.d = ifelse(test.c == 5, 1, test.d)`

Out of curiosity, what would be the most efficient way of doing this (memory and speed)?

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [February 15, 2022, 9:35am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/9 "2022-02-15T09:35:43Z")

</div>

For loop. (Implicit in that comprehension)

I get it, DataFrame users look down at for loop, but come on do we never play with big data? I know DataFrames.jl is not good at for loop because we traded for loop speed with less latency by not recording column type, but you can use DataFramesMeta.jl

---

<div class="post-metadata">

### Author: ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)
#### Post date: [February 15, 2022, 9:47am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/10 "2022-02-15T09:47:56Z")

</div>

My solution is essentially for loop but without writing it down explicitly as what I propose is more compact.

```julia
julia> using DataFrames

julia> test = DataFrame(a = 1:10, b = rand(10), c=[2,2,2,2,2,5,5,5,5,5]);

julia> test_large = repeat(test, 10^7);

julia> @time @. test.d = ifelse(test.c == 5, 1, test.c);
  0.141236 seconds (301.00 k allocations: 15.882 MiB, 99.81% compilation time)

julia> @time @. test_large.d = ifelse(test_large.c == 5, 1, test_large.c);
  0.212442 seconds (23 allocations: 762.940 MiB, 29.64% gc time)

```

@jling - can you please show your proposal so that we can compare timing on the same data?

Let us just settle on the use case: we want to measure timing of creating new column `:d`, I mention this, because if we wanted to update `:d` in place it would be a bit different syntax and faster:

```julia
julia> @time @. test_large[:, :d] = ifelse(test_large.c == 5, 1, test_large.c);
  0.097687 seconds (7 allocations: 272 bytes)

```

---

<div class="post-metadata">

### Author: ![jling](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jling/32/212909_2.png) [@jling](https://discourse.julialang.org/u/jling)
#### Post date: [February 15, 2022, 9:52am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/11 "2022-02-15T09:52:44Z")

</div>

Oh I didn’t see it was a reply quoting your solution. Yes, your solution is the best of both worlds – doesn’t have mask array, also doesn’t loop over eachrow()

(To make comprehension/ looping over eachrow() as fast, we need DataFramesMeta I think?)

---

<div class="post-metadata">

### Author: ![CompulsoryCoffee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/compulsorycoffee/32/30434_2.png) [@CompulsoryCoffee](https://discourse.julialang.org/u/CompulsoryCoffee)
#### Post date: [February 15, 2022, 9:53am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/12 "2022-02-15T09:53:44Z")

</div>

> [@DataFrames](#):
>
> `test[test.c .== 5, :d] .= 1`

Thanks!

---

<div class="post-metadata">

### Author: ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)
#### Post date: [February 15, 2022, 9:54am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/13 "2022-02-15T09:54:54Z")

</div>

> [@jling](#):
>
> we need DataFramesMeta I think?

You need `@eachrow!` from DataFramesMeta.jl [Introduction · DataFramesMeta Documentation](https://juliadata.github.io/DataFramesMeta.jl/stable/#@eachrow-and-@eachrow!).

---

<div class="post-metadata">

### Author: ![bkamins](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bkamins/32/208538_2.png) [@bkamins](https://discourse.julialang.org/u/bkamins)
#### Post date: [February 15, 2022, 9:56am UTC](https://discourse.julialang.org/t/ifelse-in-a-dataframe/76463/14 "2022-02-15T09:56:18Z")

</div>

> [@DataFrames](#):
>
> test[test.c .== 5, :d] .= 1

This is an in-place variant, and it will be slower as it allocates mask array as @jling commented:

```julia
julia> @time test_large[test_large.c .== 5, :d] .= 1;
  0.292150 seconds (10 allocations: 393.395 MiB, 23.50% gc time)

```
