! vs @view for indexing DataFrame

What is the difference in purpose between ! and @view for indexing a DataFrame? @bkaminsindexing blog post 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> 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
1 Like

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

2 Likes

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).

1 Like

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

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.

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