Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

bquery

A query and aggregation framework for Bcolz.

Bcolz is a light weight package that provides columnar, chunked data containers that can be compressed either in-memory and on-disk. that are compressed by default not only for reducing memory/disk storage, but also to improve I/O speed. It excels at storing and sequentially accessing large, numerical data sets.

The bquery framework provides methods to perform query and aggregation operations on bcolz containers, as well as accelerate these operations by pre-processing possible groupby columns. Currently the real-life performance of sum aggregations using on-disk bcolz queries is normally between 1.5 and 3.0 times slower than similar in-memory Pandas aggregations. See the Benchmark paragraph below.

It is important to notice that while the end result is a bcolz ctable (which can be out-of-core) and the input can be any out-of-core ctable, the intermediate result will be an in-memory numpy array. This is because most groupby operations on non-sorted tables require random memory access while bcolz is limited to sequential access for optimum performance. However, this memory footprint is limited to the groupby result length and can be further optimized in the future to a per-column usage.

At the moment, only two aggregation methods are provided: sum and sum_na (which ignores nan values), but we aim to extend this to all normal operations in the future. Other planned improvements are further improving per-column parallel execution of a query and extending numexpr with in/not in functionality to further speed up advanced filtering.

Though nascent, the technology itself is reliable and stable, if still limited in the depth of functionality. Visualfabriq uses bcolz and bquery to reliably handle billions of records for our clients with real-time reporting and machine learning usage.

Bquery requires bcolz. The user is also greatly encouraged to install numexpr.

Any help in extending, improving and speeding up bquery is very welcome.

Usage

Bquery subclasses the ctable from bcolz, meaning that all original ctable functions are available while adding specific new ones. First start by having a ctable (if you do not have anything available, see the '''bench_groupby.py''' file for an example.

import bquery
# assuming you have an example on-table bcolz file called example.bcolz
ct = bquery.ctable(rootdir='example.bcolz')

A groupby with aggregation is easy to perform:

ctable.groupby(list of groupby columns, agg_list)

The agg_list contains the aggregations operations, which can be:

  • a straight forward sum of a list of columns with a similarly named output: ['m1', 'm2', ...]
  • a list of new columns with input/output names [['mnew1', 'm1'], ['mnew2', 'm2], ...]
  • a list that includes the type of aggregation for each column, i.e. [['mnew1', 'm1', 'sum'], ['mnew2', 'm1, 'avg'], ...]

Examples:

# groupby column f0, perform a sum on column f2 and keep the output column with the same name
ct.groupby(['f0'], ['f2'])
# groupby column f0, perform a sum on column f2 and rename the output column to f2_sum
ct.groupby(['f0'], [['f2', 'f2_sum']])
# groupby column f0, with a sum on f2 ('f2_sum') and a sum_na on f2 ('f2_sum_na')
ct.groupby(['f0'], [['f2', 'f2_sum', 'sum'], ['f2', 'f2_sum_na', 'sum_na']])

If recurrent aggregations are done (typical in a reporting environment), you can speed up aggregations by preparing factorizations of groupby columns:

ctable.cache_factor(list of all possible groupby columns)

# cache factorization of column f0 to speed up future groupbys over column f0
ct.cache_factor(['f0'])

If the table is changed, the factorization has to be re-performed. This is not triggered automatically yet.

Building & Installing

To be able to build, the package bcolz with carray_ext.pxd at least version 0.8.0 is needed.

Clone bcolz build it and install it (at the moment both steps needed)

git clone https://github.com/blosc/bcolz.git
cd bcolz
python setup.py build_ext --inplace
cd ..
export PYTHONPATH=$(pwd)/bcolz:${PYTHONPATH}

Go back to your bquery directory and repeat build and install steps. Note: bquery/templates/ctable_ext.template.pyx will be used as template to generate the source file bquery/ctable_ext.pyx used by the cython compiler, if you are developing new features remember to write those modifications in the template file, bquery/ctable_ext.pyx will be overwritten each time you run python setup.py build_ext --from-templates --inplace.

python setup.py build_ext --from-templates --inplace
python setup.py install

Testing

nosetests bquery

Benchmarks

Short benchmark to compare bquery, cytoolz & pandas
python bquery/benchmarks/bench_groupby.py

Results might vary depending on where testing is performed

Note: ctable is in this case on-disk storage vs pandas in-memory

Groupby on column 'f0'
Aggregation results on column 'f2'
Rows: 1000000
ctable((1000000,), [('f0', 'S2'), ('f1', 'S2'), ('f2', '<i8'), ('f3', '<i8')])
nbytes: 19.07 MB; cbytes: 1.14 MB; ratio: 16.70
cparams := cparams(clevel=5, shuffle=True, cname='blosclz')
rootdir := '/var/folders/_y/zgh0g75d13d65nd9_d7x8llr0000gn/T/bcolz-LaL2Hn'
[('ES', 'b1', 1, -1) ('NL', 'b2', 2, -2) ('ES', 'b3', 1, -1) ...,
('NL', 'b3', 2, -2) ('ES', 'b4', 1, -1) ('NL', 'b5', 2, -2)]
pandas: 0.0827 sec
f0
ES 500000
NL 1000000
Name: f2, dtype: int64
cytoolz over bcolz: 1.8612 sec
x22.5 slower than pandas
{'NL': 1000000, 'ES': 500000}
blaze over bcolz: 0.2983 sec
x3.61 slower than pandas
f0 sum_f2
0 ES 500000
1 NL 1000000
bquery over bcolz: 0.1833 sec
x2.22 slower than pandas
[('ES', 500000) ('NL', 1000000)]
bquery over bcolz (factorization cached): 0.1302 sec
x1.57 slower than pandas
[('ES', 500000) ('NL', 1000000)]

For details about these results see please the python script

You could also have a look at http://nbviewer.ipython.org/github/visualfabriq/bquery/blob/ipynb_bench/bquery/benchmarks/bench_groupby.ipynb

Performance (vbench)

Run vbench suite
python bquery/benchmarks/vb_suite/run_suite.py

About

A query and aggregation framework for Bcolz

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages