# Easiest way to do "replace col1 = col2 if col3" in a dataframe

**URL:** https://discourse.julialang.org/t/easiest-way-to-do-replace-col1-col2-if-col3-in-a-dataframe/51891
**Category:** Data
**Created:** [December 15, 2020, 8:16pm UTC](https://discourse.julialang.org/t/easiest-way-to-do-replace-col1-col2-if-col3-in-a-dataframe/51891 "2020-12-15T20:16:25Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![RangeFu](https://avatars.discourse-cdn.com/v4/letter/r/e9c0ed/32.png) [@RangeFu](https://discourse.julialang.org/u/RangeFu)
#### Post date: [December 15, 2020, 8:16pm UTC](https://discourse.julialang.org/t/easiest-way-to-do-replace-col1-col2-if-col3-in-a-dataframe/51891/1 "2020-12-15T20:16:25Z")

</div>

A very common operation in data manipulation: Update in-place col1 from col2 but only for rows where conditions hold for col3. If we stick to `DataFrames`, it has to be:

```julia
dt[dt.c, a] = dt[dt.c, b]

```

so we have to carry `dt.` all around, which can be very unhandy once `dt` is long.

The syntax in the title is from Stata. Thanks to its (unattractive) feature of handling only one dataframe at a time, it can avoid repeating `dt`.

In `data.table` from R, we could also do:

```r
dt[c, a = b]
# (May not be the exact syntax - has been a while) 

```

Any hacks to achieve similiar simplicity in Julia?

---

<div class="post-metadata">

### Author: ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)
#### Post date: [December 15, 2020, 8:30pm UTC](https://discourse.julialang.org/t/easiest-way-to-do-replace-col1-col2-if-col3-in-a-dataframe/51891/2 "2020-12-15T20:30:34Z")

</div>

A complicated version:

```julia
transform!(df, [:a, :b, :c] => ((a, b, c) -> ifelse.(c, b, a)) => :c)

```

A shorter version would use DataFramesMeta

```julia
@with df :a[:c] .= :b[:c]

```

This is definitely something we can focus on improving in the future.

---

<div class="post-metadata">

### Author: ![RangeFu](https://avatars.discourse-cdn.com/v4/letter/r/e9c0ed/32.png) [@RangeFu](https://discourse.julialang.org/u/RangeFu)
#### Post date: [December 15, 2020, 9:38pm UTC](https://discourse.julialang.org/t/easiest-way-to-do-replace-col1-col2-if-col3-in-a-dataframe/51891/3 "2020-12-15T21:38:18Z")

</div>

Partially inspired by your second approach, I come up with this self-helping solution before it’s officially tackled by DataFramesMeta:

Define a view version of `@where`, called `@within`:

```julia
# code copied from DataFramesMeta with return being view:
macro within(x, args...)
    esc(within_helper(x, args...))
end

function within_helper(x, args...)
    t = (DataFramesMeta.fun_to_vec(arg; nolhs = true, gensym_names = true) for arg in args)
    quote
        $within($x, $(t...))
    end
end

function within(df::AbstractDataFrame, @nospecialize(args...))
    res = DataFrames.select(df, args...; copycols = false)
    tokeep = DataFramesMeta.df_to_bool(res)
    @view df[tokeep, :]
end

```

so we could do:

```julia
dt = DataFrame(a = [1, 1, 2, 2], b = rand(4), c = Inf * ones(4))
@with @within(dt, :a .> 1) :b .= :c

```

---

<div class="post-metadata">

### Author: ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)
#### Post date: [December 16, 2020, 10:23am UTC](https://discourse.julialang.org/t/easiest-way-to-do-replace-col1-col2-if-col3-in-a-dataframe/51891/4 "2020-12-16T10:23:54Z")

</div>

excel like solution:

```
      df.a .= (df.b .- df.a) .* df.c .+df.a

```
