| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,382 @@ | ||
| .. currentmodule:: ibis | ||
| .. _api: | ||
|
|
||
| ************* | ||
| API Reference | ||
| ************* | ||
|
|
||
| .. currentmodule:: ibis | ||
|
|
||
| .. _api.client: | ||
|
|
||
| Creating connections | ||
| -------------------- | ||
|
|
||
| These methods are in the ``ibis`` module namespace, and your main point of | ||
| entry to using Ibis. | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| make_client | ||
| impala_connect | ||
| hdfs_connect | ||
|
|
||
| Impala client | ||
| ------------- | ||
|
|
||
| These methods are available on the Impala client object after connecting to | ||
| your Impala cluster, HDFS cluster, and creating the client with | ||
| ``ibis.make_client``. | ||
|
|
||
| Table methods | ||
| ~~~~~~~~~~~~~ | ||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ImpalaClient.table | ||
| ImpalaClient.sql | ||
| ImpalaClient.list_tables | ||
| ImpalaClient.exists_table | ||
| ImpalaClient.drop_table | ||
| ImpalaClient.create_table | ||
| ImpalaClient.insert | ||
| ImpalaClient.truncate_table | ||
| ImpalaClient.get_schema | ||
| ImpalaClient.cache_table | ||
|
|
||
| Creating views is also possible: | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ImpalaClient.create_view | ||
| ImpalaClient.drop_view | ||
| ImpalaClient.drop_table_or_view | ||
|
|
||
| Accessing data formats in HDFS | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ImpalaClient.avro_file | ||
| ImpalaClient.delimited_file | ||
| ImpalaClient.parquet_file | ||
|
|
||
| Database methods | ||
| ~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ImpalaClient.set_database | ||
| ImpalaClient.create_database | ||
| ImpalaClient.drop_database | ||
| ImpalaClient.list_databases | ||
| ImpalaClient.exists_database | ||
|
|
||
| Executing expressions | ||
| ~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ImpalaClient.execute | ||
| ImpalaClient.disable_codegen | ||
|
|
||
| .. _api.hdfs: | ||
|
|
||
| HDFS | ||
| ---- | ||
|
|
||
| Client objects have an ``hdfs`` attribute you can use to interact directly with | ||
| HDFS. | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| HDFS.ls | ||
| HDFS.get | ||
| HDFS.head | ||
| HDFS.put | ||
| HDFS.put_tarfile | ||
| HDFS.rm | ||
| HDFS.rmdir | ||
| HDFS.size | ||
| HDFS.status | ||
|
|
||
| Top-level expression APIs | ||
| ------------------------- | ||
|
|
||
| These methods are available directly in the ``ibis`` module namespace. | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| case | ||
| literal | ||
| schema | ||
| table | ||
| timestamp | ||
| where | ||
| ifelse | ||
| coalesce | ||
| greatest | ||
| least | ||
| negate | ||
| desc | ||
| now | ||
| NA | ||
| null | ||
| expr_list | ||
| row_number | ||
| window | ||
| trailing_window | ||
| cumulative_window | ||
|
|
||
| .. _api.table: | ||
|
|
||
| Table methods | ||
| ------------- | ||
|
|
||
| .. currentmodule:: ibis.expr.api | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| TableExpr.add_column | ||
| TableExpr.aggregate | ||
| TableExpr.count | ||
| TableExpr.distinct | ||
| TableExpr.filter | ||
| TableExpr.get_column | ||
| TableExpr.get_columns | ||
| TableExpr.group_by | ||
| TableExpr.limit | ||
| TableExpr.mutate | ||
| TableExpr.pipe | ||
| TableExpr.projection | ||
| TableExpr.schema | ||
| TableExpr.set_column | ||
| TableExpr.sort_by | ||
| TableExpr.union | ||
| TableExpr.view | ||
|
|
||
| TableExpr.join | ||
| TableExpr.cross_join | ||
| TableExpr.inner_join | ||
| TableExpr.left_join | ||
| TableExpr.outer_join | ||
| TableExpr.semi_join | ||
| TableExpr.anti_join | ||
|
|
||
|
|
||
| Grouped table methods | ||
| ~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| GroupedTableExpr.aggregate | ||
| GroupedTableExpr.count | ||
| GroupedTableExpr.having | ||
| GroupedTableExpr.mutate | ||
| GroupedTableExpr.order_by | ||
| GroupedTableExpr.over | ||
| GroupedTableExpr.projection | ||
| GroupedTableExpr.size | ||
|
|
||
| Generic value methods | ||
| --------------------- | ||
|
|
||
| .. _api.functions: | ||
|
|
||
| Scalar or array methods | ||
| ~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ValueExpr.between | ||
| ValueExpr.cast | ||
| ValueExpr.fillna | ||
| ValueExpr.isin | ||
| ValueExpr.notin | ||
| ValueExpr.nullif | ||
| ValueExpr.hash | ||
| ValueExpr.isnull | ||
| ValueExpr.notnull | ||
| ValueExpr.over | ||
|
|
||
| ValueExpr.add | ||
| ValueExpr.sub | ||
| ValueExpr.mul | ||
| ValueExpr.div | ||
| ValueExpr.pow | ||
| ValueExpr.rdiv | ||
| ValueExpr.rsub | ||
|
|
||
| Array methods | ||
| ~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| ArrayExpr.case | ||
| ArrayExpr.cases | ||
| ArrayExpr.distinct | ||
|
|
||
| ArrayExpr.count | ||
| ArrayExpr.min | ||
| ArrayExpr.max | ||
| ArrayExpr.approx_median | ||
| ArrayExpr.approx_nunique | ||
| ArrayExpr.group_concat | ||
| ArrayExpr.nunique | ||
| ArrayExpr.summary | ||
|
|
||
| ArrayExpr.value_counts | ||
|
|
||
| ArrayExpr.first | ||
| ArrayExpr.last | ||
| ArrayExpr.dense_rank | ||
| ArrayExpr.rank | ||
| ArrayExpr.lag | ||
| ArrayExpr.lead | ||
| ArrayExpr.cummin | ||
| ArrayExpr.cummax | ||
|
|
||
| General numeric methods | ||
| ----------------------- | ||
|
|
||
| Scalar or array methods | ||
| ~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| NumericValue.abs | ||
| NumericValue.ceil | ||
| NumericValue.floor | ||
| NumericValue.sign | ||
| NumericValue.exp | ||
|
|
||
|
|
||
| Array methods | ||
| ~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| NumericArray.sum | ||
| NumericArray.mean | ||
|
|
||
| NumericArray.cumsum | ||
| NumericArray.cummean | ||
|
|
||
| NumericArray.bottomk | ||
| NumericArray.topk | ||
| NumericArray.bucket | ||
| NumericArray.histogram | ||
|
|
||
| Integer methods | ||
| --------------- | ||
|
|
||
| Scalar or array methods | ||
| ~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| IntegerValue.to_timestamp | ||
|
|
||
| .. _api.string: | ||
|
|
||
| String methods | ||
| -------------- | ||
|
|
||
| All string operations are valid either on scalar or array values | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| StringValue.length | ||
| StringValue.lower | ||
| StringValue.upper | ||
| StringValue.reverse | ||
| StringValue.ascii_str | ||
| StringValue.strip | ||
| StringValue.lstrip | ||
| StringValue.rstrip | ||
| StringValue.capitalize | ||
| StringValue.contains | ||
| StringValue.like | ||
| StringValue.parse_url | ||
| StringValue.substr | ||
| StringValue.left | ||
| StringValue.right | ||
| StringValue.repeat | ||
| StringValue.find | ||
| StringValue.translate | ||
| StringValue.find_in_set | ||
| StringValue.join | ||
| StringValue.lpad | ||
| StringValue.rpad | ||
|
|
||
| StringValue.rlike | ||
| StringValue.re_search | ||
| StringValue.re_extract | ||
| StringValue.re_replace | ||
|
|
||
|
|
||
| Timestamp methods | ||
| ----------------- | ||
|
|
||
| All timestamp operations are valid either on scalar or array values | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| TimestampValue.truncate | ||
| TimestampValue.year | ||
| TimestampValue.month | ||
| TimestampValue.day | ||
| TimestampValue.hour | ||
| TimestampValue.minute | ||
| TimestampValue.second | ||
| TimestampValue.millisecond | ||
|
|
||
| Boolean methods | ||
| --------------- | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| BooleanValue.ifelse | ||
|
|
||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| BooleanArray.any | ||
|
|
||
| Category methods | ||
| ---------------- | ||
|
|
||
| Category is a logical type with either a known or unknown cardinality. Values | ||
| are represented semantically as integers starting at 0. | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| CategoryValue.label | ||
|
|
||
| Decimal methods | ||
| --------------- | ||
|
|
||
| .. autosummary:: | ||
| :toctree: generated/ | ||
|
|
||
| DecimalValue.precision | ||
| DecimalValue.scale |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| .. _configuration: | ||
|
|
||
| **************** | ||
| Configuring Ibis | ||
| **************** |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| .. _develop: | ||
|
|
||
| *********************************** | ||
| Developing and Contributing to Ibis | ||
| *********************************** | ||
|
|
||
| For a primer on general open source contributions, see the `pandas contribution | ||
| guide <http://pandas.pydata.org/pandas-docs/stable/contributing.html>`_. The | ||
| project will be run much like pandas has been. | ||
|
|
||
| Test environment setup | ||
| ---------------------- | ||
|
|
||
| If you do not have access to an Impala cluster, you may wish to set up the test | ||
| virtual machine. We've set up a Quickstart VM to get you up and running faster, | ||
| :ref:`see here <install.quickstart>`. | ||
|
|
||
| Unit tests and integration tests that use Impala require a test data load. See | ||
| ``scripts/load_test_data.py`` in the source repository for the data loading | ||
| script. | ||
|
|
||
| Contribution Ideas | ||
| ------------------ | ||
|
|
||
| Here's a few ideas to think about outside of participating in the primary | ||
| development roadmap: | ||
|
|
||
| * Documentation | ||
| * Use cases and IPython notebooks | ||
| * Other SQL-based backends (Presto, Hive, Spark SQL, PostgreSQL) | ||
| * S3 filesytem support | ||
| * Integration with MLLib via PySpark | ||
|
|
||
| Contributor License Agreements | ||
| ------------------------------ | ||
|
|
||
| While Ibis is an Apache-licensed open source project, we require individual and | ||
| corporate contributors to execute a `contributor license agreement | ||
| <https://en.wikipedia.org/wiki/Contributor_License_Agreement>`_ to enable any | ||
| copyright issues to be avoided and to protect the user base from | ||
| disruption. This agreement only needs to be signed once. | ||
|
|
||
| We'll use the same CLA's that Impala uses: | ||
|
|
||
| * `Individual CLA <https://github.com/cloudera/Impala/wiki/Individual-Contributor-License-Agreement-(ICLA)>`_ | ||
| * `Corporate CLA <https://github.com/cloudera/Impala/wiki/Corporate-Contributor-License-Agreement-(CCLA)>`_ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| .. _install: | ||
|
|
||
| ******************************** | ||
| Installation and Getting Started | ||
| ******************************** | ||
|
|
||
| Getting up and running with Ibis involves installing the Python package and | ||
| connecting to HDFS and Impala. If you don't have a Hadoop cluster available | ||
| with Impala, see :ref:`install.quickstart` below for instructions to use a VM | ||
| to get up and running quickly. | ||
|
|
||
| Installation | ||
| ------------ | ||
|
|
||
| System dependencies | ||
| ~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| Ibis requires a working Python 2.6 or 2.7 installation (3.x support will come | ||
| in a future release). We recommend `Anaconda <http://continuum.io/downloads>`_. | ||
|
|
||
| Some platforms will require that you have Kerberos installed to build properly. | ||
|
|
||
| * Redhat / CentOS: ``yum install krb5-devel`` | ||
| * Ubuntu / Debian: ``apt-get install libkrb5-dev`` | ||
|
|
||
| Installing the Python package | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
| Install ibis using ``pip`` (or ``conda``, whenever it becomes available): | ||
|
|
||
| :: | ||
|
|
||
| pip install ibis-framework | ||
|
|
||
| This installs the ``ibis`` library to your configured Python environment. | ||
|
|
||
| Creating a client | ||
| ----------------- | ||
|
|
||
| To create an Ibis "client", you must first connect your services and assemble | ||
| the client using ``ibis.make_client``: | ||
|
|
||
| .. code-block:: python | ||
| import ibis | ||
| ic = ibis.impala_connect(host=impala_host, port=impala_port) | ||
| hdfs = ibis.hdfs_connect(host=webhdfs_host, port=webhdfs_port) | ||
| con = ibis.make_client(ic, hdfs_client=hdfs) | ||
| Depending on your cluster setup, this may be more complicated, especially if | ||
| LDAP or Kerberos is involved. See the :ref:`API reference <api.client>` for | ||
| more. | ||
|
|
||
| Learning resources | ||
| ------------------ | ||
|
|
||
| We are collecting IPython notebooks for learning here: | ||
| http://github.com/cloudera/ibis-notebooks. Some of these notebooks will be | ||
| reproduced as part of the documentation. | ||
|
|
||
| .. _install.quickstart: | ||
|
|
||
| Using Ibis with the Cloudera Quickstart VM | ||
| ------------------------------------------ | ||
|
|
||
| Since Ibis requires a running Impala cluster, we have provided a lean | ||
| VirtualBox image to simplify the process for those looking to try out Ibis | ||
| (without setting up a cluster) or start contributing code to the project. | ||
|
|
||
| TL;DR | ||
| ~~~~~ | ||
|
|
||
| :: | ||
|
|
||
| curl -s https://raw.githubusercontent.com/cloudera/ibis-notebooks/master/setup/bootstrap.sh | bash | ||
|
|
||
| Single Steps | ||
| ~~~~~~~~~~~~ | ||
|
|
||
| To use Ibis with the special Cloudera Quickstart VM follow the below | ||
| instructions: | ||
|
|
||
| * Install Oracle VirtualBox | ||
| * Make sure Anaconda is installed. You can get it from | ||
| http://continuum.io/downloads. Now prepend the Anaconda Python | ||
| to your path like this ``export PATH=$ANACONDA_HOME/bin:$PATH`` | ||
| * ``pip install ibis-framework`` | ||
| * ``git clone https://github.com/cloudera/ibis-notebooks.git`` | ||
| * ``cd ibis-notebooks`` | ||
| * ``./setup/setup-ibis-demo-vm.sh`` | ||
| * ``source setup/ibis-env.sh`` | ||
| * ``ipython notebook`` | ||
|
|
||
| VM setup | ||
| ~~~~~~~~ | ||
|
|
||
| The setup script will download a VirtualBox appliance image and import it in | ||
| VirtualBox. In addition, it will create a new host only network adapter with | ||
| DHCP. After the VM is started, it will extract the current IP address and add a | ||
| new /etc/hosts entry pointing from the IP of the VM to the hostname | ||
| ``quickstart.cloudera``. The reason for this entry is that Hadoop and HDFS | ||
| require a working reverse name mapping. If you don't want to run the automated | ||
| steps make sure to check the individual steps in the file | ||
| ``setup/setup-ibis-demo-vm.sh``. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,211 @@ | ||
| ===== | ||
| Legal | ||
| ===== | ||
|
|
||
| Ibis is distributed under the Apache License, Version 2.0. | ||
|
|
||
| Ibis development is generously sponsored by Cloudera, Inc. | ||
|
|
||
| License:: | ||
|
|
||
| Apache License | ||
| Version 2.0, January 2004 | ||
| http://www.apache.org/licenses/ | ||
|
|
||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
|
|
||
| 1. Definitions. | ||
|
|
||
| "License" shall mean the terms and conditions for use, reproduction, | ||
| and distribution as defined by Sections 1 through 9 of this document. | ||
|
|
||
| "Licensor" shall mean the copyright owner or entity authorized by | ||
| the copyright owner that is granting the License. | ||
|
|
||
| "Legal Entity" shall mean the union of the acting entity and all | ||
| other entities that control, are controlled by, or are under common | ||
| control with that entity. For the purposes of this definition, | ||
| "control" means (i) the power, direct or indirect, to cause the | ||
| direction or management of such entity, whether by contract or | ||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||
|
|
||
| "You" (or "Your") shall mean an individual or Legal Entity | ||
| exercising permissions granted by this License. | ||
|
|
||
| "Source" form shall mean the preferred form for making modifications, | ||
| including but not limited to software source code, documentation | ||
| source, and configuration files. | ||
|
|
||
| "Object" form shall mean any form resulting from mechanical | ||
| transformation or translation of a Source form, including but | ||
| not limited to compiled object code, generated documentation, | ||
| and conversions to other media types. | ||
|
|
||
| "Work" shall mean the work of authorship, whether in Source or | ||
| Object form, made available under the License, as indicated by a | ||
| copyright notice that is included in or attached to the work | ||
| (an example is provided in the Appendix below). | ||
|
|
||
| "Derivative Works" shall mean any work, whether in Source or Object | ||
| form, that is based on (or derived from) the Work and for which the | ||
| editorial revisions, annotations, elaborations, or other modifications | ||
| represent, as a whole, an original work of authorship. For the purposes | ||
| of this License, Derivative Works shall not include works that remain | ||
| separable from, or merely link (or bind by name) to the interfaces of, | ||
| the Work and Derivative Works thereof. | ||
|
|
||
| "Contribution" shall mean any work of authorship, including | ||
| the original version of the Work and any modifications or additions | ||
| to that Work or Derivative Works thereof, that is intentionally | ||
| submitted to Licensor for inclusion in the Work by the copyright owner | ||
| or by an individual or Legal Entity authorized to submit on behalf of | ||
| the copyright owner. For the purposes of this definition, "submitted" | ||
| means any form of electronic, verbal, or written communication sent | ||
| to the Licensor or its representatives, including but not limited to | ||
| communication on electronic mailing lists, source code control systems, | ||
| and issue tracking systems that are managed by, or on behalf of, the | ||
| Licensor for the purpose of discussing and improving the Work, but | ||
| excluding communication that is conspicuously marked or otherwise | ||
| designated in writing by the copyright owner as "Not a Contribution." | ||
|
|
||
| "Contributor" shall mean Licensor and any individual or Legal Entity | ||
| on behalf of whom a Contribution has been received by Licensor and | ||
| subsequently incorporated within the Work. | ||
|
|
||
| 2. Grant of Copyright License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| copyright license to reproduce, prepare Derivative Works of, | ||
| publicly display, publicly perform, sublicense, and distribute the | ||
| Work and such Derivative Works in Source or Object form. | ||
|
|
||
| 3. Grant of Patent License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| (except as stated in this section) patent license to make, have made, | ||
| use, offer to sell, sell, import, and otherwise transfer the Work, | ||
| where such license applies only to those patent claims licensable | ||
| by such Contributor that are necessarily infringed by their | ||
| Contribution(s) alone or by combination of their Contribution(s) | ||
| with the Work to which such Contribution(s) was submitted. If You | ||
| institute patent litigation against any entity (including a | ||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
| or a Contribution incorporated within the Work constitutes direct | ||
| or contributory patent infringement, then any patent licenses | ||
| granted to You under this License for that Work shall terminate | ||
| as of the date such litigation is filed. | ||
|
|
||
| 4. Redistribution. You may reproduce and distribute copies of the | ||
| Work or Derivative Works thereof in any medium, with or without | ||
| modifications, and in Source or Object form, provided that You | ||
| meet the following conditions: | ||
|
|
||
| (a) You must give any other recipients of the Work or | ||
| Derivative Works a copy of this License; and | ||
|
|
||
| (b) You must cause any modified files to carry prominent notices | ||
| stating that You changed the files; and | ||
|
|
||
| (c) You must retain, in the Source form of any Derivative Works | ||
| that You distribute, all copyright, patent, trademark, and | ||
| attribution notices from the Source form of the Work, | ||
| excluding those notices that do not pertain to any part of | ||
| the Derivative Works; and | ||
|
|
||
| (d) If the Work includes a "NOTICE" text file as part of its | ||
| distribution, then any Derivative Works that You distribute must | ||
| include a readable copy of the attribution notices contained | ||
| within such NOTICE file, excluding those notices that do not | ||
| pertain to any part of the Derivative Works, in at least one | ||
| of the following places: within a NOTICE text file distributed | ||
| as part of the Derivative Works; within the Source form or | ||
| documentation, if provided along with the Derivative Works; or, | ||
| within a display generated by the Derivative Works, if and | ||
| wherever such third-party notices normally appear. The contents | ||
| of the NOTICE file are for informational purposes only and | ||
| do not modify the License. You may add Your own attribution | ||
| notices within Derivative Works that You distribute, alongside | ||
| or as an addendum to the NOTICE text from the Work, provided | ||
| that such additional attribution notices cannot be construed | ||
| as modifying the License. | ||
|
|
||
| You may add Your own copyright statement to Your modifications and | ||
| may provide additional or different license terms and conditions | ||
| for use, reproduction, or distribution of Your modifications, or | ||
| for any such Derivative Works as a whole, provided Your use, | ||
| reproduction, and distribution of the Work otherwise complies with | ||
| the conditions stated in this License. | ||
|
|
||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | ||
| any Contribution intentionally submitted for inclusion in the Work | ||
| by You to the Licensor shall be under the terms and conditions of | ||
| this License, without any additional terms or conditions. | ||
| Notwithstanding the above, nothing herein shall supersede or modify | ||
| the terms of any separate license agreement you may have executed | ||
| with Licensor regarding such Contributions. | ||
|
|
||
| 6. Trademarks. This License does not grant permission to use the trade | ||
| names, trademarks, service marks, or product names of the Licensor, | ||
| except as required for reasonable and customary use in describing the | ||
| origin of the Work and reproducing the content of the NOTICE file. | ||
|
|
||
| 7. Disclaimer of Warranty. Unless required by applicable law or | ||
| agreed to in writing, Licensor provides the Work (and each | ||
| Contributor provides its Contributions) on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
| implied, including, without limitation, any warranties or conditions | ||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
| PARTICULAR PURPOSE. You are solely responsible for determining the | ||
| appropriateness of using or redistributing the Work and assume any | ||
| risks associated with Your exercise of permissions under this License. | ||
|
|
||
| 8. Limitation of Liability. In no event and under no legal theory, | ||
| whether in tort (including negligence), contract, or otherwise, | ||
| unless required by applicable law (such as deliberate and grossly | ||
| negligent acts) or agreed to in writing, shall any Contributor be | ||
| liable to You for damages, including any direct, indirect, special, | ||
| incidental, or consequential damages of any character arising as a | ||
| result of this License or out of the use or inability to use the | ||
| Work (including but not limited to damages for loss of goodwill, | ||
| work stoppage, computer failure or malfunction, or any and all | ||
| other commercial damages or losses), even if such Contributor | ||
| has been advised of the possibility of such damages. | ||
|
|
||
| 9. Accepting Warranty or Additional Liability. While redistributing | ||
| the Work or Derivative Works thereof, You may choose to offer, | ||
| and charge a fee for, acceptance of support, warranty, indemnity, | ||
| or other liability obligations and/or rights consistent with this | ||
| License. However, in accepting such obligations, You may act only | ||
| on Your own behalf and on Your sole responsibility, not on behalf | ||
| of any other Contributor, and only if You agree to indemnify, | ||
| defend, and hold each Contributor harmless for any liability | ||
| incurred by, or claims asserted against, such Contributor by reason | ||
| of your accepting any such warranty or additional liability. | ||
|
|
||
| END OF TERMS AND CONDITIONS | ||
|
|
||
| APPENDIX: How to apply the Apache License to your work. | ||
|
|
||
| To apply the Apache License to your work, attach the following | ||
| boilerplate notice, with the fields enclosed by brackets "[]" | ||
| replaced with your own identifying information. (Don't include | ||
| the brackets!) The text should be enclosed in the appropriate | ||
| comment syntax for the file format. We also recommend that a | ||
| file or class name and description of purpose be included on the | ||
| same "printed page" as the copyright notice for easier | ||
| identification within third-party archives. | ||
|
|
||
| Copyright [yyyy] [name of copyright owner] | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| .. _api: | ||
|
|
||
| ******** | ||
| Tutorial | ||
| ******** | ||
|
|
||
| These notebooks come from http://github.com/cloudera/ibis-notebooks and are | ||
| reproduced here using ``nbconvert``. | ||
|
|
||
| .. include:: generated-notebooks/manifest.txt |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| .. _internals: | ||
|
|
||
| ********************* | ||
| Ibis design internals | ||
| ********************* | ||
|
|
||
| More to come here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Copyright 2015 Cloudera Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # flake8: noqa | ||
|
|
||
| import sys | ||
| from six import BytesIO | ||
|
|
||
|
|
||
| PY26 = sys.version_info[0] == 2 and sys.version_info[1] == 6 | ||
|
|
||
|
|
||
| if PY26: | ||
| import unittest2 as unittest | ||
| else: | ||
| import unittest | ||
|
|
||
|
|
||
| py_string = basestring |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| # Copyright 2014 Cloudera Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import ibis | ||
|
|
||
| from ibis.compat import unittest | ||
| from ibis.expr.format import ExprFormatter | ||
| from ibis.expr.tests.mocks import MockConnection | ||
|
|
||
|
|
||
| class TestExprFormatting(unittest.TestCase): | ||
| # Uncertain about how much we want to commit to unit tests around the | ||
| # particulars of the output at the moment. | ||
|
|
||
| def setUp(self): | ||
| self.schema = [ | ||
| ('a', 'int8'), | ||
| ('b', 'int16'), | ||
| ('c', 'int32'), | ||
| ('d', 'int64'), | ||
| ('e', 'float'), | ||
| ('f', 'double'), | ||
| ('g', 'string'), | ||
| ('h', 'boolean') | ||
| ] | ||
| self.schema_dict = dict(self.schema) | ||
| self.table = ibis.table(self.schema) | ||
|
|
||
| def test_format_projection(self): | ||
| # This should produce a ref to the projection | ||
| proj = self.table[['c', 'a', 'f']] | ||
| repr(proj['a']) | ||
|
|
||
| def test_table_type_output(self): | ||
| foo = ibis.table( | ||
| [ | ||
| ('job', 'string'), | ||
| ('dept_id', 'string'), | ||
| ('year', 'int32'), | ||
| ('y', 'double') | ||
| ], 'foo') | ||
|
|
||
| expr = foo.dept_id == foo.view().dept_id | ||
| result = repr(expr) | ||
| assert 'SelfReference[table]' in result | ||
| assert 'UnboundTable[table]' in result | ||
|
|
||
| def test_memoize_aggregate_correctly(self): | ||
| table = self.table | ||
|
|
||
| agg_expr = (table['c'].sum() / table['c'].mean() - 1).name('analysis') | ||
| agg_exprs = [table['a'].sum().name('sum(a)'), | ||
| table['b'].mean().name('mean(b)'), agg_expr] | ||
|
|
||
| result = table.aggregate(agg_exprs, by=['g']) | ||
|
|
||
| formatter = ExprFormatter(result) | ||
| formatted = formatter.get_result() | ||
|
|
||
| alias = formatter.memo.get_alias(table.op()) | ||
| assert formatted.count(alias) == 7 | ||
|
|
||
| def test_aggregate_arg_names(self): | ||
| # Not sure how to test this *well* | ||
|
|
||
| t = self.table | ||
|
|
||
| by_exprs = [t.g.name('key1'), t.f.round().name('key2')] | ||
| agg_exprs = [t.c.sum().name('c'), t.d.mean().name('d')] | ||
|
|
||
| expr = self.table.group_by(by_exprs).aggregate(agg_exprs) | ||
| result = repr(expr) | ||
| assert 'metrics' in result | ||
| assert 'by' in result | ||
|
|
||
| def test_format_multiple_join_with_projection(self): | ||
| # Star schema with fact table | ||
| table = ibis.table([ | ||
| ('c', 'int32'), | ||
| ('f', 'double'), | ||
| ('foo_id', 'string'), | ||
| ('bar_id', 'string'), | ||
| ]) | ||
|
|
||
| table2 = ibis.table([ | ||
| ('foo_id', 'string'), | ||
| ('value1', 'double') | ||
| ]) | ||
|
|
||
| table3 = ibis.table([ | ||
| ('bar_id', 'string'), | ||
| ('value2', 'double') | ||
| ]) | ||
|
|
||
| filtered = table[table['f'] > 0] | ||
|
|
||
| pred1 = table['foo_id'] == table2['foo_id'] | ||
| pred2 = filtered['bar_id'] == table3['bar_id'] | ||
|
|
||
| j1 = filtered.left_join(table2, [pred1]) | ||
| j2 = j1.inner_join(table3, [pred2]) | ||
|
|
||
| # Project out the desired fields | ||
| view = j2[[table, table2['value1'], table3['value2']]] | ||
|
|
||
| # it works! | ||
| repr(view) | ||
|
|
||
| def test_memoize_database_table(self): | ||
| con = MockConnection() | ||
| table = con.table('test1') | ||
| table2 = con.table('test2') | ||
|
|
||
| filter_pred = table['f'] > 0 | ||
| table3 = table[filter_pred] | ||
| join_pred = table3['g'] == table2['key'] | ||
|
|
||
| joined = table2.inner_join(table3, [join_pred]) | ||
|
|
||
| met1 = (table3['f'] - table2['value']).mean().name('foo') | ||
| result = joined.aggregate([met1, table3['f'].sum().name('bar')], | ||
| by=[table3['g'], table2['key']]) | ||
|
|
||
| formatted = repr(result) | ||
| assert formatted.count('test1') == 1 | ||
| assert formatted.count('test2') == 1 | ||
|
|
||
| def test_named_value_expr_show_name(self): | ||
| expr = self.table.f * 2 | ||
| expr2 = expr.name('baz') | ||
|
|
||
| # it works! | ||
| repr(expr) | ||
|
|
||
| result2 = repr(expr2) | ||
|
|
||
| # not really committing to a particular output yet | ||
| assert 'baz' in result2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| # Copyright 2014 Cloudera Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| from ibis.compat import unittest | ||
| from ibis.expr.tests.mocks import MockConnection | ||
| import ibis.config as config | ||
|
|
||
| from ibis.tests.util import assert_equal | ||
|
|
||
|
|
||
| class TestInteractiveUse(unittest.TestCase): | ||
|
|
||
| def setUp(self): | ||
| self.con = MockConnection() | ||
|
|
||
| def test_interactive_execute_on_repr(self): | ||
| table = self.con.table('functional_alltypes') | ||
| expr = table.bigint_col.sum() | ||
| with config.option_context('interactive', True): | ||
| repr(expr) | ||
|
|
||
| assert len(self.con.executed_queries) > 0 | ||
|
|
||
| def test_default_limit(self): | ||
| table = self.con.table('functional_alltypes') | ||
|
|
||
| with config.option_context('interactive', True): | ||
| repr(table) | ||
|
|
||
| expected = """\ | ||
| SELECT * | ||
| FROM functional_alltypes | ||
| LIMIT {0}""".format(config.options.sql.default_limit) | ||
|
|
||
| assert self.con.executed_queries[0] == expected | ||
|
|
||
| def test_disable_query_limit(self): | ||
| table = self.con.table('functional_alltypes') | ||
|
|
||
| with config.option_context('interactive', True): | ||
| with config.option_context('sql.default_limit', None): | ||
| repr(table) | ||
|
|
||
| expected = """\ | ||
| SELECT * | ||
| FROM functional_alltypes""" | ||
|
|
||
| assert self.con.executed_queries[0] == expected | ||
|
|
||
| def test_interactive_non_compilable_repr_not_fail(self): | ||
| # #170 | ||
| table = self.con.table('functional_alltypes') | ||
|
|
||
| expr = table.string_col.topk(3) | ||
|
|
||
| # it works! | ||
| with config.option_context('interactive', True): | ||
| repr(expr) | ||
|
|
||
| def test_histogram_repr_no_query_execute(self): | ||
| t = self.con.table('functional_alltypes') | ||
| tier = t.double_col.histogram(10).name('bucket') | ||
| expr = t.group_by(tier).size() | ||
| with config.option_context('interactive', True): | ||
| expr._repr() | ||
| assert self.con.executed_queries == [] |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| # Copyright 2014 Cloudera Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| from ibis.compat import unittest | ||
| import ibis | ||
|
|
||
|
|
||
| class TestPipe(unittest.TestCase): | ||
|
|
||
| def setUp(self): | ||
| self.table = ibis.table([ | ||
| ('key1', 'string'), | ||
| ('key2', 'string'), | ||
| ('key3', 'string'), | ||
| ('value', 'double') | ||
| ], 'foo_table') | ||
|
|
||
| def test_pipe_positional_args(self): | ||
| def my_func(data, foo, bar): | ||
| return data[bar] + foo | ||
|
|
||
| result = self.table.pipe(my_func, 4, 'value') | ||
| expected = self.table['value'] + 4 | ||
|
|
||
| assert result.equals(expected) | ||
|
|
||
| def test_pipe_keyword_args(self): | ||
| def my_func(data, foo=None, bar=None): | ||
| return data[bar] + foo | ||
|
|
||
| result = self.table.pipe(my_func, foo=4, bar='value') | ||
| expected = self.table['value'] + 4 | ||
|
|
||
| assert result.equals(expected) | ||
|
|
||
| def test_pipe_pass_to_keyword(self): | ||
| def my_func(x, y, data=None): | ||
| return data[x] + y | ||
|
|
||
| result = self.table.pipe((my_func, 'data'), 'value', 4) | ||
| expected = self.table['value'] + 4 | ||
|
|
||
| assert result.equals(expected) | ||
|
|
||
| def test_call_pipe_equivalence(self): | ||
| result = self.table(lambda x: x['key1'].cast('double').sum()) | ||
| expected = self.table.key1.cast('double').sum() | ||
| assert result.equals(expected) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| # Copyright 2014 Cloudera Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import ibis | ||
|
|
||
| from ibis.compat import unittest | ||
| from ibis.expr.tests.mocks import BasicTestCase | ||
|
|
||
| from ibis.tests.util import assert_equal | ||
|
|
||
|
|
||
| class TestWindowFunctions(BasicTestCase, unittest.TestCase): | ||
|
|
||
| def setUp(self): | ||
| BasicTestCase.setUp(self) | ||
| self.t = self.con.table('alltypes') | ||
|
|
||
| def test_compose_group_by_apis(self): | ||
| t = self.t | ||
| w = ibis.window(group_by=t.g, order_by=t.f) | ||
|
|
||
| diff = t.d - t.d.lag() | ||
| grouped = t.group_by('g').order_by('f') | ||
|
|
||
| expr = grouped[t, diff.name('diff')] | ||
| expr2 = grouped.mutate(diff=diff) | ||
| expr3 = grouped.mutate([diff.name('diff')]) | ||
|
|
||
| window_expr = (t.d - t.d.lag().over(w)).name('diff') | ||
| expected = t.projection([t, window_expr]) | ||
|
|
||
| assert_equal(expr, expected) | ||
| assert_equal(expr, expr2) | ||
| assert_equal(expr, expr3) | ||
|
|
||
| def test_combine_windows(self): | ||
| pass | ||
|
|
||
| def test_window_bind_to_table(self): | ||
| w = ibis.window(group_by='g', order_by=ibis.desc('f')) | ||
|
|
||
| w2 = w.bind(self.t) | ||
| expected = ibis.window(group_by=self.t.g, | ||
| order_by=ibis.desc(self.t.f)) | ||
|
|
||
| assert_equal(w2, expected) | ||
|
|
||
| def test_preceding_following_validate(self): | ||
| # these all work | ||
| [ | ||
| ibis.window(preceding=0), | ||
| ibis.window(following=0), | ||
| ibis.window(preceding=0, following=0), | ||
| ibis.window(preceding=(None, 4)), | ||
| ibis.window(preceding=(10, 4)), | ||
| ibis.window(following=(4, None)), | ||
| ibis.window(following=(4, 10)) | ||
| ] | ||
|
|
||
| # these are ill-specified | ||
| error_cases = [ | ||
| lambda: ibis.window(preceding=(1, 3)), | ||
| lambda: ibis.window(preceding=(3, 1), following=2), | ||
| lambda: ibis.window(preceding=(3, 1), following=(2, 4)), | ||
| lambda: ibis.window(preceding=-1), | ||
| lambda: ibis.window(following=-1), | ||
| lambda: ibis.window(preceding=(-1, 2)), | ||
| lambda: ibis.window(following=(2, -1)) | ||
| ] | ||
|
|
||
| for i, case in enumerate(error_cases): | ||
| with self.assertRaises(Exception): | ||
| case() | ||
|
|
||
| def test_window_equals(self): | ||
| pass |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,210 @@ | ||
| # Copyright 2014 Cloudera Inc. | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| import ibis.expr.types as ir | ||
| import ibis.expr.operations as ops | ||
| import ibis.util as util | ||
| import ibis.common as com | ||
|
|
||
|
|
||
| def _list_to_tuple(x): | ||
| if isinstance(x, list): | ||
| x = tuple(x) | ||
| return x | ||
|
|
||
|
|
||
| class Window(object): | ||
|
|
||
| """ | ||
| A generic window function clause, patterned after SQL window clauses for | ||
| the time being. Can be expanded to cover more use cases as they arise. | ||
| Using None for preceding or following currently indicates unbounded. Use 0 | ||
| for current_value | ||
| """ | ||
|
|
||
| def __init__(self, group_by=None, order_by=None, | ||
| preceding=None, following=None): | ||
| if group_by is None: | ||
| group_by = [] | ||
|
|
||
| if order_by is None: | ||
| order_by = [] | ||
|
|
||
| self._group_by = util.promote_list(group_by) | ||
| self._order_by = util.promote_list(order_by) | ||
| self._order_by = [ops.SortKey(expr) | ||
| if isinstance(expr, ir.Expr) | ||
| else expr | ||
| for expr in self._order_by] | ||
|
|
||
| self.preceding = _list_to_tuple(preceding) | ||
| self.following = _list_to_tuple(following) | ||
|
|
||
| self._validate_frame() | ||
|
|
||
| def _validate_frame(self): | ||
| p_tuple = has_p = False | ||
| f_tuple = has_f = False | ||
| if self.preceding is not None: | ||
| p_tuple = isinstance(self.preceding, tuple) | ||
| has_p = True | ||
|
|
||
| if self.following is not None: | ||
| f_tuple = isinstance(self.following, tuple) | ||
| has_f = True | ||
|
|
||
| if ((p_tuple and has_f) or (f_tuple and has_p)): | ||
| raise com.IbisInputError('Can only specify one window side ' | ||
| ' when you want an off-center ' | ||
| 'window') | ||
| elif p_tuple: | ||
| start, end = self.preceding | ||
| if start is None: | ||
| assert end >= 0 | ||
| else: | ||
| assert start > end | ||
| elif f_tuple: | ||
| start, end = self.following | ||
| if end is None: | ||
| assert start >= 0 | ||
| else: | ||
| assert start < end | ||
| else: | ||
| if has_p and self.preceding < 0: | ||
| raise com.IbisInputError('Window offset must be positive') | ||
|
|
||
| if has_f and self.following < 0: | ||
| raise com.IbisInputError('Window offset must be positive') | ||
|
|
||
| def bind(self, table): | ||
| # Internal API, ensure that any unresolved expr references (as strings, | ||
| # say) are bound to the table being windowed | ||
| groups = table._resolve(self._group_by) | ||
| sorts = [ops.to_sort_key(table, k) for k in self._order_by] | ||
| return self._replace(group_by=groups, order_by=sorts) | ||
|
|
||
| def combine(self, window): | ||
| kwds = dict( | ||
| preceding=self.preceding or window.preceding, | ||
| following=self.following or window.following, | ||
| group_by=self._group_by + window._group_by, | ||
| order_by=self._order_by + window._order_by | ||
| ) | ||
| return Window(**kwds) | ||
|
|
||
| def group_by(self, expr): | ||
| new_groups = self._group_by + util.promote_list(expr) | ||
| return self._replace(group_by=new_groups) | ||
|
|
||
| def _replace(self, **kwds): | ||
| new_kwds = dict( | ||
| group_by=kwds.get('group_by', self._group_by), | ||
| order_by=kwds.get('order_by', self._order_by), | ||
| preceding=kwds.get('preceding', self.preceding), | ||
| following=kwds.get('following', self.following) | ||
| ) | ||
| return Window(**new_kwds) | ||
|
|
||
| def order_by(self, expr): | ||
| new_sorts = self._order_by + util.promote_list(expr) | ||
| return self._replace(order_by=new_sorts) | ||
|
|
||
| def equals(self, other): | ||
| if not isinstance(other, Window): | ||
| return False | ||
|
|
||
| if (len(self._group_by) != len(other._group_by) or | ||
| not ir.all_equal(self._group_by, other._group_by)): | ||
| return False | ||
|
|
||
| if (len(self._order_by) != len(other._order_by) or | ||
| not ir.all_equal(self._order_by, other._order_by)): | ||
| return False | ||
|
|
||
| return (self.preceding == other.preceding and | ||
| self.following == other.following) | ||
|
|
||
|
|
||
| def window(preceding=None, following=None, group_by=None, order_by=None): | ||
| """ | ||
| Create a window clause for use with window (analytic and aggregate) | ||
| functions. | ||
| All window frames / ranges are inclusive. | ||
| Parameters | ||
| ---------- | ||
| preceding : int, tuple, or None, default None | ||
| Specify None for unbounded, 0 to include current row | ||
| tuple for off-center window | ||
| following : int, tuple, or None, default None | ||
| Specify None for unbounded, 0 to include current row | ||
| tuple for off-center window | ||
| group_by : expressions, default None | ||
| Either specify here or with TableExpr.group_by | ||
| order_by : expressions, default None | ||
| For analytic functions requiring an ordering, specify here, or let Ibis | ||
| determine the default ordering (for functions like rank) | ||
| Returns | ||
| ------- | ||
| win : ibis Window | ||
| """ | ||
| return Window(preceding=preceding, following=following, | ||
| group_by=group_by, order_by=order_by) | ||
|
|
||
|
|
||
| def cumulative_window(group_by=None, order_by=None): | ||
| """ | ||
| Create a cumulative window clause for use with aggregate window functions. | ||
| All window frames / ranges are inclusive. | ||
| Parameters | ||
| ---------- | ||
| group_by : expressions, default None | ||
| Either specify here or with TableExpr.group_by | ||
| order_by : expressions, default None | ||
| For analytic functions requiring an ordering, specify here, or let Ibis | ||
| determine the default ordering (for functions like rank) | ||
| Returns | ||
| ------- | ||
| win : ibis Window | ||
| """ | ||
| return Window(preceding=None, following=0, | ||
| group_by=group_by, order_by=order_by) | ||
|
|
||
|
|
||
| def trailing_window(periods, group_by=None, order_by=None): | ||
| """ | ||
| Create a trailing window for use with aggregate window functions. | ||
| Parameters | ||
| ---------- | ||
| periods : int | ||
| Number of trailing periods to include. 0 includes only the current period | ||
| group_by : expressions, default None | ||
| Either specify here or with TableExpr.group_by | ||
| order_by : expressions, default None | ||
| For analytic functions requiring an ordering, specify here, or let Ibis | ||
| determine the default ordering (for functions like rank) | ||
| Returns | ||
| ------- | ||
| win : ibis Window | ||
| """ | ||
| return Window(preceding=periods, following=0, | ||
| group_by=group_by, order_by=order_by) |