# ! vs @view for indexing DataFrame

**URL:** <https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462>\
**Category:** Data\
**Tags:** dataframes\
**Created:** [October 28, 2022, 6:39pm UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462 "2022-10-28T18:39:23Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [October 28, 2022, 6:39pm UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462/1 "2022-10-28T18:39:23Z")

</div>

What is the difference in purpose between `!` and `@view` for indexing a DataFrame? @bkamins’ [indexing blog post](https://bkamins.github.io/julialang/2022/10/28/indexing.html) says

> When extracting the data from a data frame if you use `!` no copying of data is made. Instead, you just get a column as it is stored in the source data frame (or an appropriate view if you work with a view of a data frame)

but that seems to be what `@view` is for so I don’t see why `!` is needed.

```julia
julia> df = DataFrame(a=[1,2,3],b=[10,20,30])
3×2 DataFrame
 Row │ a b     
     │ Int64 Int64 
─────┼──────────────
   1 │ 1 10
   2 │ 2 20
   3 │ 3 30

julia> @view df[:,:a]
3-element view(::Vector{Int64}, :) with eltype Int64:
 1
 2
 3

julia> df[!,:a]
3-element Vector{Int64}:
 1
 2
 3

```

---

<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:** [October 28, 2022, 6:43pm UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462/2 "2022-10-28T18:43:15Z")

</div>

this is the difference between `a` and `@view a[:]`

---

<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:** [October 28, 2022, 7:25pm UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462/3 "2022-10-28T19:25:53Z")

</div>

To give a concrete example when this makes a difference. The type of `@view` is `SubArray` (usually), which means that, if you have code that dispatches on type of a vector the logic might be affected (probably not the result, but some optimizations might be disabled).

---

<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:** [October 28, 2022, 9:24pm UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462/4 "2022-10-28T21:24:26Z")

</div>

> [@bkamins](#):
>
> The type of `@view` is `SubArray` (usually)

I literally was thinking about why `view(a, ::Colon)` doesn’t just return `a`

---

<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:** [October 28, 2022, 9:27pm UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462/5 "2022-10-28T21:27:46Z")

</div>

There is a subtle difference here though in that `a[:]` makes a copy but `df[!, :x]` does not. The comparison would be correct for `df[:, :x]`. In general `df[:, :x]` behaves _exactly_ like array indexing but `df[!, :x]` has some different behaviors explained in the blog post.

---

<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:** [October 29, 2022, 6:34am UTC](https://discourse.julialang.org/t/vs-view-for-indexing-dataframe/89462/6 "2022-10-29T06:34:02Z")

</div>

> [@jling](#):
>
> I literally was thinking about why `view(a, ::Colon)` doesn’t just return `a`

I assume that the reason is to ensure some invariants. For example, views do not allow resizing.
