Sorting
Sorting is a fundamental component of data analysis. Basic sorting is trivial: just calling sort! will sort all columns, in place:
julia> using DataFrames, CSV
julia> iris = DataFrame(CSV.File(joinpath(dirname(pathof(DataFrames)), "../docs/src/assets/iris.csv")));
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 5.1 │ 3.5 │ 1.4 │ 0.2 │ Iris-setosa │
│ 2 │ 4.9 │ 3.0 │ 1.4 │ 0.2 │ Iris-setosa │
│ 3 │ 4.7 │ 3.2 │ 1.3 │ 0.2 │ Iris-setosa │
│ 4 │ 4.6 │ 3.1 │ 1.5 │ 0.2 │ Iris-setosa │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼────────────────┤
│ 1 │ 6.3 │ 2.5 │ 5.0 │ 1.9 │ Iris-virginica │
│ 2 │ 6.5 │ 3.0 │ 5.2 │ 2.0 │ Iris-virginica │
│ 3 │ 6.2 │ 3.4 │ 5.4 │ 2.3 │ Iris-virginica │
│ 4 │ 5.9 │ 3.0 │ 5.1 │ 1.8 │ Iris-virginica │
julia> sort!(iris);
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 4.3 │ 3.0 │ 1.1 │ 0.1 │ Iris-setosa │
│ 2 │ 4.4 │ 2.9 │ 1.4 │ 0.2 │ Iris-setosa │
│ 3 │ 4.4 │ 3.0 │ 1.3 │ 0.2 │ Iris-setosa │
│ 4 │ 4.4 │ 3.2 │ 1.3 │ 0.2 │ Iris-setosa │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼────────────────┤
│ 1 │ 7.7 │ 2.8 │ 6.7 │ 2.0 │ Iris-virginica │
│ 2 │ 7.7 │ 3.0 │ 6.1 │ 2.3 │ Iris-virginica │
│ 3 │ 7.7 │ 3.8 │ 6.7 │ 2.2 │ Iris-virginica │
│ 4 │ 7.9 │ 3.8 │ 6.4 │ 2.0 │ Iris-virginica │Observe that all columns are taken into account lexicographically when sorting the DataFrame.
You can also call the sort function to create a new DataFrame with freshly allocated sorted vectors.
In sorting DataFrames, you may want to sort different columns with different options. Here are some examples showing most of the possible options:
julia> sort!(iris, rev = true);
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼────────────────┤
│ 1 │ 7.9 │ 3.8 │ 6.4 │ 2.0 │ Iris-virginica │
│ 2 │ 7.7 │ 3.8 │ 6.7 │ 2.2 │ Iris-virginica │
│ 3 │ 7.7 │ 3.0 │ 6.1 │ 2.3 │ Iris-virginica │
│ 4 │ 7.7 │ 2.8 │ 6.7 │ 2.0 │ Iris-virginica │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 4.4 │ 3.2 │ 1.3 │ 0.2 │ Iris-setosa │
│ 2 │ 4.4 │ 3.0 │ 1.3 │ 0.2 │ Iris-setosa │
│ 3 │ 4.4 │ 2.9 │ 1.4 │ 0.2 │ Iris-setosa │
│ 4 │ 4.3 │ 3.0 │ 1.1 │ 0.1 │ Iris-setosa │
julia> sort!(iris, [:Species, :SepalWidth]);
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 4.5 │ 2.3 │ 1.3 │ 0.3 │ Iris-setosa │
│ 2 │ 4.4 │ 2.9 │ 1.4 │ 0.2 │ Iris-setosa │
│ 3 │ 5.0 │ 3.0 │ 1.6 │ 0.2 │ Iris-setosa │
│ 4 │ 4.9 │ 3.0 │ 1.4 │ 0.2 │ Iris-setosa │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼────────────────┤
│ 1 │ 6.2 │ 3.4 │ 5.4 │ 2.3 │ Iris-virginica │
│ 2 │ 7.2 │ 3.6 │ 6.1 │ 2.5 │ Iris-virginica │
│ 3 │ 7.9 │ 3.8 │ 6.4 │ 2.0 │ Iris-virginica │
│ 4 │ 7.7 │ 3.8 │ 6.7 │ 2.2 │ Iris-virginica │
julia> sort!(iris, (order(:Species, by=length), order(:SepalLength, rev=true)));
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 5.8 │ 4.0 │ 1.2 │ 0.2 │ Iris-setosa │
│ 2 │ 5.7 │ 3.8 │ 1.7 │ 0.3 │ Iris-setosa │
│ 3 │ 5.7 │ 4.4 │ 1.5 │ 0.4 │ Iris-setosa │
│ 4 │ 5.5 │ 3.5 │ 1.3 │ 0.2 │ Iris-setosa │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────────┤
│ 1 │ 5.1 │ 2.5 │ 3.0 │ 1.1 │ Iris-versicolor │
│ 2 │ 5.0 │ 2.0 │ 3.5 │ 1.0 │ Iris-versicolor │
│ 3 │ 5.0 │ 2.3 │ 3.3 │ 1.0 │ Iris-versicolor │
│ 4 │ 4.9 │ 2.4 │ 3.3 │ 1.0 │ Iris-versicolor │Keywords used above include rev (to sort in reverse), and by (to apply a function to values before comparing them). Each keyword can either be a single value, or can be a tuple or a vector, with values corresponding to individual columns.
As an alternative to using a vector or tuple values you can use order to specify an ordering for a particular column within a set of columns.
The following two examples show two ways to sort the iris dataset with the same result: :Species will be ordered in reverse order, and within groups, rows will be sorted by increasing :PetalLength:
julia> sort!(iris, (:Species, :PetalLength), rev=(true, false));
julia> julia> sort!(iris, (:Species, :PetalLength), rev=(true, false));
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼────────────────┤
│ 1 │ 4.9 │ 2.5 │ 4.5 │ 1.7 │ Iris-virginica │
│ 2 │ 6.2 │ 2.8 │ 4.8 │ 1.8 │ Iris-virginica │
│ 3 │ 6.0 │ 3.0 │ 4.8 │ 1.8 │ Iris-virginica │
│ 4 │ 6.3 │ 2.7 │ 4.9 │ 1.8 │ Iris-virginica │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 5.4 │ 3.9 │ 1.7 │ 0.4 │ Iris-setosa │
│ 2 │ 5.1 │ 3.3 │ 1.7 │ 0.5 │ Iris-setosa │
│ 3 │ 5.1 │ 3.8 │ 1.9 │ 0.4 │ Iris-setosa │
│ 4 │ 4.8 │ 3.4 │ 1.9 │ 0.2 │ Iris-setosa │
julia> sort!(iris, (order(:Species, rev=true), :PetalLength));
julia> first(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼────────────────┤
│ 1 │ 4.9 │ 2.5 │ 4.5 │ 1.7 │ Iris-virginica │
│ 2 │ 6.2 │ 2.8 │ 4.8 │ 1.8 │ Iris-virginica │
│ 3 │ 6.0 │ 3.0 │ 4.8 │ 1.8 │ Iris-virginica │
│ 4 │ 6.3 │ 2.7 │ 4.9 │ 1.8 │ Iris-virginica │
julia> last(iris, 4)
4×5 DataFrame
│ Row │ SepalLength │ SepalWidth │ PetalLength │ PetalWidth │ Species │
│ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ Float64⍰ │ String⍰ │
├─────┼─────────────┼────────────┼─────────────┼────────────┼─────────────┤
│ 1 │ 5.4 │ 3.9 │ 1.7 │ 0.4 │ Iris-setosa │
│ 2 │ 5.1 │ 3.3 │ 1.7 │ 0.5 │ Iris-setosa │
│ 3 │ 5.1 │ 3.8 │ 1.9 │ 0.4 │ Iris-setosa │
│ 4 │ 4.8 │ 3.4 │ 1.9 │ 0.2 │ Iris-setosa │