{
"cells": [
{
"cell_type": "markdown",
"source": [
"# Load and save DataFrames\n",
"\n",
"We do not cover all features of the packages. Please refer to their documentation to learn them.\n",
"\n",
"- https://github.com/ExpandingMan/Arrow.jl\n",
"- https://github.com/invenia/JLSO.jl\n",
"- https://github.com/JuliaData/JSONTables.jl\n",
"- https://github.com/xiaodaigh/JDF.jl\n",
"\n",
"Here we'll load `CSV.jl` to read and write CSV files and `Arrow.jl`, `JLSO.jl`, and serialization, which allow us to work with a binary format and `JSONTables.jl` for JSON interaction. Finally we consider a custom `JDF.jl` format."
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"using DataFrames\n",
"using Arrow\n",
"using CSV\n",
"using Serialization\n",
"using JLSO\n",
"using JSONTables\n",
"using CodecZlib\n",
"using ZipFile\n",
"using JDF\n",
"using StatsPlots ## for charts\n",
"using Mmap ## for compression"
],
"metadata": {},
"execution_count": 1
},
{
"cell_type": "markdown",
"source": [
"Let's create a simple `DataFrame` for testing purposes,"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"
1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 2
}
],
"cell_type": "code",
"source": [
"x = DataFrame(\n",
" A=[true, false, true], B=[1, 2, missing],\n",
" C=[missing, \"b\", \"c\"], D=['a', missing, 'c']\n",
")"
],
"metadata": {},
"execution_count": 2
},
{
"cell_type": "markdown",
"source": [
"and use `eltypes` to look at the columnwise types."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, String}\n Union{Missing, Char}"
},
"metadata": {},
"execution_count": 3
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(x))"
],
"metadata": {},
"execution_count": 3
},
{
"cell_type": "markdown",
"source": [
"## CSV.jl\n",
"Let's use `CSV` to save `x` to disk; make sure `x1.csv` does not conflict with some file in your working directory."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\"x1.csv\""
},
"metadata": {},
"execution_count": 4
}
],
"cell_type": "code",
"source": [
"CSV.write(\"x1.csv\", x)"
],
"metadata": {},
"execution_count": 4
},
{
"cell_type": "markdown",
"source": [
"Now we can see how it was saved by reading `x.csv`."
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A,B,C,D\n",
"true,1,,a\n",
"false,2,b,\n",
"true,,c,c\n"
]
}
],
"cell_type": "code",
"source": [
"print(read(\"x1.csv\", String))"
],
"metadata": {},
"execution_count": 5
},
{
"cell_type": "markdown",
"source": [
"We can also load it back as a data frame"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String1? \u001b[0m\u001b[90m String1? \u001b[0m\n─────┼────────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 6
}
],
"cell_type": "code",
"source": [
"y = CSV.read(\"x1.csv\", DataFrame)"
],
"metadata": {},
"execution_count": 6
},
{
"cell_type": "markdown",
"source": [
"Note that when loading in a `DataFrame` from a `CSV` the column type for columns `:C` `:D` have changed to use special strings defined in the InlineStrings.jl package."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, InlineStrings.String1}\n Union{Missing, InlineStrings.String1}"
},
"metadata": {},
"execution_count": 7
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(y))"
],
"metadata": {},
"execution_count": 7
},
{
"cell_type": "markdown",
"source": [
"## Serialization by JDF.jl and JLSO.jl\n",
"\n",
"Now we use serialization to save `x`.\n",
"\n",
"There are two ways to perform serialization. The first way is to use the `Serialization.serialize` as below:\n",
"\n",
"Note that in general, this process _will not work_ if the reading and writing are done by different versions of Julia, or an instance of Julia with a different system image."
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"open(\"x.bin\", \"w\") do io\n",
" serialize(io, x)\n",
"end"
],
"metadata": {},
"execution_count": 8
},
{
"cell_type": "markdown",
"source": [
"Now we load back the saved file to `y` variable. Again `y` is identical to `x`. However, please beware that if you session does not have DataFrames.jl loaded, then it may not recognize the content as DataFrames.jl"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 9
}
],
"cell_type": "code",
"source": [
"y = open(deserialize, \"x.bin\")"
],
"metadata": {},
"execution_count": 9
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, String}\n Union{Missing, Char}"
},
"metadata": {},
"execution_count": 10
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(y))"
],
"metadata": {},
"execution_count": 10
},
{
"cell_type": "markdown",
"source": [
"### JDF.jl\n",
"`JDF.jl` is a relatively new package designed to serialize DataFrames. You can save a DataFrame with the `savejdf` function.\n",
"For more details about design assumptions and limitations of `JDF.jl` please check out https://github.com/xiaodaigh/JDF.jl."
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"JDF.save(\"x.jdf\", x);"
],
"metadata": {},
"execution_count": 11
},
{
"cell_type": "markdown",
"source": [
"To load the saved JDF file, one can use the `loadjdf` function"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 12
}
],
"cell_type": "code",
"source": [
"x_loaded = JDF.load(\"x.jdf\") |> DataFrame"
],
"metadata": {},
"execution_count": 12
},
{
"cell_type": "markdown",
"source": [
"You can see that they are the same"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "true"
},
"metadata": {},
"execution_count": 13
}
],
"cell_type": "code",
"source": [
"isequal(x_loaded, x)"
],
"metadata": {},
"execution_count": 13
},
{
"cell_type": "markdown",
"source": [
"JDF.jl offers the ability to load only certain columns from disk to help with working with large files.\n",
"set up a JDFFile which is a on disk representation of `x` backed by JDF.jl"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "JDF.JDFFile{String}(\"x.jdf\")"
},
"metadata": {},
"execution_count": 14
}
],
"cell_type": "code",
"source": [
"x_ondisk = jdf\"x.jdf\""
],
"metadata": {},
"execution_count": 14
},
{
"cell_type": "markdown",
"source": [
"We can see all the names of `x` without loading it into memory"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Symbol}:\n :A\n :B\n :C\n :D"
},
"metadata": {},
"execution_count": 15
}
],
"cell_type": "code",
"source": [
"names(x_ondisk)"
],
"metadata": {},
"execution_count": 15
},
{
"cell_type": "markdown",
"source": [
"The below is an example of how to load only columns `:A` and `:D`"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×2 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼────────────────\n 1 │ true a\n 2 │ false \u001b[90m missing \u001b[0m\n 3 │ true c",
"text/html": [
"1 | true | a |
2 | false | missing |
3 | true | c |
"
]
},
"metadata": {},
"execution_count": 16
}
],
"cell_type": "code",
"source": [
"xd = JDF.load(x_ondisk; cols=[\"A\", \"D\"]) |> DataFrame"
],
"metadata": {},
"execution_count": 16
},
{
"cell_type": "markdown",
"source": [
"### JLSO.jl\n",
"Another way to perform serialization is by using the [JLSO.jl](https://github.com/invenia/JLSO.jl) library:"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"JLSO.save(\"x.jlso\", :data => x)"
],
"metadata": {},
"execution_count": 17
},
{
"cell_type": "markdown",
"source": [
"Now we can load back the file to `y`"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 18
}
],
"cell_type": "code",
"source": [
"y = JLSO.load(\"x.jlso\")[:data]"
],
"metadata": {},
"execution_count": 18
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, String}\n Union{Missing, Char}"
},
"metadata": {},
"execution_count": 19
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(y))"
],
"metadata": {},
"execution_count": 19
},
{
"cell_type": "markdown",
"source": [
"## JSONTables.jl\n",
"Often you might need to read and write data stored in JSON format. JSONTables.jl provides a way to process them in row-oriented or column-oriented layout. We present both options below."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "106"
},
"metadata": {},
"execution_count": 20
}
],
"cell_type": "code",
"source": [
"open(io -> arraytable(io, x), \"x1.json\", \"w\")"
],
"metadata": {},
"execution_count": 20
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "76"
},
"metadata": {},
"execution_count": 21
}
],
"cell_type": "code",
"source": [
"open(io -> objecttable(io, x), \"x2.json\", \"w\")"
],
"metadata": {},
"execution_count": 21
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[{\"A\":true,\"B\":1,\"C\":null,\"D\":\"a\"},{\"A\":false,\"B\":2,\"C\":\"b\",\"D\":null},{\"A\":true,\"B\":null,\"C\":\"c\",\"D\":\"c\"}]"
]
}
],
"cell_type": "code",
"source": [
"print(read(\"x1.json\", String))"
],
"metadata": {},
"execution_count": 22
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\"A\":[true,false,true],\"B\":[1,2,null],\"C\":[null,\"b\",\"c\"],\"D\":[\"a\",null,\"c\"]}"
]
}
],
"cell_type": "code",
"source": [
"print(read(\"x2.json\", String))"
],
"metadata": {},
"execution_count": 23
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m String? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 24
}
],
"cell_type": "code",
"source": [
"y1 = open(jsontable, \"x1.json\") |> DataFrame"
],
"metadata": {},
"execution_count": 24
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, String}\n Union{Missing, String}"
},
"metadata": {},
"execution_count": 25
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(y1))"
],
"metadata": {},
"execution_count": 25
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m String? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 26
}
],
"cell_type": "code",
"source": [
"y2 = open(jsontable, \"x2.json\") |> DataFrame"
],
"metadata": {},
"execution_count": 26
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, String}\n Union{Missing, String}"
},
"metadata": {},
"execution_count": 27
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(y2))"
],
"metadata": {},
"execution_count": 27
},
{
"cell_type": "markdown",
"source": [
"## Arrow.jl\n",
"Finally we use Apache Arrow format that allows, in particular, for data interchange with R or Python."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\"x.arrow\""
},
"metadata": {},
"execution_count": 28
}
],
"cell_type": "code",
"source": [
"Arrow.write(\"x.arrow\", x)"
],
"metadata": {},
"execution_count": 28
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 29
}
],
"cell_type": "code",
"source": [
"y = Arrow.Table(\"x.arrow\") |> DataFrame"
],
"metadata": {},
"execution_count": 29
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "4-element Vector{Type}:\n Bool\n Union{Missing, Int64}\n Union{Missing, String}\n Union{Missing, Char}"
},
"metadata": {},
"execution_count": 30
}
],
"cell_type": "code",
"source": [
"eltype.(eachcol(y))"
],
"metadata": {},
"execution_count": 30
},
{
"cell_type": "markdown",
"source": [
"Note that columns of `y` are immutable"
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ReadOnlyMemoryError()"
]
}
],
"cell_type": "code",
"source": [
"try\n",
" y.A[1] = false\n",
"catch e\n",
" show(e)\n",
"end"
],
"metadata": {},
"execution_count": 31
},
{
"cell_type": "markdown",
"source": [
"This is because `Arrow.Table` uses memory mapping and thus uses a custom vector types:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "3-element Arrow.BoolVector{Bool}:\n 1\n 0\n 1"
},
"metadata": {},
"execution_count": 32
}
],
"cell_type": "code",
"source": [
"y.A"
],
"metadata": {},
"execution_count": 32
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "3-element Arrow.Primitive{Union{Missing, Int64}, Vector{Int64}}:\n 1\n 2\n missing"
},
"metadata": {},
"execution_count": 33
}
],
"cell_type": "code",
"source": [
"y.B"
],
"metadata": {},
"execution_count": 33
},
{
"cell_type": "markdown",
"source": [
"You can get standard Julia Base vectors by copying a data frame"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m A \u001b[0m\u001b[1m B \u001b[0m\u001b[1m C \u001b[0m\u001b[1m D \u001b[0m\n │\u001b[90m Bool \u001b[0m\u001b[90m Int64? \u001b[0m\u001b[90m String? \u001b[0m\u001b[90m Char? \u001b[0m\n─────┼──────────────────────────────────\n 1 │ true 1 \u001b[90m missing \u001b[0m a\n 2 │ false 2 b \u001b[90m missing \u001b[0m\n 3 │ true \u001b[90m missing \u001b[0m c c",
"text/html": [
"1 | true | 1 | missing | a |
2 | false | 2 | b | missing |
3 | true | missing | c | c |
"
]
},
"metadata": {},
"execution_count": 34
}
],
"cell_type": "code",
"source": [
"y2 = copy(y)"
],
"metadata": {},
"execution_count": 34
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "3-element Vector{Bool}:\n 1\n 0\n 1"
},
"metadata": {},
"execution_count": 35
}
],
"cell_type": "code",
"source": [
"y2.A"
],
"metadata": {},
"execution_count": 35
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "3-element Vector{Union{Missing, Int64}}:\n 1\n 2\n missing"
},
"metadata": {},
"execution_count": 36
}
],
"cell_type": "code",
"source": [
"y2.B"
],
"metadata": {},
"execution_count": 36
},
{
"cell_type": "markdown",
"source": [
"## Basic benchmarking\n",
"Next, we'll create some files, so be careful that you don't already have these files in your working directory!\n",
"In particular, we'll time how long it takes us to write a `DataFrame` with 1000 rows and 100000 columns."
],
"metadata": {}
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First run\n"
]
}
],
"cell_type": "code",
"source": [
"bigdf = DataFrame(rand(Bool, 10^4, 1000), :auto)\n",
"\n",
"bigdf[!, 1] = Int.(bigdf[!, 1])\n",
"bigdf[!, 2] = bigdf[!, 2] .+ 0.5\n",
"bigdf[!, 3] = string.(bigdf[!, 3], \", as string\")\n",
"\n",
"println(\"First run\")"
],
"metadata": {},
"execution_count": 37
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CSV.jl\n",
" 4.182118 seconds (44.60 M allocations: 1.126 GiB, 1.93% gc time, 70.66% compilation time)\n",
"Serialization\n",
" 0.182378 seconds (148.06 k allocations: 9.349 MiB, 25.80% compilation time)\n",
"JDF.jl\n",
" 0.167824 seconds (46.70 k allocations: 147.645 MiB, 7.71% gc time, 26.96% compilation time)\n",
"JLSO.jl\n",
" 1.042447 seconds (170.03 k allocations: 17.368 MiB, 0.58% gc time, 6.27% compilation time)\n",
"Arrow.jl\n",
" 3.306893 seconds (3.02 M allocations: 209.474 MiB, 1.39% gc time, 97.12% compilation time)\n",
"JSONTables.jl arraytable\n",
" 11.088881 seconds (229.61 M allocations: 5.423 GiB, 14.59% gc time, 0.07% compilation time)\n",
"JSONTables.jl objecttable\n",
" 0.441042 seconds (62.21 k allocations: 308.136 MiB, 47.08% gc time, 15.77% compilation time)\n",
"Second run\n",
"CSV.jl\n",
" 1.451915 seconds (44.40 M allocations: 1.113 GiB, 17.16% gc time)\n",
"Serialization\n",
" 0.142911 seconds (14.32 k allocations: 397.188 KiB, 5.72% compilation time)\n",
"JDF.jl\n",
" 0.120403 seconds (28.11 k allocations: 146.392 MiB, 8.49% gc time)\n",
"JLSO.jl\n",
" 0.972342 seconds (30.24 k allocations: 7.593 MiB)\n",
"Arrow.jl\n",
" 0.094460 seconds (52.67 k allocations: 5.608 MiB)\n",
"JSONTables.jl arraytable\n",
" 11.273705 seconds (229.61 M allocations: 5.423 GiB, 14.34% gc time, 0.07% compilation time)\n",
"JSONTables.jl objecttable\n",
" 0.204532 seconds (18.94 k allocations: 305.308 MiB, 2.62% gc time, 4.38% compilation time)\n"
]
},
{
"output_type": "execute_result",
"data": {
"text/plain": "0.204651448"
},
"metadata": {},
"execution_count": 38
}
],
"cell_type": "code",
"source": [
"println(\"CSV.jl\")\n",
"csvwrite1 = @elapsed @time CSV.write(\"bigdf1.csv\", bigdf)\n",
"println(\"Serialization\")\n",
"serializewrite1 = @elapsed @time open(io -> serialize(io, bigdf), \"bigdf.bin\", \"w\")\n",
"println(\"JDF.jl\")\n",
"jdfwrite1 = @elapsed @time JDF.save(\"bigdf.jdf\", bigdf)\n",
"println(\"JLSO.jl\")\n",
"jlsowrite1 = @elapsed @time JLSO.save(\"bigdf.jlso\", :data => bigdf)\n",
"println(\"Arrow.jl\")\n",
"arrowwrite1 = @elapsed @time Arrow.write(\"bigdf.arrow\", bigdf)\n",
"println(\"JSONTables.jl arraytable\")\n",
"jsontablesawrite1 = @elapsed @time open(io -> arraytable(io, bigdf), \"bigdf1.json\", \"w\")\n",
"println(\"JSONTables.jl objecttable\")\n",
"jsontablesowrite1 = @elapsed @time open(io -> objecttable(io, bigdf), \"bigdf2.json\", \"w\")\n",
"println(\"Second run\")\n",
"println(\"CSV.jl\")\n",
"csvwrite2 = @elapsed @time CSV.write(\"bigdf1.csv\", bigdf)\n",
"println(\"Serialization\")\n",
"serializewrite2 = @elapsed @time open(io -> serialize(io, bigdf), \"bigdf.bin\", \"w\")\n",
"println(\"JDF.jl\")\n",
"jdfwrite2 = @elapsed @time JDF.save(\"bigdf.jdf\", bigdf)\n",
"println(\"JLSO.jl\")\n",
"jlsowrite2 = @elapsed @time JLSO.save(\"bigdf.jlso\", :data => bigdf)\n",
"println(\"Arrow.jl\")\n",
"arrowwrite2 = @elapsed @time Arrow.write(\"bigdf.arrow\", bigdf)\n",
"println(\"JSONTables.jl arraytable\")\n",
"jsontablesawrite2 = @elapsed @time open(io -> arraytable(io, bigdf), \"bigdf1.json\", \"w\")\n",
"println(\"JSONTables.jl objecttable\")\n",
"jsontablesowrite2 = @elapsed @time open(io -> objecttable(io, bigdf), \"bigdf2.json\", \"w\")"
],
"metadata": {},
"execution_count": 38
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "Plot{Plots.GRBackend() n=2}",
"image/png": "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EOLq6mpnZ3fz5s24uLhKugPgDoIQPhhisfjChQsXLlw4ceLE7t27Z82a5eTktGLFCn19/T179rCXpRgbGzdv3jwpKWnNmjVyuZwQ8ujRo4EDB5ZdBoVOulizZk1kZOSdO3diY2MJIS1atDA0NPz777/Z4IyKivryyy/pgb73R2Nj5cqVdI+ntLR006ZN27Ztq9nC3+Xy8/MLDAy8d+9enz59bt26JZVKCSFisfjixYsjRoyIiIhga44fP97d3T00NLQqzd6/f/+7774rKioihDx+/PjLL79kGGbu3LkVjdzIyOiHH35QKBQ9e/bct2/fnTt3jh496uPjo7YWq5aW1oIFCwgho0aNoouYl5SULF68uLb+8gB4t7qcuwFQNXQeYVkmJiZff/11YmKiWv0zZ87QSxB1dXXpFTTu7u70COqaNWvYajk5OaqXTYpEIlr+66+/0nN7hoaG9HKVfv360av5Q0ND2bdXvrIMnUcYHBysVi6TyXr27El7tLCw0NPT09bW3rVrl62trb6+PluNziOcOHGi2tvNzc1NTEzUCukE87///pstKSgo+OKLL9jtYhdmE4lEUVFRbLVqzSP87bffTExMdHV1rays6F8VX331lerESrV5hNQPP/zALkZDCOnfv/+hQ4cIITNnzmTrKBSKCRMm0ApWVla6urqGhob79u0jmEcIGoFzhPABcHNzUz1QZmJiYmJi4uTk5OLiUu69Dvz8/OLj448cOZKUlGRkZNS5c+dhw4Y9f/7czMzM09OTrWZubh4fHx8XF/fq1avs7Gy2qSlTprRr1y40NPTFixfm5ua+vr6BgYExMTGurq5t2rRh37548eLMzEx2YTA1gYGBdnZ2ZadPiESi06dPHzly5MaNG2KxuEmTJsOHD2/ZsqWenh7ddaNatmy5Y8cOus+qav369WqHVQkhX375ZZs2bVTndRgZGR0+fHjevHlhYWF0np+dnV3Lli0DAgJUr0RdsGDB2LFj1c78lTVz5sxBgwYNGTLE19d3//79jx8/NjY27tu3r9oExH79+tnZ2am1tnz58ilTply/fl0qlbq5ubVo0YLOxFc9RSoUCn/77bdhw4aFhobm5eU1bdp09OjR1tbW7JR8ysTEZMeOHby9uQdwR8D8+0oBAABO+fn5nTt37vLlyz4+PnU9FgBCcI4QALiTkpKyceNG9nKkt2/f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8UIQQt37+++/w8PDy16Vt3nzZkKIq6trRefk/vzzz+XLlzs5OYWEhJS7DDddUWXFihVlryoUi8WqUy/WrVu3bNmyd541pPdVZ+fAVdeYMWMEAsHWrVvZI4EMw/z444+EELr8GDVgwABTU9OwsLD79++zhT///LNEIhkyZAj702jTpo27u/vz58/pNUFUSEhIQkJC69at2aTR09P74osv5HI5XYSTSkxMPH78uLGx8eDBg9nCZ8+eLViwYM2aNTXbOjV0qMePH1ed2/Df//5XLpcPHz6cnvMjhHTs2LFly5YJCQkhISFstUOHDj1//rx9+/Z00RlCiJGR0eDBg0tLS3/66Se22r1798LCwho0aECn1au6deuWvr5+bV0yCh83nCOEuhcXF7d06VIXF5cBAwa0atVKV1f39evXISEhUVFRWlpaNCfKys3NpUuHDBo06K+//lJ7deLEiXRq+bRp07Zt29a2bdupU6e6urrq6Oi8ePHi+vXrx44de/ToEbts9M8//5yZmenn56e6gHVZvXv31tHRKTsJPS8vjy4HSgh5+PAhIWT16tW7d+8mhHTr1o2uL0oI8fDwGDdu3J49ez7//PO5c+eamJjs2bPn9OnTrq6uU6ZMYVszMzNbvXr1jBkzevbsuXjxYicnpzNnzmzdutXc3HzlypWq/W7cuNHX13fChAlPnz5t37793bt3g4KCRCLRxo0bVfePf/jhh5MnT/7888+FhYWBgYEvXrwICgoqLS0NCgpSvQL21atXa9eubdy48YIFCyr5IRBCJkyYQK9biY2NJYQEBwfTBUibNWu2evVqWsfS0vKHH36YO3dujx49Fi1a5OjoePLkyR07dlhZWakexBYIBJs2bfL39x81alRCQkLbtm3v3Lnz448/amtrb9y4UbXTlStXhoeHBwUF5eXl+fn5JScnr169WiaTBQUFqZ2yffToUXp6+qBBg+r2LiXwoeA8CF+9eqWvr48j9VCJHj163L179/z58//9739Vy9u0abN27Vq6LHVZEomETstT3UVgTZgwgd4FacuWLS4uLqtXr16yZAn7qoGBgZ+fXyX3P6pIo0aN+vfvf/To0aSkJNWp96WlpUePHlWtGRkZSR+oTQzYtm2brq7uzp07x4wZQ0t69Oixf/9+tTtvTJ8+XSqVLl26lK7KRghp0aLFwYMH2eSmunbtevz4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"
},
"metadata": {},
"execution_count": 39
}
],
"cell_type": "code",
"source": [
"groupedbar(\n",
" repeat([\"CSV.jl\", \"Serialization\", \"JDF.jl\", \"JLSO.jl\", \"Arrow.jl\", \"JSONTables.jl\\nobjecttable\"],\n",
" inner=2),\n",
" [csvwrite1, csvwrite2, serializewrite1, serializewrite1, jdfwrite1, jdfwrite2,\n",
" jlsowrite1, jlsowrite2, arrowwrite1, arrowwrite2, jsontablesowrite2, jsontablesowrite2],\n",
" group=repeat([\"1st\", \"2nd\"], outer=6),\n",
" ylab=\"Second\",\n",
" title=\"Write Performance\\nDataFrame: bigdf\\nSize: $(size(bigdf))\"\n",
")"
],
"metadata": {},
"execution_count": 39
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m6×2 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m file \u001b[0m\u001b[1m size \u001b[0m\n │\u001b[90m String \u001b[0m\u001b[90m Int64 \u001b[0m\n─────┼────────────────────────\n 1 │ bigdf.arrow 1742874\n 2 │ bigdf.bin 5197783\n 3 │ bigdf.jdf 5220906\n 4 │ bigdf1.csv 55088279\n 5 │ bigdf2.json 55092280\n 6 │ bigdf1.json 124033387",
"text/html": [
"1 | bigdf.arrow | 1742874 |
2 | bigdf.bin | 5197783 |
3 | bigdf.jdf | 5220906 |
4 | bigdf1.csv | 55088279 |
5 | bigdf2.json | 55092280 |
6 | bigdf1.json | 124033387 |
"
]
},
"metadata": {},
"execution_count": 40
}
],
"cell_type": "code",
"source": [
"data_files = [\"bigdf1.csv\", \"bigdf.bin\", \"bigdf.arrow\", \"bigdf1.json\", \"bigdf2.json\"]\n",
"df = DataFrame(file=data_files, size=getfield.(stat.(data_files), :size))\n",
"append!(df, DataFrame(file=\"bigdf.jdf\", size=reduce((x, y) -> x + y.size,\n",
" stat.(joinpath.(\"bigdf.jdf\", readdir(\"bigdf.jdf\"))),\n",
" init=0)))\n",
"sort!(df, :size)"
],
"metadata": {},
"execution_count": 40
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "Plot{Plots.GRBackend() n=1}",
"image/png": "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"
},
"metadata": {},
"execution_count": 41
}
],
"cell_type": "code",
"source": [
"@df df plot(:file, :size / 1024^2, seriestype=:bar, title=\"Format File Size (MB)\", label=\"Size\", ylab=\"MB\")"
],
"metadata": {},
"execution_count": 41
},
{
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First run\n",
"CSV.jl\n",
" 1.118292 seconds (397.72 k allocations: 51.661 MiB, 1.84% gc time, 35.97% compilation time)\n",
"Serialization\n",
" 0.421860 seconds (9.49 M allocations: 155.129 MiB, 6.02% gc time, 6.04% compilation time)\n",
"JDF.jl\n",
" 0.235720 seconds (123.90 k allocations: 161.540 MiB, 69.39% compilation time)\n",
"JLSO.jl\n",
" 0.358017 seconds (9.50 M allocations: 157.744 MiB, 2.95% gc time, 6.18% compilation time)\n",
"Arrow.jl\n",
" 0.373816 seconds (347.63 k allocations: 22.531 MiB, 98.14% compilation time)\n",
" 0.054821 seconds (12.50 k allocations: 10.320 MiB)\n",
"JSONTables.jl arraytable\n",
" 13.365779 seconds (30.24 M allocations: 2.530 GiB, 4.82% gc time)\n",
"JSONTables.jl objecttable\n",
" 0.346682 seconds (7.05 k allocations: 282.608 MiB, 2.31% gc time, 0.04% compilation time)\n",
"Second run\n",
" 0.829712 seconds (137.55 k allocations: 34.245 MiB)\n",
"Serialization\n",
" 0.384698 seconds (9.48 M allocations: 154.650 MiB, 4.71% gc time)\n",
"JDF.jl\n",
" 0.060879 seconds (69.69 k allocations: 157.941 MiB)\n",
"JLSO.jl\n",
" 0.371550 seconds (9.50 M allocations: 157.320 MiB, 7.39% gc time)\n",
"Arrow.jl\n",
" 0.005045 seconds (67.53 k allocations: 3.292 MiB)\n",
" 0.054906 seconds (12.50 k allocations: 10.320 MiB)\n",
"JSONTables.jl arraytable\n",
" 13.105496 seconds (30.24 M allocations: 2.530 GiB, 3.00% gc time)\n",
"JSONTables.jl objecttable\n",
" 0.348026 seconds (6.06 k allocations: 282.538 MiB, 4.00% gc time)\n"
]
}
],
"cell_type": "code",
"source": [
"println(\"First run\")\n",
"println(\"CSV.jl\")\n",
"csvread1 = @elapsed @time CSV.read(\"bigdf1.csv\", DataFrame)\n",
"println(\"Serialization\")\n",
"serializeread1 = @elapsed @time open(deserialize, \"bigdf.bin\")\n",
"println(\"JDF.jl\")\n",
"jdfread1 = @elapsed @time JDF.load(\"bigdf.jdf\") |> DataFrame\n",
"println(\"JLSO.jl\")\n",
"jlsoread1 = @elapsed @time JLSO.load(\"bigdf.jlso\")\n",
"println(\"Arrow.jl\")\n",
"arrowread1 = @elapsed @time df_tmp = Arrow.Table(\"bigdf.arrow\") |> DataFrame\n",
"arrowread1copy = @elapsed @time copy(df_tmp)\n",
"println(\"JSONTables.jl arraytable\")\n",
"jsontablesaread1 = @elapsed @time open(jsontable, \"bigdf1.json\")\n",
"println(\"JSONTables.jl objecttable\")\n",
"jsontablesoread1 = @elapsed @time open(jsontable, \"bigdf2.json\")\n",
"println(\"Second run\")\n",
"csvread2 = @elapsed @time CSV.read(\"bigdf1.csv\", DataFrame)\n",
"println(\"Serialization\")\n",
"serializeread2 = @elapsed @time open(deserialize, \"bigdf.bin\")\n",
"println(\"JDF.jl\")\n",
"jdfread2 = @elapsed @time JDF.load(\"bigdf.jdf\") |> DataFrame\n",
"println(\"JLSO.jl\")\n",
"jlsoread2 = @elapsed @time JLSO.load(\"bigdf.jlso\")\n",
"println(\"Arrow.jl\")\n",
"arrowread2 = @elapsed @time df_tmp = Arrow.Table(\"bigdf.arrow\") |> DataFrame\n",
"arrowread2copy = @elapsed @time copy(df_tmp)\n",
"println(\"JSONTables.jl arraytable\")\n",
"jsontablesaread2 = @elapsed @time open(jsontable, \"bigdf1.json\")\n",
"println(\"JSONTables.jl objecttable\")\n",
"jsontablesoread2 = @elapsed @time open(jsontable, \"bigdf2.json\");"
],
"metadata": {},
"execution_count": 42
},
{
"cell_type": "markdown",
"source": [
"Exclude JSONTables due to much longer timing"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "Plot{Plots.GRBackend() n=2}",
"image/png": "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"
},
"metadata": {},
"execution_count": 43
}
],
"cell_type": "code",
"source": [
"groupedbar(\n",
" repeat([\"CSV.jl\", \"Serialization\", \"JDF.jl\", \"JLSO.jl\", \"Arrow.jl\", \"Arrow.jl\\ncopy\", ##\"JSON\\narraytable\",\n",
" \"JSON\\nobjecttable\"], inner=2),\n",
" [csvread1, csvread2, serializeread1, serializeread2, jdfread1, jdfread2, jlsoread1, jlsoread2,\n",
" arrowread1, arrowread2, arrowread1 + arrowread1copy, arrowread2 + arrowread2copy,\n",
" # jsontablesaread1, jsontablesaread2,\n",
" jsontablesoread1, jsontablesoread2],\n",
" group=repeat([\"1st\", \"2nd\"], outer=7),\n",
" ylab=\"Second\",\n",
" title=\"Read Performance\\nDataFrame: bigdf\\nSize: $(size(bigdf))\"\n",
")"
],
"metadata": {},
"execution_count": 43
},
{
"cell_type": "markdown",
"source": [
"## Using gzip compression\n",
"A common user requirement is to be able to load and save CSV that are compressed using gzip. Below we show how this can be accomplished using `CodecZlib.jl`. The same pattern is applicable to `JSONTables.jl` compression/decompression.\n",
"Again make sure that you do not have file named `df_compress_test.csv.gz` in your working directory.\n",
"We first generate a random data frame."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m10×1000 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m x1 \u001b[0m\u001b[1m x2 \u001b[0m\u001b[1m x3 \u001b[0m\u001b[1m x4 \u001b[0m\u001b[1m x5 \u001b[0m\u001b[1m x6 \u001b[0m\u001b[1m x7 \u001b[0m\u001b[1m x8 \u001b[0m\u001b[1m x9 \u001b[0m\u001b[1m x10 \u001b[0m\u001b[1m x\u001b[0m ⋯\n │\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m I\u001b[0m ⋯\n─────┼──────────────────────────────────────────────────────────────────────────\n 1 │ 2 10 9 3 4 2 6 4 10 7 ⋯\n 2 │ 4 2 1 10 1 8 9 5 6 10\n 3 │ 2 4 1 5 8 7 2 7 8 5\n 4 │ 7 5 4 3 9 2 10 6 6 4\n 5 │ 9 5 5 6 9 8 1 10 1 8 ⋯\n 6 │ 1 10 4 9 8 3 9 4 2 7\n 7 │ 2 4 2 9 7 5 7 5 10 3\n 8 │ 7 10 7 6 5 1 4 7 10 2\n 9 │ 4 7 9 3 9 5 1 5 4 5 ⋯\n 10 │ 8 4 7 10 7 3 5 6 2 3\n\u001b[36m 990 columns omitted\u001b[0m",
"text/html": [
"10×1000 DataFrame
900 columns omitted
1 | 2 | 10 | 9 | 3 | 4 | 2 | 6 | 4 | 10 | 7 | 5 | 10 | 1 | 8 | 5 | 7 | 9 | 2 | 5 | 2 | 5 | 2 | 5 | 1 | 6 | 10 | 5 | 8 | 3 | 5 | 10 | 5 | 10 | 1 | 4 | 9 | 10 | 4 | 3 | 3 | 5 | 9 | 4 | 1 | 4 | 1 | 8 | 6 | 6 | 10 | 1 | 5 | 7 | 6 | 9 | 9 | 10 | 2 | 5 | 3 | 5 | 3 | 9 | 7 | 9 | 9 | 6 | 6 | 4 | 1 | 8 | 6 | 2 | 1 | 5 | 3 | 9 | 7 | 9 | 7 | 1 | 9 | 9 | 1 | 7 | 10 | 1 | 1 | 3 | 7 | 1 | 7 | 2 | 3 | 10 | 1 | 10 | 3 | 4 | 1 | ⋯ |
2 | 4 | 2 | 1 | 10 | 1 | 8 | 9 | 5 | 6 | 10 | 9 | 8 | 2 | 2 | 2 | 8 | 10 | 8 | 5 | 10 | 10 | 10 | 3 | 6 | 8 | 3 | 1 | 9 | 3 | 10 | 1 | 1 | 2 | 8 | 7 | 5 | 4 | 6 | 8 | 7 | 8 | 10 | 8 | 1 | 1 | 2 | 9 | 6 | 7 | 8 | 6 | 4 | 9 | 4 | 5 | 10 | 10 | 10 | 9 | 7 | 9 | 8 | 5 | 7 | 4 | 7 | 5 | 6 | 6 | 7 | 1 | 1 | 7 | 2 | 7 | 5 | 1 | 8 | 6 | 2 | 6 | 2 | 6 | 9 | 7 | 1 | 5 | 9 | 9 | 9 | 4 | 7 | 8 | 1 | 8 | 1 | 2 | 3 | 10 | 3 | ⋯ |
3 | 2 | 4 | 1 | 5 | 8 | 7 | 2 | 7 | 8 | 5 | 5 | 4 | 2 | 9 | 1 | 2 | 8 | 5 | 5 | 4 | 9 | 7 | 6 | 1 | 10 | 4 | 7 | 7 | 5 | 6 | 2 | 3 | 3 | 6 | 10 | 10 | 2 | 9 | 9 | 4 | 4 | 2 | 9 | 2 | 10 | 10 | 5 | 6 | 2 | 5 | 10 | 7 | 7 | 3 | 9 | 2 | 10 | 5 | 6 | 3 | 6 | 3 | 5 | 10 | 3 | 7 | 9 | 5 | 2 | 4 | 7 | 1 | 1 | 3 | 6 | 8 | 3 | 3 | 4 | 10 | 2 | 6 | 7 | 3 | 4 | 10 | 7 | 4 | 6 | 7 | 6 | 8 | 6 | 10 | 6 | 10 | 8 | 1 | 3 | 8 | ⋯ |
4 | 7 | 5 | 4 | 3 | 9 | 2 | 10 | 6 | 6 | 4 | 5 | 7 | 8 | 3 | 6 | 5 | 5 | 2 | 5 | 8 | 4 | 1 | 2 | 8 | 6 | 5 | 5 | 4 | 2 | 7 | 2 | 1 | 9 | 6 | 2 | 8 | 1 | 3 | 8 | 3 | 1 | 5 | 3 | 4 | 9 | 8 | 9 | 4 | 5 | 5 | 7 | 4 | 2 | 2 | 6 | 6 | 3 | 7 | 4 | 6 | 8 | 9 | 1 | 9 | 1 | 10 | 6 | 9 | 2 | 4 | 3 | 6 | 3 | 2 | 1 | 2 | 10 | 3 | 5 | 5 | 9 | 8 | 4 | 8 | 1 | 6 | 7 | 3 | 10 | 2 | 5 | 4 | 3 | 9 | 8 | 10 | 7 | 4 | 7 | 5 | ⋯ |
5 | 9 | 5 | 5 | 6 | 9 | 8 | 1 | 10 | 1 | 8 | 5 | 8 | 3 | 2 | 8 | 2 | 5 | 8 | 9 | 1 | 4 | 10 | 8 | 7 | 2 | 10 | 9 | 8 | 8 | 4 | 6 | 8 | 2 | 6 | 6 | 4 | 8 | 2 | 4 | 1 | 1 | 4 | 3 | 2 | 9 | 2 | 7 | 7 | 1 | 7 | 5 | 3 | 7 | 2 | 4 | 8 | 4 | 7 | 2 | 7 | 4 | 7 | 4 | 1 | 4 | 9 | 7 | 9 | 9 | 7 | 7 | 3 | 9 | 4 | 9 | 1 | 8 | 3 | 1 | 1 | 7 | 10 | 4 | 6 | 8 | 5 | 6 | 10 | 5 | 10 | 9 | 7 | 8 | 1 | 3 | 5 | 9 | 8 | 2 | 7 | ⋯ |
6 | 1 | 10 | 4 | 9 | 8 | 3 | 9 | 4 | 2 | 7 | 1 | 8 | 4 | 7 | 9 | 10 | 7 | 8 | 2 | 2 | 1 | 1 | 10 | 2 | 3 | 3 | 7 | 3 | 2 | 2 | 5 | 4 | 4 | 3 | 7 | 5 | 6 | 8 | 8 | 1 | 1 | 4 | 10 | 9 | 6 | 6 | 2 | 1 | 4 | 5 | 2 | 10 | 9 | 5 | 3 | 5 | 3 | 3 | 8 | 5 | 6 | 4 | 2 | 8 | 4 | 1 | 9 | 8 | 10 | 8 | 5 | 10 | 6 | 2 | 3 | 10 | 1 | 6 | 2 | 2 | 10 | 1 | 1 | 7 | 10 | 6 | 4 | 10 | 7 | 10 | 10 | 10 | 7 | 7 | 10 | 3 | 9 | 8 | 4 | 4 | ⋯ |
7 | 2 | 4 | 2 | 9 | 7 | 5 | 7 | 5 | 10 | 3 | 8 | 2 | 1 | 1 | 5 | 4 | 4 | 3 | 1 | 10 | 3 | 7 | 10 | 3 | 2 | 2 | 1 | 6 | 5 | 4 | 10 | 7 | 1 | 10 | 1 | 8 | 8 | 7 | 3 | 8 | 10 | 3 | 2 | 7 | 10 | 9 | 5 | 10 | 6 | 10 | 5 | 6 | 7 | 7 | 4 | 2 | 5 | 8 | 4 | 2 | 6 | 10 | 6 | 1 | 6 | 8 | 9 | 5 | 3 | 5 | 8 | 9 | 7 | 3 | 5 | 7 | 9 | 7 | 9 | 7 | 3 | 10 | 6 | 7 | 1 | 8 | 8 | 4 | 7 | 7 | 8 | 4 | 1 | 5 | 8 | 2 | 9 | 5 | 9 | 10 | ⋯ |
8 | 7 | 10 | 7 | 6 | 5 | 1 | 4 | 7 | 10 | 2 | 2 | 2 | 7 | 4 | 3 | 9 | 4 | 7 | 4 | 6 | 9 | 7 | 4 | 3 | 10 | 2 | 7 | 4 | 6 | 7 | 1 | 8 | 4 | 7 | 8 | 4 | 3 | 9 | 9 | 2 | 6 | 8 | 5 | 10 | 9 | 8 | 3 | 8 | 7 | 8 | 3 | 1 | 5 | 7 | 3 | 6 | 9 | 7 | 2 | 3 | 7 | 6 | 4 | 2 | 6 | 8 | 6 | 7 | 10 | 7 | 1 | 7 | 2 | 9 | 4 | 7 | 2 | 7 | 10 | 8 | 5 | 5 | 2 | 10 | 8 | 6 | 2 | 4 | 1 | 5 | 6 | 2 | 3 | 5 | 4 | 5 | 6 | 1 | 2 | 4 | ⋯ |
9 | 4 | 7 | 9 | 3 | 9 | 5 | 1 | 5 | 4 | 5 | 8 | 5 | 8 | 10 | 7 | 2 | 6 | 2 | 3 | 2 | 10 | 5 | 10 | 6 | 7 | 8 | 2 | 9 | 9 | 3 | 5 | 3 | 2 | 5 | 3 | 9 | 9 | 5 | 3 | 3 | 9 | 9 | 5 | 2 | 1 | 8 | 4 | 3 | 6 | 2 | 2 | 6 | 6 | 8 | 3 | 2 | 2 | 9 | 2 | 4 | 8 | 8 | 3 | 2 | 1 | 8 | 8 | 6 | 10 | 5 | 7 | 3 | 6 | 4 | 8 | 8 | 10 | 4 | 5 | 2 | 3 | 6 | 2 | 8 | 7 | 5 | 2 | 8 | 8 | 2 | 9 | 10 | 1 | 5 | 9 | 3 | 5 | 1 | 3 | 4 | ⋯ |
10 | 8 | 4 | 7 | 10 | 7 | 3 | 5 | 6 | 2 | 3 | 6 | 2 | 7 | 3 | 9 | 8 | 2 | 8 | 9 | 3 | 2 | 3 | 7 | 4 | 10 | 2 | 3 | 3 | 3 | 1 | 4 | 6 | 8 | 5 | 6 | 1 | 1 | 6 | 3 | 4 | 6 | 3 | 7 | 9 | 6 | 5 | 3 | 5 | 8 | 7 | 2 | 3 | 4 | 9 | 7 | 4 | 9 | 1 | 4 | 10 | 10 | 4 | 3 | 8 | 2 | 8 | 5 | 2 | 3 | 3 | 3 | 4 | 9 | 10 | 5 | 6 | 3 | 7 | 9 | 10 | 5 | 5 | 2 | 4 | 3 | 4 | 3 | 6 | 2 | 9 | 3 | 6 | 5 | 9 | 3 | 2 | 5 | 3 | 8 | 8 | ⋯ |
"
]
},
"metadata": {},
"execution_count": 44
}
],
"cell_type": "code",
"source": [
"df = DataFrame(rand(1:10, 10, 1000), :auto)"
],
"metadata": {},
"execution_count": 44
},
{
"cell_type": "markdown",
"source": [
"GzipCompressorStream comes from `CodecZlib`"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"open(\"df_compress_test.csv.gz\", \"w\") do io\n",
" stream = GzipCompressorStream(io)\n",
" CSV.write(stream, df)\n",
" close(stream)\n",
"end"
],
"metadata": {},
"execution_count": 45
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m10×1000 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m x1 \u001b[0m\u001b[1m x2 \u001b[0m\u001b[1m x3 \u001b[0m\u001b[1m x4 \u001b[0m\u001b[1m x5 \u001b[0m\u001b[1m x6 \u001b[0m\u001b[1m x7 \u001b[0m\u001b[1m x8 \u001b[0m\u001b[1m x9 \u001b[0m\u001b[1m x10 \u001b[0m\u001b[1m x\u001b[0m ⋯\n │\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m I\u001b[0m ⋯\n─────┼──────────────────────────────────────────────────────────────────────────\n 1 │ 2 10 9 3 4 2 6 4 10 7 ⋯\n 2 │ 4 2 1 10 1 8 9 5 6 10\n 3 │ 2 4 1 5 8 7 2 7 8 5\n 4 │ 7 5 4 3 9 2 10 6 6 4\n 5 │ 9 5 5 6 9 8 1 10 1 8 ⋯\n 6 │ 1 10 4 9 8 3 9 4 2 7\n 7 │ 2 4 2 9 7 5 7 5 10 3\n 8 │ 7 10 7 6 5 1 4 7 10 2\n 9 │ 4 7 9 3 9 5 1 5 4 5 ⋯\n 10 │ 8 4 7 10 7 3 5 6 2 3\n\u001b[36m 990 columns omitted\u001b[0m",
"text/html": [
"10×1000 DataFrame
900 columns omitted
1 | 2 | 10 | 9 | 3 | 4 | 2 | 6 | 4 | 10 | 7 | 5 | 10 | 1 | 8 | 5 | 7 | 9 | 2 | 5 | 2 | 5 | 2 | 5 | 1 | 6 | 10 | 5 | 8 | 3 | 5 | 10 | 5 | 10 | 1 | 4 | 9 | 10 | 4 | 3 | 3 | 5 | 9 | 4 | 1 | 4 | 1 | 8 | 6 | 6 | 10 | 1 | 5 | 7 | 6 | 9 | 9 | 10 | 2 | 5 | 3 | 5 | 3 | 9 | 7 | 9 | 9 | 6 | 6 | 4 | 1 | 8 | 6 | 2 | 1 | 5 | 3 | 9 | 7 | 9 | 7 | 1 | 9 | 9 | 1 | 7 | 10 | 1 | 1 | 3 | 7 | 1 | 7 | 2 | 3 | 10 | 1 | 10 | 3 | 4 | 1 | ⋯ |
2 | 4 | 2 | 1 | 10 | 1 | 8 | 9 | 5 | 6 | 10 | 9 | 8 | 2 | 2 | 2 | 8 | 10 | 8 | 5 | 10 | 10 | 10 | 3 | 6 | 8 | 3 | 1 | 9 | 3 | 10 | 1 | 1 | 2 | 8 | 7 | 5 | 4 | 6 | 8 | 7 | 8 | 10 | 8 | 1 | 1 | 2 | 9 | 6 | 7 | 8 | 6 | 4 | 9 | 4 | 5 | 10 | 10 | 10 | 9 | 7 | 9 | 8 | 5 | 7 | 4 | 7 | 5 | 6 | 6 | 7 | 1 | 1 | 7 | 2 | 7 | 5 | 1 | 8 | 6 | 2 | 6 | 2 | 6 | 9 | 7 | 1 | 5 | 9 | 9 | 9 | 4 | 7 | 8 | 1 | 8 | 1 | 2 | 3 | 10 | 3 | ⋯ |
3 | 2 | 4 | 1 | 5 | 8 | 7 | 2 | 7 | 8 | 5 | 5 | 4 | 2 | 9 | 1 | 2 | 8 | 5 | 5 | 4 | 9 | 7 | 6 | 1 | 10 | 4 | 7 | 7 | 5 | 6 | 2 | 3 | 3 | 6 | 10 | 10 | 2 | 9 | 9 | 4 | 4 | 2 | 9 | 2 | 10 | 10 | 5 | 6 | 2 | 5 | 10 | 7 | 7 | 3 | 9 | 2 | 10 | 5 | 6 | 3 | 6 | 3 | 5 | 10 | 3 | 7 | 9 | 5 | 2 | 4 | 7 | 1 | 1 | 3 | 6 | 8 | 3 | 3 | 4 | 10 | 2 | 6 | 7 | 3 | 4 | 10 | 7 | 4 | 6 | 7 | 6 | 8 | 6 | 10 | 6 | 10 | 8 | 1 | 3 | 8 | ⋯ |
4 | 7 | 5 | 4 | 3 | 9 | 2 | 10 | 6 | 6 | 4 | 5 | 7 | 8 | 3 | 6 | 5 | 5 | 2 | 5 | 8 | 4 | 1 | 2 | 8 | 6 | 5 | 5 | 4 | 2 | 7 | 2 | 1 | 9 | 6 | 2 | 8 | 1 | 3 | 8 | 3 | 1 | 5 | 3 | 4 | 9 | 8 | 9 | 4 | 5 | 5 | 7 | 4 | 2 | 2 | 6 | 6 | 3 | 7 | 4 | 6 | 8 | 9 | 1 | 9 | 1 | 10 | 6 | 9 | 2 | 4 | 3 | 6 | 3 | 2 | 1 | 2 | 10 | 3 | 5 | 5 | 9 | 8 | 4 | 8 | 1 | 6 | 7 | 3 | 10 | 2 | 5 | 4 | 3 | 9 | 8 | 10 | 7 | 4 | 7 | 5 | ⋯ |
5 | 9 | 5 | 5 | 6 | 9 | 8 | 1 | 10 | 1 | 8 | 5 | 8 | 3 | 2 | 8 | 2 | 5 | 8 | 9 | 1 | 4 | 10 | 8 | 7 | 2 | 10 | 9 | 8 | 8 | 4 | 6 | 8 | 2 | 6 | 6 | 4 | 8 | 2 | 4 | 1 | 1 | 4 | 3 | 2 | 9 | 2 | 7 | 7 | 1 | 7 | 5 | 3 | 7 | 2 | 4 | 8 | 4 | 7 | 2 | 7 | 4 | 7 | 4 | 1 | 4 | 9 | 7 | 9 | 9 | 7 | 7 | 3 | 9 | 4 | 9 | 1 | 8 | 3 | 1 | 1 | 7 | 10 | 4 | 6 | 8 | 5 | 6 | 10 | 5 | 10 | 9 | 7 | 8 | 1 | 3 | 5 | 9 | 8 | 2 | 7 | ⋯ |
6 | 1 | 10 | 4 | 9 | 8 | 3 | 9 | 4 | 2 | 7 | 1 | 8 | 4 | 7 | 9 | 10 | 7 | 8 | 2 | 2 | 1 | 1 | 10 | 2 | 3 | 3 | 7 | 3 | 2 | 2 | 5 | 4 | 4 | 3 | 7 | 5 | 6 | 8 | 8 | 1 | 1 | 4 | 10 | 9 | 6 | 6 | 2 | 1 | 4 | 5 | 2 | 10 | 9 | 5 | 3 | 5 | 3 | 3 | 8 | 5 | 6 | 4 | 2 | 8 | 4 | 1 | 9 | 8 | 10 | 8 | 5 | 10 | 6 | 2 | 3 | 10 | 1 | 6 | 2 | 2 | 10 | 1 | 1 | 7 | 10 | 6 | 4 | 10 | 7 | 10 | 10 | 10 | 7 | 7 | 10 | 3 | 9 | 8 | 4 | 4 | ⋯ |
7 | 2 | 4 | 2 | 9 | 7 | 5 | 7 | 5 | 10 | 3 | 8 | 2 | 1 | 1 | 5 | 4 | 4 | 3 | 1 | 10 | 3 | 7 | 10 | 3 | 2 | 2 | 1 | 6 | 5 | 4 | 10 | 7 | 1 | 10 | 1 | 8 | 8 | 7 | 3 | 8 | 10 | 3 | 2 | 7 | 10 | 9 | 5 | 10 | 6 | 10 | 5 | 6 | 7 | 7 | 4 | 2 | 5 | 8 | 4 | 2 | 6 | 10 | 6 | 1 | 6 | 8 | 9 | 5 | 3 | 5 | 8 | 9 | 7 | 3 | 5 | 7 | 9 | 7 | 9 | 7 | 3 | 10 | 6 | 7 | 1 | 8 | 8 | 4 | 7 | 7 | 8 | 4 | 1 | 5 | 8 | 2 | 9 | 5 | 9 | 10 | ⋯ |
8 | 7 | 10 | 7 | 6 | 5 | 1 | 4 | 7 | 10 | 2 | 2 | 2 | 7 | 4 | 3 | 9 | 4 | 7 | 4 | 6 | 9 | 7 | 4 | 3 | 10 | 2 | 7 | 4 | 6 | 7 | 1 | 8 | 4 | 7 | 8 | 4 | 3 | 9 | 9 | 2 | 6 | 8 | 5 | 10 | 9 | 8 | 3 | 8 | 7 | 8 | 3 | 1 | 5 | 7 | 3 | 6 | 9 | 7 | 2 | 3 | 7 | 6 | 4 | 2 | 6 | 8 | 6 | 7 | 10 | 7 | 1 | 7 | 2 | 9 | 4 | 7 | 2 | 7 | 10 | 8 | 5 | 5 | 2 | 10 | 8 | 6 | 2 | 4 | 1 | 5 | 6 | 2 | 3 | 5 | 4 | 5 | 6 | 1 | 2 | 4 | ⋯ |
9 | 4 | 7 | 9 | 3 | 9 | 5 | 1 | 5 | 4 | 5 | 8 | 5 | 8 | 10 | 7 | 2 | 6 | 2 | 3 | 2 | 10 | 5 | 10 | 6 | 7 | 8 | 2 | 9 | 9 | 3 | 5 | 3 | 2 | 5 | 3 | 9 | 9 | 5 | 3 | 3 | 9 | 9 | 5 | 2 | 1 | 8 | 4 | 3 | 6 | 2 | 2 | 6 | 6 | 8 | 3 | 2 | 2 | 9 | 2 | 4 | 8 | 8 | 3 | 2 | 1 | 8 | 8 | 6 | 10 | 5 | 7 | 3 | 6 | 4 | 8 | 8 | 10 | 4 | 5 | 2 | 3 | 6 | 2 | 8 | 7 | 5 | 2 | 8 | 8 | 2 | 9 | 10 | 1 | 5 | 9 | 3 | 5 | 1 | 3 | 4 | ⋯ |
10 | 8 | 4 | 7 | 10 | 7 | 3 | 5 | 6 | 2 | 3 | 6 | 2 | 7 | 3 | 9 | 8 | 2 | 8 | 9 | 3 | 2 | 3 | 7 | 4 | 10 | 2 | 3 | 3 | 3 | 1 | 4 | 6 | 8 | 5 | 6 | 1 | 1 | 6 | 3 | 4 | 6 | 3 | 7 | 9 | 6 | 5 | 3 | 5 | 8 | 7 | 2 | 3 | 4 | 9 | 7 | 4 | 9 | 1 | 4 | 10 | 10 | 4 | 3 | 8 | 2 | 8 | 5 | 2 | 3 | 3 | 3 | 4 | 9 | 10 | 5 | 6 | 3 | 7 | 9 | 10 | 5 | 5 | 2 | 4 | 3 | 4 | 3 | 6 | 2 | 9 | 3 | 6 | 5 | 9 | 3 | 2 | 5 | 3 | 8 | 8 | ⋯ |
"
]
},
"metadata": {},
"execution_count": 46
}
],
"cell_type": "code",
"source": [
"df2 = CSV.File(transcode(GzipDecompressor, Mmap.mmap(\"df_compress_test.csv.gz\"))) |> DataFrame"
],
"metadata": {},
"execution_count": 46
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "true"
},
"metadata": {},
"execution_count": 47
}
],
"cell_type": "code",
"source": [
"df == df2"
],
"metadata": {},
"execution_count": 47
},
{
"cell_type": "markdown",
"source": [
"## Using zip files\n",
"Sometimes you may have files compressed inside a zip file.\n",
"In such a situation you may use [ZipFile.jl](https://github.com/fhs/ZipFile.jl) in conjunction an an appropriate reader to read the files.\n",
"Here we first create a ZIP file and then read back its contents into a `DataFrame`."
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m x1 \u001b[0m\u001b[1m x2 \u001b[0m\u001b[1m x3 \u001b[0m\u001b[1m x4 \u001b[0m\n │\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\n─────┼────────────────────────────\n 1 │ 6 5 9 6\n 2 │ 9 3 10 5\n 3 │ 6 3 1 6",
"text/html": [
""
]
},
"metadata": {},
"execution_count": 48
}
],
"cell_type": "code",
"source": [
"df1 = DataFrame(rand(1:10, 3, 4), :auto)"
],
"metadata": {},
"execution_count": 48
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m x1 \u001b[0m\u001b[1m x2 \u001b[0m\u001b[1m x3 \u001b[0m\u001b[1m x4 \u001b[0m\n │\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\n─────┼────────────────────────────\n 1 │ 3 8 7 2\n 2 │ 3 5 3 9\n 3 │ 4 2 9 5",
"text/html": [
""
]
},
"metadata": {},
"execution_count": 49
}
],
"cell_type": "code",
"source": [
"df2 = DataFrame(rand(1:10, 3, 4), :auto)"
],
"metadata": {},
"execution_count": 49
},
{
"cell_type": "markdown",
"source": [
"And we show yet another way to write a `DataFrame` into a CSV file:\n",
"Writing a CSV file into the zip file"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"w = ZipFile.Writer(\"x.zip\")\n",
"\n",
"f1 = ZipFile.addfile(w, \"x1.csv\")\n",
"write(f1, sprint(show, \"text/csv\", df1))\n",
"\n",
"# write a second CSV file into zip file\n",
"f2 = ZipFile.addfile(w, \"x2.csv\", method=ZipFile.Deflate)\n",
"write(f2, sprint(show, \"text/csv\", df2))\n",
"\n",
"close(w)"
],
"metadata": {},
"execution_count": 50
},
{
"cell_type": "markdown",
"source": [
"Now we read the compressed CSV file we have written:"
],
"metadata": {}
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m x1 \u001b[0m\u001b[1m x2 \u001b[0m\u001b[1m x3 \u001b[0m\u001b[1m x4 \u001b[0m\n │\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\n─────┼────────────────────────────\n 1 │ 6 5 9 6\n 2 │ 9 3 10 5\n 3 │ 6 3 1 6",
"text/html": [
""
]
},
"metadata": {},
"execution_count": 51
}
],
"cell_type": "code",
"source": [
"z = ZipFile.Reader(\"x.zip\");\n",
"# find the index index of file called x1.csv\n",
"index_xcsv = findfirst(x -> x.name == \"x1.csv\", z.files)\n",
"# to read the x1.csv file in the zip file\n",
"df1_2 = CSV.read(read(z.files[index_xcsv]), DataFrame)"
],
"metadata": {},
"execution_count": 51
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "true"
},
"metadata": {},
"execution_count": 52
}
],
"cell_type": "code",
"source": [
"df1_2 == df1"
],
"metadata": {},
"execution_count": 52
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "\u001b[1m3×4 DataFrame\u001b[0m\n\u001b[1m Row \u001b[0m│\u001b[1m x1 \u001b[0m\u001b[1m x2 \u001b[0m\u001b[1m x3 \u001b[0m\u001b[1m x4 \u001b[0m\n │\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\u001b[90m Int64 \u001b[0m\n─────┼────────────────────────────\n 1 │ 3 8 7 2\n 2 │ 3 5 3 9\n 3 │ 4 2 9 5",
"text/html": [
""
]
},
"metadata": {},
"execution_count": 53
}
],
"cell_type": "code",
"source": [
"# find the index index of file called x2.csv\n",
"index_xcsv = findfirst(x -> x.name == \"x2.csv\", z.files)\n",
"# to read the x2.csv file in the zip file\n",
"df2_2 = CSV.read(read(z.files[index_xcsv]), DataFrame)"
],
"metadata": {},
"execution_count": 53
},
{
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "true"
},
"metadata": {},
"execution_count": 54
}
],
"cell_type": "code",
"source": [
"df2_2 == df2"
],
"metadata": {},
"execution_count": 54
},
{
"cell_type": "markdown",
"source": [
"Note that once you read a given file from `z` object its stream is all used-up (reaching its end). Therefore to read it again you need to close the file object `z` and open it again.\n",
"Also do not forget to close the zip file once you are done."
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"close(z)"
],
"metadata": {},
"execution_count": 55
},
{
"cell_type": "markdown",
"source": [
"Remove generated files"
],
"metadata": {}
},
{
"outputs": [],
"cell_type": "code",
"source": [
"rm(\"x.arrow\")\n",
"rm(\"x.bin\")\n",
"rm(\"x.zip\")\n",
"rm(\"x.jlso\")\n",
"rm(\"x1.csv\")\n",
"rm(\"x1.json\")\n",
"rm(\"x2.json\")\n",
"rm(\"x.jdf\", recursive=true)\n",
"rm(\"bigdf.jdf\", recursive=true)\n",
"rm(\"df_compress_test.csv.gz\")\n",
"rm(\"bigdf1.json\")\n",
"rm(\"bigdf1.csv\")\n",
"rm(\"bigdf2.json\")\n",
"rm(\"bigdf.jlso\")\n",
"rm(\"bigdf.bin\")\n",
"rm(\"bigdf.arrow\")"
],
"metadata": {},
"execution_count": 56
},
{
"cell_type": "markdown",
"source": [
"---\n",
"\n",
"*This notebook was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*"
],
"metadata": {}
}
],
"nbformat_minor": 3,
"metadata": {
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.10.5"
},
"kernelspec": {
"name": "julia-1.10",
"display_name": "Julia 1.10.5",
"language": "julia"
}
},
"nbformat": 4
}