Introduction

With the release of v1.0 of the DataFrames.jl package, it would seem appropriate to introduce a rather comprehensive cheatsheet of it. One that is of special use to people who come from tidyverse (arguably, the best data transformation syntax there is for combined expressiveness and brevity).

The order of topics is the same as dplyr cheatsheet.

using RDatasets, RCall, DataFrames, StatsBase, InteractiveErrors

R"library(dplyr)";

Setting up the data using RCall

data = dataset("datasets", "iris")

@rput data;

Summarize Cases

summarize

julia> R"summarize(data, avSL = mean(SepalLength), avSW = mean(SepalWidth))"
RObject{VecSxp}
      avSL     avSW
1 5.843333 3.057333

In Julia:

julia> combine(data, [:SepalLength, :SepalWidth] .=> mean .=> [:avSL, :avSW])
1×2 DataFrame
 Row │ avSL     avSW
Float64  Float64
─────┼──────────────────
   15.84333  3.05733

There are two important things to note. Firstly, broadcasting is mandatory. Secondly, the syntax allows for one factoring of the function in the middle.

Now let us summarize by different functions:

julia> combine(data, [:SepalLength, :SepalWidth] .=> [maximum, minimum] .=>
               [:maxSL, :minSW])
1×2 DataFrame
 Row │ maxSL    minSW
Float64  Float64
─────┼──────────────────
   17.9      2.0

And with anonymous functions:

julia> combine(data, [:SepalLength, :SepalWidth] .=> 
               [x->sum(x./100), x->sum(sqrt.(x))] .=> [:x1, :x2])
1×2 DataFrame
 Row │ x1       x2
Float64  Float64
─────┼──────────────────
   18.765  261.619

The r equivalent would be:

julia> R"""
       summarize(data, x1=sum(SepalLength/100), x2=sum(sqrt(SepalWidth)))
       """
RObject{VecSxp}
     x1       x2
1 8.765 261.6187

The reason that r is often-times nicer is quotation. With DataFrames.jl on the other hand, the idea is to simply pass the actual data and data identifiers around. This means greater flexibility but slightly more verbose syntax.

For instance, consider summarizing by matching column names:

julia> combine(data, filter(x->occursin.("Sepal", x), names(data)) .=> mean)
1×2 DataFrame
 Row │ SepalLength_mean  SepalWidth_mean
Float64           Float64
─────┼───────────────────────────────────
   15.84333          3.05733

In R, one needs to explicitly use other function to escape the quoting procedure:

julia> R"""
       summarize(data, across(contains("Sepal"), mean))
       """
RObject{VecSxp}
  SepalLength SepalWidth
1    5.843333   3.057333

Both have their ups and downs. Basically, the field of nonstandard evaluation will require its own functions, whereas, by avoiding that, one can rely on existing functions or at least only slightly modified functions (based on multiple dispatch for instance) to arrive at the desired results.

count

data = dataset("ggplot2", "mpg")

@rput data;

julia> R"""
       data <- as_tibble(data)
       count(data, Cyl, Drv)
       """
RObject{VecSxp}
# A tibble: 9 x 3
    Cyl Drv       n
  <int> <fct> <int>
1     4 4        23
2     4 f        58
3     5 f         4
4     6 4        32
5     6 f        43
6     6 r         4
7     8 4        48
8     8 f         1
9     8 r        21

Any function that operates on (sub)dataframes can be used immediately (nrow here):

julia> combine(groupby(data, [:Cyl, :Drv], sort = true), nrow)
9×3 DataFrame
 Row │ Cyl    Drv   nrow
Int32  Cat…  Int64
─────┼────────────────────
   14  4        23
   24  f        58
   35  f         4
   46  4        32
   56  f        43
   66  r         4
   78  4        48
   88  f         1
   98  r        21

This was a proper interlude to the next topic, grouping.

Group Cases

Ungroup

The general grouping operation in DataFrames.jl is as above, whereby a “sub” dataframe is recognized, perhaps not overly different from views in arrays.

Ungrouping is done rather automatically. The default value of ungroup in the transformation functions is true.

julia> df = groupby(data, [:Cyl, :Drv], sort = true)
GroupedDataFrame with 9 groups based on keys: Cyl, Drv
First Group (23 rows): Cyl = 4, Drv = CategoricalArrays.CategoricalValue{String, UInt8} "4"
 Row │ Manufacturer  Model              Displ    Year   Cyl    Trans         D 
     │ Categorical…  Categorical…       Float64  Int32  Int32  Categorical…  C 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4 quattro             1.8   1999      4  manual(m5)    4 
   2 │ audi          a4 quattro             1.8   1999      4  auto(l5)      4
   3 │ audi          a4 quattro             2.0   2008      4  manual(m6)    4
   4 │ audi          a4 quattro             2.0   2008      4  auto(s6)      4
   5 │ subaru        forester awd           2.5   1999      4  manual(m5)    4 
   6 │ subaru        forester awd           2.5   1999      4  auto(l4)      4
   7 │ subaru        forester awd           2.5   2008      4  manual(m5)    4
   8 │ subaru        forester awd           2.5   2008      4  manual(m5)    4
                                                               
  16 │ subaru        impreza awd            2.5   2008      4  auto(s4)      4 
  17 │ subaru        impreza awd            2.5   2008      4  manual(m5)    4
  18 │ subaru        impreza awd            2.5   2008      4  manual(m5)    4
  19 │ toyota        4runner 4wd            2.7   1999      4  manual(m5)    4
  20 │ toyota        4runner 4wd            2.7   1999      4  auto(l4)      4 
  21 │ toyota        toyota tacoma 4wd      2.7   1999      4  manual(m5)    4
  22 │ toyota        toyota tacoma 4wd      2.7   1999      4  auto(l4)      4
  23 │ toyota        toyota tacoma 4wd      2.7   2008      4  manual(m5)    4
                                                    5 columns and 7 rows omitted

Last Group (21 rows): Cyl = 8, Drv = CategoricalArrays.CategoricalValue{String, UInt8} "r"
 Row │ Manufacturer  Model               Displ    Year   Cyl    Trans          
     │ Categorical…  Categorical…        Float64  Int32  Int32  Categorical…   
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ chevrolet     c1500 suburban 2wd      5.3   2008      8  auto(l4)       
   2 │ chevrolet     c1500 suburban 2wd      5.3   2008      8  auto(l4)
   3 │ chevrolet     c1500 suburban 2wd      5.3   2008      8  auto(l4)
   4 │ chevrolet     c1500 suburban 2wd      5.7   1999      8  auto(l4)
   5 │ chevrolet     c1500 suburban 2wd      6.0   2008      8  auto(l4)       
   6 │ chevrolet     corvette                5.7   1999      8  manual(m6)
   7 │ chevrolet     corvette                5.7   1999      8  auto(l4)
   8 │ chevrolet     corvette                6.2   2008      8  manual(m6)
                                                               
  14 │ ford          mustang                 4.6   1999      8  auto(l4)       
  15 │ ford          mustang                 4.6   1999      8  manual(m5)
  16 │ ford          mustang                 4.6   2008      8  manual(m5)
  17 │ ford          mustang                 4.6   2008      8  auto(l5)
  18 │ ford          mustang                 5.4   2008      8  manual(m6)     
  19 │ lincoln       navigator 2wd           5.4   1999      8  auto(l4)
  20 │ lincoln       navigator 2wd           5.4   1999      8  auto(l4)
  21 │ lincoln       navigator 2wd           5.4   2008      8  auto(l6)
                                                    5 columns and 5 rows omitted

julia> df2 = combine(df, :)
234×11 DataFrame
 Row │ Cyl    Drv   Manufacturer  Model           Displ    Year   Trans        
Int32  Cat…  Cat…          Cat…            Float64  Int32  Cat…         
─────┼──────────────────────────────────────────────────────────────────────────
   14  4     audi          a4 quattro          1.8   1999  manual(m5)   
   24  4     audi          a4 quattro          1.8   1999  auto(l5)
   34  4     audi          a4 quattro          2.0   2008  manual(m6)
   44  4     audi          a4 quattro          2.0   2008  auto(s6)
   54  4     subaru        forester awd        2.5   1999  manual(m5)   
   64  4     subaru        forester awd        2.5   1999  auto(l4)
   74  4     subaru        forester awd        2.5   2008  manual(m5)
   84  4     subaru        forester awd        2.5   2008  manual(m5)
                                                                 
 2288  r     ford          mustang             4.6   1999  manual(m5)   
 2298  r     ford          mustang             4.6   2008  manual(m5)
 2308  r     ford          mustang             4.6   2008  auto(l5)
 2318  r     ford          mustang             5.4   2008  manual(m6)
 2328  r     lincoln       navigator 2wd       5.4   1999  auto(l4)     
 2338  r     lincoln       navigator 2wd       5.4   1999  auto(l4)
 2348  r     lincoln       navigator 2wd       5.4   2008  auto(l6)
                                                  4 columns and 219 rows omitted

The colon indicates that all items should be retained (whether columns or rows, depending on the specific argument it is used in place of). Here, it means to keep all rows and columns. However, since combine does ungrouping by default, that means retaining the original content of the data:

julia> nrow(df2) == nrow(data)
true

It is important to note, however, that presently, grouping changes the row order.

julia> df3 = combine(data, :)
234×11 DataFrame
 Row │ Manufacturer  Model         Displ    Year   Cyl    Trans         Drv    
     │ Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4                1.8   1999      4  auto(l5)      f      
   2 │ audi          a4                1.8   1999      4  manual(m5)    f
   3 │ audi          a4                2.0   2008      4  manual(m6)    f
   4 │ audi          a4                2.0   2008      4  auto(av)      f
   5 │ audi          a4                2.8   1999      6  auto(l5)      f      
   6 │ audi          a4                2.8   1999      6  manual(m5)    f
   7 │ audi          a4                3.1   2008      6  auto(av)      f
   8 │ audi          a4 quattro        1.8   1999      4  manual(m5)    4
                                                              
 228 │ volkswagen    passat            1.8   1999      4  manual(m5)    f      
 229 │ volkswagen    passat            1.8   1999      4  auto(l5)      f
 230 │ volkswagen    passat            2.0   2008      4  auto(s6)      f
 231 │ volkswagen    passat            2.0   2008      4  manual(m6)    f
 232 │ volkswagen    passat            2.8   1999      6  auto(l5)      f      
 233 │ volkswagen    passat            2.8   1999      6  manual(m5)    f
 234 │ volkswagen    passat            3.6   2008      6  auto(s6)      f
                                                  5 columns and 219 rows omitted

julia> df3 == data
true

whereas:

julia> df2 == data
false

In r, use of the ungroup function is needed.

Row-wise operation

Row-wise is, conceptually, setting each row as its own group. Nevertheless, oftentimes we do not need to think this way.

Say you want to know the minimum between 1.5 times the city miles per gallon and highway miles per galon for each model. In r, it would require this:

julia> R"""
       data %>% rowwise() %>% mutate(maxy = max(1.5*Cty, Hwy)) %>% 
           select(maxy, everything())
       """
RObject{VecSxp}
# A tibble: 234 x 12
# Rowwise: 
    maxy Manufacturer Model    Displ  Year   Cyl Trans   Drv     Cty   Hwy Fl   
   <dbl> <fct>        <fct>    <dbl> <int> <int> <fct>   <fct> <int> <int> <fct>
 1  29   audi         a4         1.8  1999     4 auto(l… f        18    29 p    
 2  31.5 audi         a4         1.8  1999     4 manual… f        21    29 p    
 3  31   audi         a4         2    2008     4 manual… f        20    31 p    
 4  31.5 audi         a4         2    2008     4 auto(a… f        21    30 p    
 5  26   audi         a4         2.8  1999     6 auto(l… f        16    26 p    
 6  27   audi         a4         2.8  1999     6 manual… f        18    26 p    
 7  27   audi         a4         3.1  2008     6 auto(a… f        18    27 p    
 8  27   audi         a4 quat…   1.8  1999     4 manual… 4        18    26 p    
 9  25   audi         a4 quat…   1.8  1999     4 auto(l… 4        16    25 p    
10  30   audi         a4 quat…   2    2008     4 manual… 4        20    28 p    
# … with 224 more rows, and 1 more variable: Class <fct>

In Julia, it is simply a matter of specifying the operation itself to rowwise:

julia> transform(data, [:Cty, :Hwy] => ByRow((x,y)->max(1.5*x,y)) => :maxy) |> 
       x->x[:, Cols([:maxy], :)]
234×12 DataFrame
 Row │ maxy     Manufacturer  Model         Displ    Year   Cyl    Trans       
Float64  Categorical…  Categorical…  Float64  Int32  Int32  Categorical 
─────┼──────────────────────────────────────────────────────────────────────────
   129.0  audi          a4                1.8   1999      4  auto(l5)    
   231.5  audi          a4                1.8   1999      4  manual(m5)
   331.0  audi          a4                2.0   2008      4  manual(m6)
   431.5  audi          a4                2.0   2008      4  auto(av)
   526.0  audi          a4                2.8   1999      6  auto(l5)    
   627.0  audi          a4                2.8   1999      6  manual(m5)
   727.0  audi          a4                3.1   2008      6  auto(av)
   827.0  audi          a4 quattro        1.8   1999      4  manual(m5)
                                                                
 22831.5  volkswagen    passat            1.8   1999      4  manual(m5)  
 22929.0  volkswagen    passat            1.8   1999      4  auto(l5)
 23028.5  volkswagen    passat            2.0   2008      4  auto(s6)
 23131.5  volkswagen    passat            2.0   2008      4  manual(m6)
 23226.0  volkswagen    passat            2.8   1999      6  auto(l5)    
 23327.0  volkswagen    passat            2.8   1999      6  manual(m5)
 23426.0  volkswagen    passat            3.6   2008      6  auto(s6)
                                                  6 columns and 219 rows omitted

Manipulate Cases

Filter

Filtering essentially uses the same principles as applied to any other Julia data structure, and can even use the conventional filter function for this purpose:

julia> filter(:Cty => x->(x>20), data)[:, Cols(:Cty,:)]
45×11 DataFrame
 Row │ Cty    Manufacturer  Model         Displ    Year   Cyl    Trans         
Int32  Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  
─────┼──────────────────────────────────────────────────────────────────────────
   121  audi          a4                1.8   1999      4  manual(m5)    
   221  audi          a4                2.0   2008      4  auto(av)
   322  chevrolet     malibu            2.4   2008      4  auto(l4)
   428  honda         civic             1.6   1999      4  manual(m5)
   524  honda         civic             1.6   1999      4  auto(l4)      
   625  honda         civic             1.6   1999      4  manual(m5)
   723  honda         civic             1.6   1999      4  manual(m5)
   824  honda         civic             1.6   1999      4  auto(l4)
                                                                 
  3921  volkswagen    jetta             2.5   2008      5  auto(s6)      
  4021  volkswagen    jetta             2.5   2008      5  manual(m5)
  4135  volkswagen    new beetle        1.9   1999      4  manual(m5)
  4229  volkswagen    new beetle        1.9   1999      4  auto(l4)
  4321  volkswagen    new beetle        2.0   1999      4  manual(m5)    
  4421  volkswagen    passat            1.8   1999      4  manual(m5)
  4521  volkswagen    passat            2.0   2008      4  manual(m6)
                                                   4 columns and 30 rows omitted

Julia data collection functions usually take a function as the first argument in order to facilitate the use of do blocks. This doesn’t look nice when using piping. Therefore, my suggestion is to stick with the subset function. Besides, apparently, filter doesn’t work on data groups.

julia> subset(data, :Cty => x->(x.>20))[:, Cols(:Cty,:)]
45×11 DataFrame
 Row │ Cty    Manufacturer  Model         Displ    Year   Cyl    Trans         
Int32  Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  
─────┼──────────────────────────────────────────────────────────────────────────
   121  audi          a4                1.8   1999      4  manual(m5)    
   221  audi          a4                2.0   2008      4  auto(av)
   322  chevrolet     malibu            2.4   2008      4  auto(l4)
   428  honda         civic             1.6   1999      4  manual(m5)
   524  honda         civic             1.6   1999      4  auto(l4)      
   625  honda         civic             1.6   1999      4  manual(m5)
   723  honda         civic             1.6   1999      4  manual(m5)
   824  honda         civic             1.6   1999      4  auto(l4)
                                                                 
  3921  volkswagen    jetta             2.5   2008      5  auto(s6)      
  4021  volkswagen    jetta             2.5   2008      5  manual(m5)
  4135  volkswagen    new beetle        1.9   1999      4  manual(m5)
  4229  volkswagen    new beetle        1.9   1999      4  auto(l4)
  4321  volkswagen    new beetle        2.0   1999      4  manual(m5)    
  4421  volkswagen    passat            1.8   1999      4  manual(m5)
  4521  volkswagen    passat            2.0   2008      4  manual(m6)
                                                   4 columns and 30 rows omitted

Distinct

julia> unique(data, [:Cyl, :Drv])
9×11 DataFrame
 Row │ Manufacturer  Model               Displ    Year   Cyl    Trans          
     │ Categorical…  Categorical…        Float64  Int32  Int32  Categorical…   
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4                      1.8   1999      4  auto(l5)       
   2 │ audi          a4                      2.8   1999      6  auto(l5)
   3 │ audi          a4 quattro              1.8   1999      4  manual(m5)
   4 │ audi          a4 quattro              2.8   1999      6  auto(l5)
   5 │ audi          a6 quattro              4.2   2008      8  auto(s6)       
   6 │ chevrolet     c1500 suburban 2wd      5.3   2008      8  auto(l4)
   7 │ ford          mustang                 3.8   1999      6  manual(m5)
   8 │ pontiac       grand prix              5.3   2008      8  auto(s4)
   9 │ volkswagen    jetta                   2.5   2008      5  auto(s6)       
                                                               5 columns omitted
julia> R"""
       distinct(data, Cyl, Drv)
       """
RObject{VecSxp}
# A tibble: 9 x 2
    Cyl Drv  
  <int> <fct>
1     4 f    
2     6 f    
3     4 4    
4     6 4    
5     8 4    
6     8 r    
7     6 r    
8     8 f    
9     5 f    

Slice

The point of a function such as slice is to be used in pipes really. Otherwise one can simply do this:

julia> R"""
       data[4:10,]
       """
RObject{VecSxp}
# A tibble: 7 x 11
  Manufacturer Model    Displ  Year   Cyl Trans   Drv     Cty   Hwy Fl    Class 
  <fct>        <fct>    <dbl> <int> <int> <fct>   <fct> <int> <int> <fct> <fct> 
1 audi         a4         2    2008     4 auto(a… f        21    30 p     compa…
2 audi         a4         2.8  1999     6 auto(l… f        16    26 p     compa…
3 audi         a4         2.8  1999     6 manual… f        18    26 p     compa…
4 audi         a4         3.1  2008     6 auto(a… f        18    27 p     compa…
5 audi         a4 quat…   1.8  1999     4 manual… 4        18    26 p     compa…
6 audi         a4 quat…   1.8  1999     4 auto(l… 4        16    25 p     compa…
7 audi         a4 quat…   2    2008     4 manual… 4        20    28 p     compa…

Same with julia:

julia> data[4:10,:]
7×11 DataFrame
 Row │ Manufacturer  Model         Displ    Year   Cyl    Trans         Drv    
     │ Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4                2.0   2008      4  auto(av)      f      
   2 │ audi          a4                2.8   1999      6  auto(l5)      f
   3 │ audi          a4                2.8   1999      6  manual(m5)    f
   4 │ audi          a4                3.1   2008      6  auto(av)      f
   5 │ audi          a4 quattro        1.8   1999      4  manual(m5)    4      
   6 │ audi          a4 quattro        1.8   1999      4  auto(l5)      4
   7 │ audi          a4 quattro        2.0   2008      4  manual(m6)    4
                                                               5 columns omitted

Slice-sample

The StatsBase module can be used here.

julia> data[rand(1:nrow(data), 10),:]
10×11 DataFrame
 Row │ Manufacturer  Model              Displ    Year   Cyl    Trans         D 
     │ Categorical…  Categorical…       Float64  Int32  Int32  Categorical…  C 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ ford          explorer 4wd           4.0   1999      6  auto(l5)      4 
   2 │ nissan        altima                 2.4   1999      4  auto(l4)      f
   3 │ volkswagen    new beetle             1.9   1999      4  manual(m5)    f
   4 │ hyundai       tiburon                2.7   2008      6  manual(m5)    f
   5 │ toyota        toyota tacoma 4wd      2.7   1999      4  manual(m5)    4 
   6 │ chevrolet     corvette               6.2   2008      8  manual(m6)    r
   7 │ hyundai       sonata                 3.3   2008      6  auto(l5)      f
   8 │ dodge         durango 4wd            5.9   1999      8  auto(l4)      4
   9 │ ford          f150 pickup 4wd        4.6   1999      8  manual(m5)    4 
  10 │ volkswagen    new beetle             2.5   2008      5  auto(s6)      f
                                                               5 columns omitted

Slice min and max

This is just a convenience function:

julia> data[data.Cty .>= quantile(data.Cty, 0.75),:]
76×11 DataFrame
 Row │ Manufacturer  Model         Displ    Year   Cyl    Trans         Drv    
     │ Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4                1.8   1999      4  manual(m5)    f      
   2 │ audi          a4                2.0   2008      4  manual(m6)    f
   3 │ audi          a4                2.0   2008      4  auto(av)      f
   4 │ audi          a4 quattro        2.0   2008      4  manual(m6)    4
   5 │ audi          a4 quattro        2.0   2008      4  auto(s6)      4      
   6 │ chevrolet     malibu            2.4   1999      4  auto(l4)      f
   7 │ chevrolet     malibu            2.4   2008      4  auto(l4)      f
   8 │ honda         civic             1.6   1999      4  manual(m5)    f
                                                              
  70 │ volkswagen    new beetle        2.0   1999      4  manual(m5)    f      
  71 │ volkswagen    new beetle        2.0   1999      4  auto(l4)      f
  72 │ volkswagen    new beetle        2.5   2008      5  manual(m5)    f
  73 │ volkswagen    new beetle        2.5   2008      5  auto(s6)      f
  74 │ volkswagen    passat            1.8   1999      4  manual(m5)    f      
  75 │ volkswagen    passat            2.0   2008      4  auto(s6)      f
  76 │ volkswagen    passat            2.0   2008      4  manual(m6)    f
                                                   5 columns and 61 rows omitted

The R code:

julia> R"""
       slice_max(data, Cty, prop = 0.25)
       """
RObject{VecSxp}
# A tibble: 76 x 11
   Manufacturer Model   Displ  Year   Cyl Trans   Drv     Cty   Hwy Fl    Class 
   <fct>        <fct>   <dbl> <int> <int> <fct>   <fct> <int> <int> <fct> <fct> 
 1 volkswagen   new be…   1.9  1999     4 manual… f        35    44 d     subco…
 2 volkswagen   jetta     1.9  1999     4 manual… f        33    44 d     compa…
 3 volkswagen   new be…   1.9  1999     4 auto(l… f        29    41 d     subco…
 4 honda        civic     1.6  1999     4 manual… f        28    33 r     subco…
 5 toyota       corolla   1.8  2008     4 manual… f        28    37 r     compa…
 6 honda        civic     1.8  2008     4 manual… f        26    34 r     subco…
 7 toyota       corolla   1.8  1999     4 manual… f        26    35 r     compa…
 8 toyota       corolla   1.8  2008     4 auto(l… f        26    35 r     compa…
 9 honda        civic     1.6  1999     4 manual… f        25    32 r     subco…
10 honda        civic     1.8  2008     4 auto(l… f        25    36 r     subco…
# … with 66 more rows

Slice head and tail

again, mostly meaningful for pipes. Nevertheless:

julia> data[end-5:end,:]
6×11 DataFrame
 Row │ Manufacturer  Model         Displ    Year   Cyl    Trans         Drv    
     │ Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ volkswagen    passat            1.8   1999      4  auto(l5)      f      
   2 │ volkswagen    passat            2.0   2008      4  auto(s6)      f
   3 │ volkswagen    passat            2.0   2008      4  manual(m6)    f
   4 │ volkswagen    passat            2.8   1999      6  auto(l5)      f
   5 │ volkswagen    passat            2.8   1999      6  manual(m5)    f      
   6 │ volkswagen    passat            3.6   2008      6  auto(s6)      f
                                                               5 columns omitted

Arrange

Instead of arrange, sort is used. The syntax is very clear:

julia> sort(data, [order(:Year, rev=true), :Displ])
234×11 DataFrame
 Row │ Manufacturer  Model                Displ    Year   Cyl    Trans         
     │ Categorical…  Categorical…         Float64  Int32  Int32  Categorical…  
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ honda         civic                    1.8   2008      4  manual(m5)    
   2 │ honda         civic                    1.8   2008      4  auto(l5)
   3 │ honda         civic                    1.8   2008      4  auto(l5)
   4 │ toyota        corolla                  1.8   2008      4  manual(m5)
   5 │ toyota        corolla                  1.8   2008      4  auto(l4)      
   6 │ audi          a4                       2.0   2008      4  manual(m6)
   7 │ audi          a4                       2.0   2008      4  auto(av)
   8 │ audi          a4 quattro               2.0   2008      4  manual(m6)
                                                               
 228 │ chevrolet     c1500 suburban 2wd       5.7   1999      8  auto(l4)      
 229 │ chevrolet     corvette                 5.7   1999      8  manual(m6)
 230 │ chevrolet     corvette                 5.7   1999      8  auto(l4)
 231 │ chevrolet     k1500 tahoe 4wd          5.7   1999      8  auto(l4)
 232 │ dodge         durango 4wd              5.9   1999      8  auto(l4)      
 233 │ dodge         ram 1500 pickup 4wd      5.9   1999      8  auto(l4)
 234 │ chevrolet     k1500 tahoe 4wd          6.5   1999      8  auto(l4)
                                                  5 columns and 219 rows omitted
julia> R"""
       arrange(data, desc(Year), Displ)
       """
RObject{VecSxp}
# A tibble: 234 x 11
   Manufacturer Model   Displ  Year   Cyl Trans   Drv     Cty   Hwy Fl    Class 
   <fct>        <fct>   <dbl> <int> <int> <fct>   <fct> <int> <int> <fct> <fct> 
 1 honda        civic     1.8  2008     4 manual… f        26    34 r     subco…
 2 honda        civic     1.8  2008     4 auto(l… f        25    36 r     subco…
 3 honda        civic     1.8  2008     4 auto(l… f        24    36 c     subco…
 4 toyota       corolla   1.8  2008     4 manual… f        28    37 r     compa…
 5 toyota       corolla   1.8  2008     4 auto(l… f        26    35 r     compa…
 6 audi         a4        2    2008     4 manual… f        20    31 p     compa…
 7 audi         a4        2    2008     4 auto(a… f        21    30 p     compa…
 8 audi         a4 qua…   2    2008     4 manual… 4        20    28 p     compa…
 9 audi         a4 qua…   2    2008     4 auto(s… 4        19    27 p     compa…
10 honda        civic     2    2008     4 manual… f        21    29 p     subco…
# … with 224 more rows

One can in fact use any kind of sorting. See the sorting section in DataFrames.jl.

Adding row at position

Again, this is just a convenience function. Let’s add a duplicate row for instance:

julia> vcat(data, DataFrame(data[5,:]))
235×11 DataFrame
 Row │ Manufacturer  Model         Displ    Year   Cyl    Trans         Drv    
     │ Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4                1.8   1999      4  auto(l5)      f      
   2 │ audi          a4                1.8   1999      4  manual(m5)    f
   3 │ audi          a4                2.0   2008      4  manual(m6)    f
   4 │ audi          a4                2.0   2008      4  auto(av)      f
   5 │ audi          a4                2.8   1999      6  auto(l5)      f      
   6 │ audi          a4                2.8   1999      6  manual(m5)    f
   7 │ audi          a4                3.1   2008      6  auto(av)      f
   8 │ audi          a4 quattro        1.8   1999      4  manual(m5)    4
                                                              
 229 │ volkswagen    passat            1.8   1999      4  auto(l5)      f      
 230 │ volkswagen    passat            2.0   2008      4  auto(s6)      f
 231 │ volkswagen    passat            2.0   2008      4  manual(m6)    f
 232 │ volkswagen    passat            2.8   1999      6  auto(l5)      f
 233 │ volkswagen    passat            2.8   1999      6  manual(m5)    f      
 234 │ volkswagen    passat            3.6   2008      6  auto(s6)      f
 235 │ audi          a4                2.8   1999      6  auto(l5)      f
                                                  5 columns and 220 rows omitted

The issue is that specifying the position at which to insert the row can take extra work. See also append! and push! with the catch being modification of the original dataframe.

Extract variables

Conventional indexing can be used:

pull

One can just use the fact that the dataframe is a collection of vectors in a dictionary-like relation:

julia> data.Hwy
234-element Vector{Int32}:
 29
 29
 31
 30
 26
 26
 27
 26
 25
 28
  
 28
 29
 29
 29
 28
 29
 26
 26
 26
julia> R"pull(data, Hwy)"
RObject{IntSxp}
  [1] 29 29 31 30 26 26 27 26 25 28 27 25 25 25 25 24 25 23 20 15 20 17 17 26 23
 [26] 26 25 24 19 14 15 17 27 30 26 29 26 24 24 22 22 24 24 17 22 21 23 23 19 18
 [51] 17 17 19 19 12 17 15 17 17 12 17 16 18 15 16 12 17 17 16 12 15 16 17 15 17
 [76] 17 18 17 19 17 19 19 17 17 17 16 16 17 15 17 26 25 26 24 21 22 23 22 20 33
[101] 32 32 29 32 34 36 36 29 26 27 30 31 26 26 28 26 29 28 27 24 24 24 22 19 20
[126] 17 12 19 18 14 15 18 18 15 17 16 18 17 19 19 17 29 27 31 32 27 26 26 25 25
[151] 17 17 20 18 26 26 27 28 25 25 24 27 25 26 23 26 26 26 26 25 27 25 27 20 20
[176] 19 17 20 17 29 27 31 31 26 26 28 27 29 31 31 26 26 27 30 33 35 37 35 15 18
[201] 20 20 22 17 19 18 20 29 26 29 29 24 44 29 26 29 29 29 29 23 24 44 41 29 26
[226] 28 29 29 29 28 29 26 26 26

select

julia> data[:, [:Hwy, :Cty]]
234×2 DataFrame
 Row │ Hwy    Cty
Int32  Int32
─────┼──────────────
   129     18
   229     21
   331     20
   430     21
   526     16
   626     18
   727     18
   826     18
        
 22829     21
 22929     18
 23028     19
 23129     21
 23226     16
 23326     18
 23426     17
    219 rows omitted

Note that when selecting only a single column, it is no different than the dot syntax and the return structure is not dataframe:

julia> data[:, :Hwy]
234-element Vector{Int32}:
 29
 29
 31
 30
 26
 26
 27
 26
 25
 28
  
 28
 29
 29
 29
 28
 29
 26
 26
 26

Of course, wrapping in vector the column symbol gives the desired result:

julia> data[:, [:Hwy]]
234×1 DataFrame
 Row │ Hwy
Int32
─────┼───────
   129
   229
   331
   430
   526
   626
   727
   826
  
 22829
 22929
 23028
 23129
 23226
 23326
 23426
219 rows omitted

relocate

Just use Cols as before. For instance, to put columns starting with m at front:

julia> data[:, Cols(filter(x->occursin(r"^[mM].*", x), names(data)),
           :Year, :Class, :)]
234×11 DataFrame
 Row │ Manufacturer  Model         Year   Class         Displ    Cyl    Trans  
     │ Categorical…  Categorical…  Int32  Categorical…  Float64  Int32  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4             1999  compact           1.8      4  auto(l 
   2 │ audi          a4             1999  compact           1.8      4  manual
   3 │ audi          a4             2008  compact           2.0      4  manual
   4 │ audi          a4             2008  compact           2.0      4  auto(a
   5 │ audi          a4             1999  compact           2.8      6  auto(l 
   6 │ audi          a4             1999  compact           2.8      6  manual
   7 │ audi          a4             2008  compact           3.1      6  auto(a
   8 │ audi          a4 quattro     1999  compact           1.8      4  manual
                                                              
 228 │ volkswagen    passat         1999  midsize           1.8      4  manual 
 229 │ volkswagen    passat         1999  midsize           1.8      4  auto(l
 230 │ volkswagen    passat         2008  midsize           2.0      4  auto(s
 231 │ volkswagen    passat         2008  midsize           2.0      4  manual
 232 │ volkswagen    passat         1999  midsize           2.8      6  auto(l 
 233 │ volkswagen    passat         1999  midsize           2.8      6  manual
 234 │ volkswagen    passat         2008  midsize           3.6      6  auto(s
                                                  5 columns and 219 rows omitted

To put Model after Year:

julia> data[:, Cols( setdiff(propertynames(data), [:Model]) |> x->insert!(x,
           findfirst(x .== :Year) + 1, :Model))]
234×11 DataFrame
 Row │ Manufacturer  Displ    Year   Model         Cyl    Trans         Drv    
     │ Categorical…  Float64  Int32  Categorical…  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi              1.8   1999  a4                4  auto(l5)      f      
   2 │ audi              1.8   1999  a4                4  manual(m5)    f
   3 │ audi              2.0   2008  a4                4  manual(m6)    f
   4 │ audi              2.0   2008  a4                4  auto(av)      f
   5 │ audi              2.8   1999  a4                6  auto(l5)      f      
   6 │ audi              2.8   1999  a4                6  manual(m5)    f
   7 │ audi              3.1   2008  a4                6  auto(av)      f
   8 │ audi              1.8   1999  a4 quattro        4  manual(m5)    4
                                                              
 228 │ volkswagen        1.8   1999  passat            4  manual(m5)    f      
 229 │ volkswagen        1.8   1999  passat            4  auto(l5)      f
 230 │ volkswagen        2.0   2008  passat            4  auto(s6)      f
 231 │ volkswagen        2.0   2008  passat            4  manual(m6)    f
 232 │ volkswagen        2.8   1999  passat            6  auto(l5)      f      
 233 │ volkswagen        2.8   1999  passat            6  manual(m5)    f
 234 │ volkswagen        3.6   2008  passat            6  auto(s6)      f
                                                  5 columns and 219 rows omitted
julia> R"""
       relocate(data, Model, .after = Year)
       """
RObject{VecSxp}
# A tibble: 234 x 11
   Manufacturer Displ  Year Model      Cyl Trans   Drv     Cty   Hwy Fl    Class
   <fct>        <dbl> <int> <fct>    <int> <fct>   <fct> <int> <int> <fct> <fct>
 1 audi           1.8  1999 a4           4 auto(l… f        18    29 p     comp…
 2 audi           1.8  1999 a4           4 manual… f        21    29 p     comp…
 3 audi           2    2008 a4           4 manual… f        20    31 p     comp…
 4 audi           2    2008 a4           4 auto(a… f        21    30 p     comp…
 5 audi           2.8  1999 a4           6 auto(l… f        16    26 p     comp…
 6 audi           2.8  1999 a4           6 manual… f        18    26 p     comp…
 7 audi           3.1  2008 a4           6 auto(a… f        18    27 p     comp…
 8 audi           1.8  1999 a4 quat…     4 manual… 4        18    26 p     comp…
 9 audi           1.8  1999 a4 quat…     4 auto(l… 4        16    25 p     comp…
10 audi           2    2008 a4 quat…     4 manual… 4        20    28 p     comp…
# … with 224 more rows

Currently, there aren’t any helper functions for selection, though the general procedure isn’t that verbose in base Julia either.

Across function

As mentioned in the beginning, Julia provides quite flexible ways of combining data, and there is no need for extra across functions, mainly due to the employment of the broadcasting concept.

Making new variables

mutate, and transmutate

The mutate equivalent is transform. The select function is the transmutate equivalent, which only selects the specifided columns, and after applying the specified functions, returns only said columns.

rename

julia> rename(data, [:Model, :Year] .=> [:type, :date])
234×11 DataFrame
 Row │ Manufacturer  type          Displ    date   Cyl    Trans         Drv    
     │ Categorical…  Categorical…  Float64  Int32  Int32  Categorical…  Catego 
─────┼──────────────────────────────────────────────────────────────────────────
   1 │ audi          a4                1.8   1999      4  auto(l5)      f      
   2 │ audi          a4                1.8   1999      4  manual(m5)    f
   3 │ audi          a4                2.0   2008      4  manual(m6)    f
   4 │ audi          a4                2.0   2008      4  auto(av)      f
   5 │ audi          a4                2.8   1999      6  auto(l5)      f      
   6 │ audi          a4                2.8   1999      6  manual(m5)    f
   7 │ audi          a4                3.1   2008      6  auto(av)      f
   8 │ audi          a4 quattro        1.8   1999      4  manual(m5)    4
                                                              
 228 │ volkswagen    passat            1.8   1999      4  manual(m5)    f      
 229 │ volkswagen    passat            1.8   1999      4  auto(l5)      f
 230 │ volkswagen    passat            2.0   2008      4  auto(s6)      f
 231 │ volkswagen    passat            2.0   2008      4  manual(m6)    f
 232 │ volkswagen    passat            2.8   1999      6  auto(l5)      f      
 233 │ volkswagen    passat            2.8   1999      6  manual(m5)    f
 234 │ volkswagen    passat            3.6   2008      6  auto(s6)      f
                                                  5 columns and 219 rows omitted

This concludes the first page of the cheatsheet.