Julia - separate() tidyr equivalent

Viewed 63

Are there any functions in julia that is equivalent to separate() in R? I have a column with a long string with ":" as a delimiter and I want to split the string by those delimiter into 8 columns.

1 Answers

Assuming you use DataFrames.jl you can use the following.

First generate some test data:

julia> using DataFrames

julia> df = DataFrame(in = join.(eachrow(rand(1:9, 10, 8)), ":"))
10×1 DataFrame
 Row │ in
     │ String
─────┼─────────────────
   1 │ 8:2:9:4:1:9:3:1
   2 │ 9:6:9:9:8:1:9:5
   3 │ 2:4:9:8:5:4:8:7
   4 │ 8:2:2:9:5:3:7:7
   5 │ 1:4:6:1:3:9:2:1
   6 │ 8:6:1:5:1:4:8:8
   7 │ 4:6:4:4:4:4:8:8
   8 │ 4:3:3:5:1:4:3:4
   9 │ 9:5:5:7:5:3:4:3
  10 │ 4:5:8:5:2:5:7:4

The splitting could be done in many ways (we are fully flexible in how you can split your column). Here I just use the split function.

If you want auto-generated column names use:

julia> transform(df, :in => ByRow(x -> split(x, ":")) => AsTable)
10×9 DataFrame
 Row │ in               x1         x2         x3         x4         x5         x6         x7         x8        
     │ String           SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin… 
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │ 8:2:9:4:1:9:3:1  8          2          9          4          1          9          3          1
   2 │ 9:6:9:9:8:1:9:5  9          6          9          9          8          1          9          5
   3 │ 2:4:9:8:5:4:8:7  2          4          9          8          5          4          8          7
   4 │ 8:2:2:9:5:3:7:7  8          2          2          9          5          3          7          7
   5 │ 1:4:6:1:3:9:2:1  1          4          6          1          3          9          2          1
   6 │ 8:6:1:5:1:4:8:8  8          6          1          5          1          4          8          8
   7 │ 4:6:4:4:4:4:8:8  4          6          4          4          4          4          8          8
   8 │ 4:3:3:5:1:4:3:4  4          3          3          5          1          4          3          4
   9 │ 9:5:5:7:5:3:4:3  9          5          5          7          5          3          4          3
  10 │ 4:5:8:5:2:5:7:4  4          5          8          5          2          5          7          4

Alternatively pass your own column names:

julia> transform(df, :in => ByRow(x -> split(x, ":")) => "out" .* string.(1:8))
10×9 DataFrame
 Row │ in               out1       out2       out3       out4       out5       out6       out7       out8      
     │ String           SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin…  SubStrin… 
─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────
   1 │ 8:2:9:4:1:9:3:1  8          2          9          4          1          9          3          1
   2 │ 9:6:9:9:8:1:9:5  9          6          9          9          8          1          9          5
   3 │ 2:4:9:8:5:4:8:7  2          4          9          8          5          4          8          7
   4 │ 8:2:2:9:5:3:7:7  8          2          2          9          5          3          7          7
   5 │ 1:4:6:1:3:9:2:1  1          4          6          1          3          9          2          1
   6 │ 8:6:1:5:1:4:8:8  8          6          1          5          1          4          8          8
   7 │ 4:6:4:4:4:4:8:8  4          6          4          4          4          4          8          8
   8 │ 4:3:3:5:1:4:3:4  4          3          3          5          1          4          3          4
   9 │ 9:5:5:7:5:3:4:3  9          5          5          7          5          3          4          3
  10 │ 4:5:8:5:2:5:7:4  4          5          8          5          2          5          7          4

Note that the benefit of allowing custom parser is that you can in one shot convert the parts of your original string to their numeric values like this:

julia> transform(df, :in => ByRow(x -> parse.(Int, split(x, ":"))) => AsTable)
10×9 DataFrame
 Row │ in               x1     x2     x3     x4     x5     x6     x7     x8    
     │ String           Int64  Int64  Int64  Int64  Int64  Int64  Int64  Int64 
─────┼─────────────────────────────────────────────────────────────────────────
   1 │ 8:2:9:4:1:9:3:1      8      2      9      4      1      9      3      1 
   2 │ 9:6:9:9:8:1:9:5      9      6      9      9      8      1      9      5 
   3 │ 2:4:9:8:5:4:8:7      2      4      9      8      5      4      8      7 
   4 │ 8:2:2:9:5:3:7:7      8      2      2      9      5      3      7      7 
   5 │ 1:4:6:1:3:9:2:1      1      4      6      1      3      9      2      1 
   6 │ 8:6:1:5:1:4:8:8      8      6      1      5      1      4      8      8 
   7 │ 4:6:4:4:4:4:8:8      4      6      4      4      4      4      8      8 
   8 │ 4:3:3:5:1:4:3:4      4      3      3      5      1      4      3      4 
   9 │ 9:5:5:7:5:3:4:3      9      5      5      7      5      3      4      3 
  10 │ 4:5:8:5:2:5:7:4      4      5      8      5      2      5      7      4 

Here is another way to do it. Not as composable as the above but showing you the flexibility of the ecosystem:

julia> using CSV

julia> CSV.read(IOBuffer(join(df.in, "\n")), DataFrame, header=false, delim=":")
10×8 DataFrame
 Row │ Column1  Column2  Column3  Column4  Column5  Column6  Column7  Column8 
     │ Int64    Int64    Int64    Int64    Int64    Int64    Int64    Int64   
─────┼────────────────────────────────────────────────────────────────────────
   1 │       8        2        9        4        1        9        3        1
   2 │       9        6        9        9        8        1        9        5
   3 │       2        4        9        8        5        4        8        7
   4 │       8        2        2        9        5        3        7        7
   5 │       1        4        6        1        3        9        2        1
   6 │       8        6        1        5        1        4        8        8
   7 │       4        6        4        4        4        4        8        8
   8 │       4        3        3        5        1        4        3        4
   9 │       9        5        5        7        5        3        4        3
  10 │       4        5        8        5        2        5        7        4

julia> CSV.read(IOBuffer(join(df.in, "\n")), DataFrame, header="out" .* string.(1:8), delim=":")
10×8 DataFrame
 Row │ out1   out2   out3   out4   out5   out6   out7   out8  
     │ Int64  Int64  Int64  Int64  Int64  Int64  Int64  Int64 
─────┼────────────────────────────────────────────────────────
   1 │     8      2      9      4      1      9      3      1 
   2 │     9      6      9      9      8      1      9      5 
   3 │     2      4      9      8      5      4      8      7 
   4 │     8      2      2      9      5      3      7      7 
   5 │     1      4      6      1      3      9      2      1 
   6 │     8      6      1      5      1      4      8      8 
   7 │     4      6      4      4      4      4      8      8 
   8 │     4      3      3      5      1      4      3      4 
   9 │     9      5      5      7      5      3      4      3 
  10 │     4      5      8      5      2      5      7      4 
Related