From fc86a711a0550f0ff0f646ac1000c21404fa165d Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Wed, 23 Jan 2019 10:53:38 -0800 Subject: [PATCH 01/24] initial notebook tutorials --- .gitignore | 1 + .../BigQuery Basics_output.ipynb | 615 +++++++++++++ .../BigQuery Query Magic_output.ipynb | 818 ++++++++++++++++++ .../BigQuery Shell Commands_output.ipynb | 809 +++++++++++++++++ .../Storage Client Library_output.ipynb | 391 +++++++++ .../Storage Commands_output.ipynb | 468 ++++++++++ ...isualize BigQuery Public Data_output.ipynb | 763 ++++++++++++++++ .../tutorials/bigquery/BigQuery Basics.ipynb | 344 ++++++++ .../bigquery/BigQuery Query Magic.ipynb | 189 ++++ .../bigquery/BigQuery Shell Commands.ipynb | 144 +++ .../Visualize BigQuery Public Data.ipynb | 271 ++++++ .../bigquery/resources/us-states.csv | 51 ++ .../storage/Storage Client Library.ipynb | 294 +++++++ .../tutorials/storage/Storage Commands.ipynb | 241 ++++++ .../resources/downloaded-us-states.txt | 51 ++ .../tutorials/storage/resources/us-states.txt | 51 ++ 16 files changed, 5501 insertions(+) create mode 100644 notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb create mode 100644 notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb create mode 100644 notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb create mode 100644 notebooks/test/executed_notebooks/Storage Client Library_output.ipynb create mode 100644 notebooks/test/executed_notebooks/Storage Commands_output.ipynb create mode 100644 notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb create mode 100644 notebooks/tutorials/bigquery/BigQuery Basics.ipynb create mode 100644 notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb create mode 100644 notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb create mode 100644 notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb create mode 100644 notebooks/tutorials/bigquery/resources/us-states.csv create mode 100644 notebooks/tutorials/storage/Storage Client Library.ipynb create mode 100644 notebooks/tutorials/storage/Storage Commands.ipynb create mode 100644 notebooks/tutorials/storage/resources/downloaded-us-states.txt create mode 100644 notebooks/tutorials/storage/resources/us-states.txt diff --git a/.gitignore b/.gitignore index 79fbc1fc767..0cf723b8750 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ .coverage .tox .pytest_cache +.ipynb_checkpoints coverage.xml python-docs-samples.json service-account.json diff --git a/notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb b/notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb new file mode 100644 index 00000000000..fc0d6c2674a --- /dev/null +++ b/notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb @@ -0,0 +1,615 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext google.cloud.bigquery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery Basics\n", + "\n", + "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Import the libraries used in this tutorial" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import bigquery\n", + "import pandas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize a client\n", + "\n", + "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "client = bigquery.Client()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a query on a public dataset\n", + "\n", + "The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", + "\n", + "Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
name
0Mary
1Ruby
2Annie
3Willie
4Ruth
5Gladys
6Maria
7Frances
8Margaret
9Helen
\n", + "
" + ], + "text/plain": [ + " name\n", + "0 Mary\n", + "1 Ruby\n", + "2 Annie\n", + "3 Willie\n", + "4 Ruth\n", + "5 Gladys\n", + "6 Maria\n", + "7 Frances\n", + "8 Margaret\n", + "9 Helen" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "query = \"\"\"\n", + " SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + " WHERE state = \"TX\"\n", + " LIMIT 10\n", + "\"\"\"\n", + "query_job = client.query(\n", + " query,\n", + " # Location must match that of the dataset(s) referenced in the query.\n", + " location=\"US\",\n", + ") # API request - starts the query\n", + "\n", + "df = query_job.to_dataframe()\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a new dataset\n", + "\n", + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "\n", + "# Define a name for the new dataset.\n", + "dataset_id = 'test_dataset_1548268897503'\n", + "\n", + "# Create a DatasetReference using a chosen dataset ID.\n", + "# The project defaults to the Client's project if not specified.\n", + "dataset_ref = client.dataset(dataset_id)\n", + "\n", + "# Construct a full Dataset object to send to the API.\n", + "dataset = bigquery.Dataset(dataset_ref)\n", + "# Specify the geographic location where the dataset should reside.\n", + "dataset.location = 'US'\n", + "\n", + "# Send the dataset to the API for creation.\n", + "dataset = client.create_dataset(dataset) # API request" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a Pandas DataFrame to a new table" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded dataframe to /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/monty_python\n" + ] + } + ], + "source": [ + "records = [\n", + " {\"title\": \"The Meaning of Life\", \"release_year\": 1983},\n", + " {\"title\": \"Monty Python and the Holy Grail\", \"release_year\": 1975},\n", + " {\"title\": \"Life of Brian\", \"release_year\": 1979},\n", + " {\"title\": \"And Now for Something Completely Different\", \"release_year\": 1971},\n", + "]\n", + "\n", + "# Optionally set explicit indices.\n", + "# If indices are not specified, a column will be created for the default\n", + "# indices created by pandas.\n", + "index = [\"Q24980\", \"Q25043\", \"Q24953\", \"Q16403\"]\n", + "df = pandas.DataFrame(records, index=pandas.Index(index, name=\"wikidata_id\"))\n", + "\n", + "table_ref = dataset_ref.table(\"monty_python\")\n", + "job = client.load_table_from_dataframe(df, table_ref, location=\"US\")\n", + "\n", + "job.result() # Waits for table load to complete.\n", + "print(\"Loaded dataframe to {}\".format(table_ref.path))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load query results to a table\n", + "\n", + "For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Query results loaded to table /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/your_new_table_id\n" + ] + } + ], + "source": [ + "sql = \"\"\"\n", + " SELECT corpus\n", + " FROM `bigquery-public-data.samples.shakespeare`\n", + " GROUP BY corpus;\n", + "\"\"\"\n", + "table_ref = dataset.table(\"your_new_table_id\")\n", + "job_config = bigquery.QueryJobConfig(\n", + " destination=table_ref\n", + ")\n", + "\n", + "# Start the query, passing in the extra configuration.\n", + "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", + "\n", + "query_job.result() # Waits for the query to finish\n", + "print(\"Query results loaded to table {}\".format(table_ref.path))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a local file to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded 50 rows into test_dataset_1548268897503:/projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/us_states_from_local_file.\n" + ] + } + ], + "source": [ + "source_filename = 'resources/us-states.csv'\n", + "\n", + "table_ref = dataset_ref.table('us_states_from_local_file')\n", + "job_config = bigquery.LoadJobConfig(\n", + " source_format=bigquery.SourceFormat.CSV,\n", + " skip_leading_rows=1,\n", + " autodetect=True\n", + ")\n", + "\n", + "with open(source_filename, 'rb') as source_file:\n", + " job = client.load_table_from_file(\n", + " source_file,\n", + " table_ref,\n", + " location='US', # Must match the destination dataset location.\n", + " job_config=job_config) # API request\n", + "\n", + "job.result() # Waits for table load to complete.\n", + "\n", + "print('Loaded {} rows into {}:{}.'.format(\n", + " job.output_rows, dataset_id, table_ref.path))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from Google Cloud Storage to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Starting job f65c1470-3e8b-4b0f-8a44-ff6a3f5cbaf0\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Job finished.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Loaded 50 rows.\n" + ] + } + ], + "source": [ + "# Configure the load job\n", + "job_config = bigquery.LoadJobConfig(\n", + " schema=[\n", + " bigquery.SchemaField('name', 'STRING'),\n", + " bigquery.SchemaField('post_abbr', 'STRING')\n", + " ],\n", + " skip_leading_rows=1,\n", + " # The source format defaults to CSV, so the line below is optional.\n", + " source_format=bigquery.SourceFormat.CSV\n", + ")\n", + "uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'\n", + "destination_table_ref = dataset.table('us_states_from_gcs')\n", + "\n", + "# Start the load job\n", + "load_job = client.load_table_from_uri(\n", + " uri, destination_table_ref, job_config=job_config)\n", + "print('Starting job {}'.format(load_job.job_id))\n", + "\n", + "load_job.result() # Waits for table load to complete.\n", + "print('Job finished.')\n", + "\n", + "# Retreive the destination table\n", + "destination_table = client.get_table(table_ref)\n", + "print('Loaded {} rows.'.format(destination_table.num_rows))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a parameterized query\n", + "\n", + "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", + "\n", + "To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", + "\n", + "For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
wordword_count
0the614
1I577
2and490
3to486
4a407
5of367
6my314
7is307
8in291
9you271
10that270
11me263
\n", + "
" + ], + "text/plain": [ + " word word_count\n", + "0 the 614\n", + "1 I 577\n", + "2 and 490\n", + "3 to 486\n", + "4 a 407\n", + "5 of 367\n", + "6 my 314\n", + "7 is 307\n", + "8 in 291\n", + "9 you 271\n", + "10 that 270\n", + "11 me 263" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Define the query\n", + "sql = \"\"\"\n", + " SELECT word, word_count\n", + " FROM `bigquery-public-data.samples.shakespeare`\n", + " WHERE corpus = @corpus\n", + " AND word_count >= @min_word_count\n", + " ORDER BY word_count DESC;\n", + "\"\"\"\n", + "\n", + "# Define the parameter values in a query job configuration\n", + "job_config = bigquery.QueryJobConfig(\n", + " query_parameters=[\n", + " bigquery.ScalarQueryParameter(\"corpus\", \"STRING\", \"romeoandjuliet\"),\n", + " bigquery.ScalarQueryParameter(\"min_word_count\", \"INT64\", 250),\n", + " ]\n", + ")\n", + "\n", + "# Start the query job\n", + "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", + "\n", + "# Return the results as a Pandas DataFrame\n", + "query_job.to_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning Up\n", + "\n", + "The following code deletes the dataset created for this tutorial, including all tables in the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleted dataset: /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503\n" + ] + } + ], + "source": [ + "# Retrieve the dataset from the API\n", + "dataset = client.get_dataset(client.dataset(dataset_id))\n", + "\n", + "# Delete the dataset and its contents\n", + "client.delete_dataset(dataset, delete_contents=True)\n", + "\n", + "print('Deleted dataset: {}'.format(dataset.path))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb b/notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb new file mode 100644 index 00000000000..16d78b6438a --- /dev/null +++ b/notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb @@ -0,0 +1,818 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext google.cloud.bigquery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery Query Magic\n", + "\n", + "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a query on a public dataset\n", + "\n", + "The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", + "\n", + "The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", + "
" + ], + "text/plain": [ + " name count\n", + "0 James 5001762\n", + "1 John 4875934\n", + "2 Robert 4743843\n", + "3 Michael 4354622\n", + "4 William 3886371\n", + "5 Mary 3748377\n", + "6 David 3595923\n", + "7 Richard 2542659\n", + "8 Joseph 2518578\n", + "9 Charles 2273860" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Display verbose output\n", + "\n", + "As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Executing query with job ID: 791c0804-adf8-432a-8618-dab212848f03\n", + "\r", + "Query executing: 0.48s" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "Query complete after 0.93s\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", + "
" + ], + "text/plain": [ + " name count\n", + "0 James 5001762\n", + "1 John 4875934\n", + "2 Robert 4743843\n", + "3 Michael 4354622\n", + "4 William 3886371\n", + "5 Mary 3748377\n", + "6 David 3595923\n", + "7 Richard 2542659\n", + "8 Joseph 2518578\n", + "9 Charles 2273860" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery --verbose\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Explicitly specify a project\n", + "\n", + "By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "project_id = 'my-project-id'" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "project_id = 'ajhamilton-scratch'" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", + "
" + ], + "text/plain": [ + " name count\n", + "0 James 5001762\n", + "1 John 4875934\n", + "2 Robert 4743843\n", + "3 Michael 4354622\n", + "4 William 3886371\n", + "5 Mary 3748377\n", + "6 David 3595923\n", + "7 Richard 2542659\n", + "8 Joseph 2518578\n", + "9 Charles 2273860" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery --project $project_id\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assign the query results to a variable\n", + "\n", + "If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", + "
" + ], + "text/plain": [ + " name count\n", + "0 James 5001762\n", + "1 John 4875934\n", + "2 Robert 4743843\n", + "3 Michael 4354622\n", + "4 William 3886371\n", + "5 Mary 3748377\n", + "6 David 3595923\n", + "7 Richard 2542659\n", + "8 Joseph 2518578\n", + "9 Charles 2273860" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery df\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", + "
" + ], + "text/plain": [ + " name count\n", + "0 James 5001762\n", + "1 John 4875934\n", + "2 Robert 4743843\n", + "3 Michael 4354622\n", + "4 William 3886371\n", + "5 Mary 3748377\n", + "6 David 3595923\n", + "7 Richard 2542659\n", + "8 Joseph 2518578\n", + "9 Charles 2273860" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a parameterized query\n", + "\n", + "Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "params = {\"limit\": 10}" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", + "
" + ], + "text/plain": [ + " name count\n", + "0 James 5001762\n", + "1 John 4875934\n", + "2 Robert 4743843\n", + "3 Michael 4354622\n", + "4 William 3886371\n", + "5 Mary 3748377\n", + "6 David 3595923\n", + "7 Richard 2542659\n", + "8 Joseph 2518578\n", + "9 Charles 2273860" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery --params $params\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT @limit" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb b/notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb new file mode 100644 index 00000000000..64c5a311e93 --- /dev/null +++ b/notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb @@ -0,0 +1,809 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext google.cloud.bigquery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery command-line tool\n", + "\n", + "The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## View available commands\n", + "\n", + "To view the available commands for the BigQuery command-line tool, use the `--help` flag." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python script for interacting with BigQuery.\r\n", + "\r\n", + "\r\n", + "USAGE: bq [--global_flags] [--command_flags] [args]\r\n", + "\r\n", + "\r\n", + "Any of the following commands:\r\n", + " cancel, cp, extract, head, help, init, insert, load, ls, mk, mkdef, partition,\r\n", + " query, rm, shell, show, update, version, wait\r\n", + "\r\n", + "\r\n", + "cancel Request a cancel and waits for the job to be cancelled.\r\n", + "\r\n", + " Requests a cancel and then either: a) waits until the job is done if\r\n", + " the sync flag is set [default], or b) returns immediately if the sync\r\n", + " flag is not set. Not all job types support a cancel, an error is\r\n", + " returned if it cannot be cancelled. Even for jobs that support a\r\n", + " cancel, success is not guaranteed, the job may have completed by the\r\n", + " time the cancel request is noticed, or the job may be in a stage\r\n", + " where it cannot be cancelled.\r\n", + "\r\n", + " Examples:\r\n", + " bq cancel job_id # Requests a cancel and waits until the job is done.\r\n", + " bq --nosync cancel job_id # Requests a cancel and returns\r\n", + " immediately.\r\n", + "\r\n", + " Arguments:\r\n", + " job_id: Job ID to cancel.\r\n", + "\r\n", + "cp Copies one table to another.\r\n", + "\r\n", + " Examples:\r\n", + " bq cp dataset.old_table dataset2.new_table\r\n", + " bq cp --destination_kms_key=kms_key dataset.old_table\r\n", + " dataset2.new_table\r\n", + "\r\n", + "extract Perform an extract operation of source_table into destination_uris.\r\n", + "\r\n", + " Usage:\r\n", + " extract \r\n", + "\r\n", + " Examples:\r\n", + " bq extract ds.summary gs://mybucket/summary.csv\r\n", + "\r\n", + " Arguments:\r\n", + " source_table: Source table to extract.\r\n", + " destination_uris: One or more Google Cloud Storage URIs, separated by\r\n", + " commas.\r\n", + "\r\n", + "head Displays rows in a table.\r\n", + "\r\n", + " Examples:\r\n", + " bq head dataset.table\r\n", + " bq head -j job\r\n", + " bq head -n 10 dataset.table\r\n", + " bq head -s 5 -n 10 dataset.table\r\n", + "\r\n", + "help Help for all or selected command:\r\n", + " bq help []\r\n", + "\r\n", + " To retrieve help with global flags:\r\n", + " bq --help\r\n", + "\r\n", + " To retrieve help with flags only from the main module:\r\n", + " bq --helpshort []\r\n", + "\r\n", + "init Authenticate and create a default .bigqueryrc file.\r\n", + "\r\n", + "insert Inserts rows in a table.\r\n", + "\r\n", + " Inserts the records formatted as newline delimited JSON from file\r\n", + " into the specified table. If file is not specified, reads from stdin.\r\n", + " If there were any insert errors it prints the errors to stdout.\r\n", + "\r\n", + " Examples:\r\n", + " bq insert dataset.table /tmp/mydata.json\r\n", + " echo '{\"a\":1, \"b\":2}' | bq insert dataset.table\r\n", + "\r\n", + " Template table examples: Insert to dataset.template_suffix table\r\n", + " using dataset.template table as its template.\r\n", + " bq insert -x=_suffix dataset.table /tmp/mydata.json\r\n", + "\r\n", + "load Perform a load operation of source into destination_table.\r\n", + "\r\n", + " Usage:\r\n", + " load []\r\n", + "\r\n", + " The is the fully-qualified table name of table to\r\n", + " create, or append to if the table already exists.\r\n", + "\r\n", + " The argument can be a path to a single local file, or a\r\n", + " comma-separated list of URIs.\r\n", + "\r\n", + " The argument should be either the name of a JSON file or a\r\n", + " text schema. This schema should be omitted if the table already has\r\n", + " one.\r\n", + "\r\n", + " In the case that the schema is provided in text form, it should be a\r\n", + " comma-separated list of entries of the form name[:type], where type\r\n", + " will default to string if not specified.\r\n", + "\r\n", + " In the case that is a filename, it should contain a single\r\n", + " array object, each entry of which should be an object with properties\r\n", + " 'name', 'type', and (optionally) 'mode'. See the online documentation\r\n", + " for more detail:\r\n", + " https://developers.google.com/bigquery/preparing-data-for-bigquery\r\n", + "\r\n", + " Note: the case of a single-entry schema with no type specified is\r\n", + " ambiguous; one can use name:string to force interpretation as a\r\n", + " text schema.\r\n", + "\r\n", + " Examples:\r\n", + " bq load ds.new_tbl ./info.csv ./info_schema.json\r\n", + " bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json\r\n", + " bq load ds.small gs://mybucket/small.csv name:integer,value:string\r\n", + " bq load ds.small gs://mybucket/small.csv field1,field2,field3\r\n", + "\r\n", + " Arguments:\r\n", + " destination_table: Destination table name.\r\n", + " source: Name of local file to import, or a comma-separated list of\r\n", + " URI paths to data to import.\r\n", + " schema: Either a text schema or JSON file, as above.\r\n", + "\r\n", + "ls List the objects contained in the named collection.\r\n", + "\r\n", + " List the objects in the named project or dataset. A trailing : or .\r\n", + " can be used to signify a project or dataset.\r\n", + " * With -j, show the jobs in the named project.\r\n", + " * With -p, show all projects.\r\n", + "\r\n", + " Examples:\r\n", + " bq ls\r\n", + " bq ls -j proj\r\n", + " bq ls -p -n 1000\r\n", + " bq ls mydataset\r\n", + " bq ls -a\r\n", + " bq ls --filter labels.color:red\r\n", + " bq ls --filter 'labels.color:red labels.size:*'\r\n", + " bq ls --transfer_config --transfer_location='us'\r\n", + " --filter='dataSourceIds:play,adwords'\r\n", + " bq ls --transfer_run --filter='states:SUCCESSED,PENDING'\r\n", + " --run_attempt='LATEST' projects/p/locations/l/transferConfigs/c\r\n", + " bq ls --transfer_log --message_type='messageTypes:INFO,ERROR'\r\n", + " projects/p/locations/l/transferConfigs/c/runs/r\r\n", + "\r\n", + "mk Create a dataset, table, view, or transfer configuration with this\r\n", + " name.\r\n", + "\r\n", + " See 'bq help load' for more information on specifying the schema.\r\n", + "\r\n", + " Examples:\r\n", + " bq mk new_dataset\r\n", + " bq mk new_dataset.new_table\r\n", + " bq --dataset_id=new_dataset mk table\r\n", + " bq mk -t new_dataset.newtable name:integer,value:string\r\n", + " bq mk --view='select 1 as num' new_dataset.newview\r\n", + " (--view_udf_resource=path/to/file.js)\r\n", + " bq mk -d --data_location=EU new_dataset\r\n", + " bq mk --transfer_config --target_dataset=dataset --display_name=name\r\n", + " -p='{\"param\":\"value\"}' --data_source=source\r\n", + " bq mk --transfer_run --start_time={start_time} --end_time={end_time}\r\n", + " projects/p/locations/l/transferConfigs/c\r\n", + "\r\n", + "mkdef Emits a definition in JSON for a GCS backed table.\r\n", + "\r\n", + " The output of this command can be redirected to a file and used for\r\n", + " the external_table_definition flag with the \"bq query\" and \"bq mk\"\r\n", + " commands. It produces a definition with the most commonly used values\r\n", + " for options. You can modify the output to override option values.\r\n", + "\r\n", + " Usage:\r\n", + " mkdef []\r\n", + "\r\n", + " Examples:\r\n", + " bq mkdef 'gs://bucket/file.csv' field1:integer,field2:string\r\n", + "\r\n", + " Arguments:\r\n", + " source_uris: a comma-separated list of uris.\r\n", + " schema: The argument should be either the name of a JSON\r\n", + " file or\r\n", + " a text schema.\r\n", + "\r\n", + " In the case that the schema is provided in text form, it should be a\r\n", + " comma-separated list of entries of the form name[:type], where type\r\n", + " will\r\n", + " default to string if not specified.\r\n", + "\r\n", + " In the case that is a filename, it should contain a\r\n", + " single array object, each entry of which should be an object with\r\n", + " properties 'name', 'type', and (optionally) 'mode'. See the online\r\n", + " documentation for more detail:\r\n", + " https://developers.google.com/bigquery/preparing-data-for-bigquery\r\n", + "\r\n", + " Note: the case of a single-entry schema with no type specified is\r\n", + " ambiguous; one can use name:string to force interpretation as a\r\n", + " text schema.\r\n", + "\r\n", + "partition Copies source tables into partitioned tables.\r\n", + "\r\n", + " Usage: bq partition \r\n", + " \r\n", + "\r\n", + " Copies tables of the format to a\r\n", + " destination partitioned table, with the date suffix of the source\r\n", + " tables becoming the partition date of the destination table\r\n", + " partitions.\r\n", + "\r\n", + " If the destination table does not exist, one will be created with a\r\n", + " schema and that matches the last table that matches the supplied\r\n", + " prefix.\r\n", + "\r\n", + " Examples:\r\n", + " bq partition dataset1.sharded_ dataset2.partitioned_table\r\n", + "\r\n", + "query Execute a query.\r\n", + "\r\n", + " Query should be specifed on command line, or passed on stdin.\r\n", + "\r\n", + " Examples:\r\n", + " bq query 'select count(*) from publicdata:samples.shakespeare'\r\n", + " echo 'select count(*) from publicdata:samples.shakespeare' | bq query\r\n", + "\r\n", + " Usage:\r\n", + " query []\r\n", + "\r\n", + "rm Delete the dataset, table, or transfer config described by\r\n", + " identifier.\r\n", + "\r\n", + " Always requires an identifier, unlike the show and ls commands. By\r\n", + " default, also requires confirmation before deleting. Supports the -d\r\n", + " -t flags to signify that the identifier is a dataset or table.\r\n", + " * With -f, don't ask for confirmation before deleting.\r\n", + " * With -r, remove all tables in the named dataset.\r\n", + "\r\n", + " Examples:\r\n", + " bq rm ds.table\r\n", + " bq rm -r -f old_dataset\r\n", + " bq rm --transfer_config=projects/p/locations/l/transferConfigs/c\r\n", + "\r\n", + "shell Start an interactive bq session.\r\n", + "\r\n", + "show Show all information about an object.\r\n", + "\r\n", + " Examples:\r\n", + " bq show -j \r\n", + " bq show dataset\r\n", + " bq show [--schema] dataset.table\r\n", + " bq show [--view] dataset.view\r\n", + " bq show --transfer_config projects/p/locations/l/transferConfigs/c\r\n", + " bq show --transfer_run\r\n", + " projects/p/locations/l/transferConfigs/c/runs/r\r\n", + " bq show --encryption_service_account\r\n", + "\r\n", + "update Updates a dataset, table, view or transfer configuration with this\r\n", + " name.\r\n", + "\r\n", + " See 'bq help load' for more information on specifying the schema.\r\n", + "\r\n", + " Examples:\r\n", + " bq update --description \"Dataset description\" existing_dataset\r\n", + " bq update --description \"My table\" existing_dataset.existing_table\r\n", + " bq update -t existing_dataset.existing_table\r\n", + " name:integer,value:string\r\n", + " bq update --destination_kms_key\r\n", + " projects/p/locations/l/keyRings/r/cryptoKeys/k\r\n", + " existing_dataset.existing_table\r\n", + " bq update --view='select 1 as num' existing_dataset.existing_view\r\n", + " (--view_udf_resource=path/to/file.js)\r\n", + " bq update --transfer_config --display_name=name\r\n", + " -p='{\"param\":\"value\"}'\r\n", + " projects/p/locations/l/transferConfigs/c\r\n", + " bq update --transfer_config --target_dataset=dataset\r\n", + " --refresh_window_days=5 --update_credentials\r\n", + " projects/p/locations/l/transferConfigs/c\r\n", + "\r\n", + "version Return the version of bq.\r\n", + "\r\n", + "wait Wait some number of seconds for a job to finish.\r\n", + "\r\n", + " Poll job_id until either (1) the job is DONE or (2) the specified\r\n", + " number of seconds have elapsed. Waits forever if unspecified. If no\r\n", + " job_id is specified, and there is only one running job, we poll that\r\n", + " job.\r\n", + "\r\n", + " Examples:\r\n", + " bq wait # Waits forever for the currently running job.\r\n", + " bq wait job_id # Waits forever\r\n", + " bq wait job_id 100 # Waits 100 seconds\r\n", + " bq wait job_id 0 # Polls if a job is done, then returns immediately.\r\n", + " # These may exit with a non-zero status code to indicate \"failure\":\r\n", + " bq wait --fail_on_error job_id # Succeeds if job succeeds.\r\n", + " bq wait --fail_on_error job_id 100 # Succeeds if job succeeds in 100\r\n", + " sec.\r\n", + "\r\n", + " Arguments:\r\n", + " job_id: Job ID to wait on.\r\n", + " secs: Number of seconds to wait (must be >= 0).\r\n", + "\r\n", + "\r\n", + "Run 'bq --help' to get help for global flags.\r\n", + "Run 'bq help ' to get help for .\r\n" + ] + } + ], + "source": [ + "!bq help" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a new dataset\n", + "\n", + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", + "\n", + "The example below creates a new dataset in the US named \"your_new_dataset\"." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dataset 'ajhamilton-scratch:your_dataset_id' successfully created.\r\n" + ] + } + ], + "source": [ + "!bq --location=US mk --dataset \"your_dataset_id\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a local file to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python script for interacting with BigQuery.\r\n", + "\r\n", + "\r\n", + "USAGE: bq [--global_flags] [--command_flags] [args]\r\n", + "\r\n", + "\r\n", + "load Perform a load operation of source into destination_table.\r\n", + "\r\n", + " Usage:\r\n", + " load []\r\n", + "\r\n", + " The is the fully-qualified table name of table to\r\n", + " create, or append to if the table already exists.\r\n", + "\r\n", + " The argument can be a path to a single local file, or a\r\n", + " comma-separated list of URIs.\r\n", + "\r\n", + " The argument should be either the name of a JSON file or a\r\n", + " text schema. This schema should be omitted if the table already has\r\n", + " one.\r\n", + "\r\n", + " In the case that the schema is provided in text form, it should be a\r\n", + " comma-separated list of entries of the form name[:type], where type\r\n", + " will default to string if not specified.\r\n", + "\r\n", + " In the case that is a filename, it should contain a single\r\n", + " array object, each entry of which should be an object with properties\r\n", + " 'name', 'type', and (optionally) 'mode'. See the online documentation\r\n", + " for more detail:\r\n", + " https://developers.google.com/bigquery/preparing-data-for-bigquery\r\n", + "\r\n", + " Note: the case of a single-entry schema with no type specified is\r\n", + " ambiguous; one can use name:string to force interpretation as a\r\n", + " text schema.\r\n", + "\r\n", + " Examples:\r\n", + " bq load ds.new_tbl ./info.csv ./info_schema.json\r\n", + " bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json\r\n", + " bq load ds.small gs://mybucket/small.csv name:integer,value:string\r\n", + " bq load ds.small gs://mybucket/small.csv field1,field2,field3\r\n", + "\r\n", + " Arguments:\r\n", + " destination_table: Destination table name.\r\n", + " source: Name of local file to import, or a comma-separated list of\r\n", + " URI paths to data to import.\r\n", + " schema: Either a text schema or JSON file, as above.\r\n", + "\r\n", + " Flags for load:\r\n", + "\r\n", + "/Users/ajhamilton/google-cloud-sdk/platform/bq/bq.py:\r\n", + " --[no]allow_jagged_rows: Whether to allow missing trailing optional columns in\r\n", + " CSV import data.\r\n", + " --[no]allow_quoted_newlines: Whether to allow quoted newlines in CSV import\r\n", + " data.\r\n", + " --[no]autodetect: Enable auto detection of schema and options for formats that\r\n", + " are not self describing like CSV and JSON.\r\n", + " --clustering_fields: Comma separated field names. Can only be specified with\r\n", + " time based partitioning. Data will be first partitioned and subsequently\r\n", + " \"clustered on these fields.\r\n", + " --destination_kms_key: Cloud KMS key for encryption of the destination table\r\n", + " data.\r\n", + " -E,--encoding: : The character encoding used by the input\r\n", + " file. Options include:\r\n", + " ISO-8859-1 (also known as Latin-1)\r\n", + " UTF-8\r\n", + " -F,--field_delimiter: The character that indicates the boundary between\r\n", + " columns in the input file. \"\\t\" and \"tab\" are accepted names for tab.\r\n", + " --[no]ignore_unknown_values: Whether to allow and ignore extra, unrecognized\r\n", + " values in CSV or JSON import data.\r\n", + " --max_bad_records: Maximum number of bad records allowed before the entire job\r\n", + " fails.\r\n", + " (default: '0')\r\n", + " (an integer)\r\n", + " --null_marker: An optional custom string that will represent a NULL valuein\r\n", + " CSV import data.\r\n", + " --projection_fields: If sourceFormat is set to \"DATASTORE_BACKUP\", indicates\r\n", + " which entity properties to load into BigQuery from a Cloud Datastore backup.\r\n", + " Property names are case sensitive and must refer to top-level properties.\r\n", + " (default: '')\r\n", + " (a comma separated list)\r\n", + " --quote: Quote character to use to enclose records. Default is \". To indicate\r\n", + " no quote character at all, use an empty string.\r\n", + " --[no]replace: If true erase existing contents before loading new data.\r\n", + " (default: 'false')\r\n", + " --[no]require_partition_filter: Whether to require partition filter for\r\n", + " queries over this table. Only apply to partitioned table.\r\n", + " --schema: Either a filename or a comma-separated list of fields in the form\r\n", + " name[:type].\r\n", + " --schema_update_option: Can be specified when append to a table, or replace a\r\n", + " table partition. When specified, the schema of the destination table will be\r\n", + " updated with the schema of the new data. One or more of the following\r\n", + " options can be specified:\r\n", + " ALLOW_FIELD_ADDITION: allow new fields to be added\r\n", + " ALLOW_FIELD_RELAXATION: allow relaxing required fields to nullable;\r\n", + " repeat this option to specify a list of values\r\n", + " --skip_leading_rows: The number of rows at the beginning of the source file to\r\n", + " skip.\r\n", + " (an integer)\r\n", + " --source_format:\r\n", + " : Format of\r\n", + " source data. Options include:\r\n", + " CSV\r\n", + " NEWLINE_DELIMITED_JSON\r\n", + " DATASTORE_BACKUP\r\n", + " AVRO\r\n", + " PARQUET\r\n", + " ORC (experimental)\r\n", + " --time_partitioning_expiration: Enables time based partitioning on the table\r\n", + " and sets the number of seconds for which to keep the storage for the\r\n", + " partitions in the table. The storage in a partition will have an expiration\r\n", + " time of its partition time plus this value. A negative number means no\r\n", + " expiration.\r\n", + " (an integer)\r\n", + " --time_partitioning_field: Enables time based partitioning on the table and\r\n", + " the table will be partitioned based on the value of this field. If time\r\n", + " based partitioning is enabled without this value, the table will be\r\n", + " partitioned based on the loading time.\r\n", + " --time_partitioning_type: Enables time based partitioning on the table and set\r\n", + " the type. The only type accepted is DAY, which will generate one partition\r\n", + " per day.\r\n", + "\r\n", + "gflags:\r\n", + " --flagfile: Insert flag definitions from the given file into the command line.\r\n", + " (default: '')\r\n", + " --undefok: comma-separated list of flag names that it is okay to specify on\r\n", + " the command line even if the program does not define a flag with that name.\r\n", + " IMPORTANT: flags in this list that have arguments MUST use the --flag=value\r\n", + " format.\r\n", + " (default: '')\r\n", + "\r\n", + "\r\n", + "Global flags:\r\n", + "\r\n", + "bq_auth_flags:\r\n", + " --application_default_credential_file: Only for the gcloud wrapper use.\r\n", + " (default: '')\r\n", + " --credential_file: Only for the gcloud wrapper use.\r\n", + " (default: '/Users/ajhamilton/.bigquery.v2.token')\r\n", + " --service_account: Only for the gcloud wrapper use.\r\n", + " (default: '')\r\n", + " --service_account_credential_file: Only for the gcloud wrapper use.\r\n", + " --service_account_private_key_file: Only for the gcloud wrapper use.\r\n", + " (default: '')\r\n", + " --service_account_private_key_password: Only for the gcloud wrapper use.\r\n", + " (default: 'notasecret')\r\n", + " --[no]use_gce_service_account: Only for the gcloud wrapper use.\r\n", + " (default: 'false')\r\n", + "\r\n", + "bq_flags:\r\n", + " --api: API endpoint to talk to.\r\n", + " (default: 'https://www.googleapis.com')\r\n", + " --api_version: API version to use.\r\n", + " (default: 'v2')\r\n", + " --apilog: Log all API requests and responses to the file specified by this\r\n", + " flag. Also accepts \"stdout\" and \"stderr\". Specifying the empty string will\r\n", + " direct to stdout.\r\n", + " --bigqueryrc: Path to configuration file. The configuration file specifies new\r\n", + " defaults for any flags, and can be overrridden by specifying the flag on the\r\n", + " command line. If the --bigqueryrc flag is not specified, the BIGQUERYRC\r\n", + " environment variable is used. If that is not specified, the path\r\n", + " \"~/.bigqueryrc\" is used.\r\n", + " (default: '/Users/ajhamilton/.bigqueryrc')\r\n", + " --ca_certificates_file: Location of CA certificates file.\r\n", + " (default: '')\r\n", + " --dataset_id: Default dataset reference to use for requests (Ignored when not\r\n", + " applicable.). Can be set as \"project:dataset\" or \"dataset\". If project is\r\n", + " missing, the value of the project_id flag will be used.\r\n", + " (default: '')\r\n", + " --[no]debug_mode: Show tracebacks on Python exceptions.\r\n", + " (default: 'false')\r\n", + " --[no]disable_ssl_validation: Disables HTTPS certificates validation. This is\r\n", + " off by default.\r\n", + " (default: 'false')\r\n", + " --discovery_file: Filename for JSON document to read for discovery.\r\n", + " (default: '')\r\n", + " --[no]enable_gdrive: When set to true, requests new OAuth token with GDrive\r\n", + " scope. When set to false, requests new OAuth token without GDrive scope.\r\n", + " --[no]fingerprint_job_id: Whether to use a job id that is derived from a\r\n", + " fingerprint of the job configuration. This will prevent the same job from\r\n", + " running multiple times accidentally.\r\n", + " (default: 'false')\r\n", + " --format: : Format for command output.\r\n", + " Options include:\r\n", + " pretty: formatted table output\r\n", + " sparse: simpler table output\r\n", + " prettyjson: easy-to-read JSON format\r\n", + " json: maximally compact JSON\r\n", + " csv: csv format with header\r\n", + " The first three are intended to be human-readable, and the latter three are\r\n", + " for passing to another program. If no format is selected, one will be chosen\r\n", + " based on the command run.\r\n", + " --[no]headless: Whether this bq session is running without user interaction.\r\n", + " This affects behavior that expects user interaction, like whether debug_mode\r\n", + " will break into the debugger and lowers the frequency of informational\r\n", + " printing.\r\n", + " (default: 'false')\r\n", + " --httplib2_debuglevel: Instruct httplib2 to print debugging messages by\r\n", + " setting debuglevel to the given value.\r\n", + " --job_id: A unique job_id to use for the request. If not specified, this\r\n", + " client will generate a job_id. Applies only to commands that launch jobs,\r\n", + " such as cp, extract, load, and query.\r\n", + " --job_property: Additional key-value pairs to include in the properties field\r\n", + " of the job configuration;\r\n", + " repeat this option to specify a list of values\r\n", + " --location: Default geographic location to use when creating datasets or\r\n", + " determining where jobs should run (Ignored when not applicable.)\r\n", + " --max_rows_per_request: Specifies the max number of rows to return per read.\r\n", + " (an integer)\r\n", + " --project_id: Default project to use for requests.\r\n", + " (default: '')\r\n", + " --proxy_address: The name or IP address of the proxy host to use for\r\n", + " connecting to GCP.\r\n", + " (default: '')\r\n", + " --proxy_password: The password to use when authenticating with proxy host.\r\n", + " (default: '')\r\n", + " --proxy_port: The port number to use to connect to the proxy host.\r\n", + " (default: '')\r\n", + " --proxy_username: The user name to use when authenticating with proxy host.\r\n", + " (default: '')\r\n", + " -q,--[no]quiet: If True, ignore status updates while jobs are running.\r\n", + " (default: 'false')\r\n", + " -sync,--[no]synchronous_mode: If True, wait for command completion before\r\n", + " returning, and use the job completion status for error codes. If False,\r\n", + " simply create the job, and use the success of job creation as the error\r\n", + " code.\r\n", + " (default: 'true')\r\n", + " --trace: A tracing token of the form \"token:\" to include in api\r\n", + " requests.\r\n", + "\r\n", + "google.apputils.app:\r\n", + " -?,--[no]help: show this help\r\n", + " --[no]helpshort: show usage only for this module\r\n", + " --[no]helpxml: like --help, but generates XML output\r\n", + " --[no]run_with_pdb: Set to true for PDB debug mode\r\n", + " (default: 'false')\r\n", + " --[no]run_with_profiling: Set to true for profiling the script. Execution will\r\n", + " be slower, and the output format might change over time.\r\n", + " (default: 'false')\r\n", + " --[no]show_build_data: show build data and exit\r\n", + " --[no]use_cprofile_for_profiling: Use cProfile instead of the profile module\r\n", + " for profiling. This has no effect unless --run_with_profiling is set.\r\n", + " (default: 'true')\r\n", + "\r\n", + "gflags:\r\n", + " --flagfile: Insert flag definitions from the given file into the command line.\r\n", + " (default: '')\r\n", + " --undefok: comma-separated list of flag names that it is okay to specify on\r\n", + " the command line even if the program does not define a flag with that name.\r\n", + " IMPORTANT: flags in this list that have arguments MUST use the --flag=value\r\n", + " format.\r\n", + " (default: '')\r\n", + "\r\n", + "Run 'bq help' to see the list of available commands.\r\n" + ] + } + ], + "source": [ + "!bq load --help" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + "Upload complete.\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (0s) Current status: RUNNING" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + " \r", + "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (1s) Current status: RUNNING" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + " \r", + "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (2s) Current status: RUNNING" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + " \r", + "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (2s) Current status: DONE \r\n" + ] + } + ], + "source": [ + "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from Google Cloud Storage to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + "Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (0s) Current status: RUNNING" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + " \r", + "Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (1s) Current status: RUNNING" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + " \r", + "Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (1s) Current status: DONE \r\n" + ] + } + ], + "source": [ + "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a query\n", + "\n", + "The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning Up\n", + "\n", + "The following code deletes the dataset created for this tutorial, including all tables in the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "!bq rm -r -f --dataset your_dataset_id" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/test/executed_notebooks/Storage Client Library_output.ipynb b/notebooks/test/executed_notebooks/Storage Client Library_output.ipynb new file mode 100644 index 00000000000..16baab9ff01 --- /dev/null +++ b/notebooks/test/executed_notebooks/Storage Client Library_output.ipynb @@ -0,0 +1,391 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext google.cloud.bigquery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Google Cloud Storage\n", + "\n", + "This page shows how to get started with the Google Cloud Storage Python client library." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Import the library" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import storage" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Projects\n", + "\n", + "All data in Cloud Storage belongs inside a project. A project consists of a\n", + "set of users, a set of APIs, and billing, authentication, and monitoring\n", + "settings for those APIs. You can have one project or multiple projects." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Clients\n", + "Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "client = storage.Client(project=\"ajhamilton-scratch\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Buckets\n", + "\n", + "Buckets are the basic containers that hold your data. Everything that you\n", + "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", + "organize your data and control access to your data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create a bucket\n", + "\n", + "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", + "you specify a globally-unique name." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bucket test-storage-bucket-1548268970715 created.\n" + ] + } + ], + "source": [ + "# Replace the string below with a unique name for the new bucket\n", + "bucket_name = 'test-storage-bucket-1548268970715'\n", + "\n", + "# Creates the new bucket\n", + "bucket = client.create_bucket(bucket_name)\n", + "\n", + "print('Bucket {} created.'.format(bucket.name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List buckets in a project" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Buckets in ajhamilton-scratch:\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\tajhamilton-scratch\n", + "\tmy-new-bucket-1548180688764\n", + "\tmy-new-bucket-1548208228513\n", + "\ttest-storage-bucket-1548209987490\n", + "\ttest-storage-bucket-1548268970715\n" + ] + } + ], + "source": [ + "buckets = client.list_buckets()\n", + "\n", + "print(\"Buckets in {}:\".format(client.project))\n", + "for item in buckets:\n", + " print(\"\\t\" + item.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "bucket = client.get_bucket(bucket_name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objects\n", + "\n", + "Objects are the individual pieces of data that you store in Cloud Storage.\n", + "There is no limit on the number of objects that you can create in a bucket." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload a local file to a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File uploaded to test-storage-bucket-1548268970715.\n" + ] + } + ], + "source": [ + "blob_name = 'us-states.txt'\n", + "blob = bucket.blob(blob_name)\n", + "\n", + "source_file_name = 'resources/us-states.txt'\n", + "blob.upload_from_filename(source_file_name)\n", + "\n", + "print('File uploaded to {}.'.format(bucket.name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List blobs in a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Blobs in test-storage-bucket-1548268970715:\n", + "\tus-states.txt\n" + ] + } + ], + "source": [ + "blobs = bucket.list_blobs()\n", + "\n", + "print(\"Blobs in {}:\".format(bucket.name))\n", + "for item in blobs:\n", + " print(\"\\t\" + item.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a blob and display metadata\n", + "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Select metadata for blob us-states.txt:\n", + "\tID: test-storage-bucket-1548268970715/us-states.txt/1548268974850839\n", + "\tSize: 637 bytes\n", + "\tUpdated: 2019-01-23 18:42:54.850000+00:00\n" + ] + } + ], + "source": [ + "blob = bucket.get_blob(blob_name)\n", + "\n", + "print('Select metadata for blob {}:'.format(blob_name))\n", + "print('\\tID: {}'.format(blob.id))\n", + "print('\\tSize: {} bytes'.format(blob.size))\n", + "print('\\tUpdated: {}'.format(blob.updated))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download a blob to a local directory" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Downloaded blob us-states.txt to resources/downloaded-us-states.txt.\n" + ] + } + ], + "source": [ + "output_file_name = 'resources/downloaded-us-states.txt'\n", + "blob.download_to_filename(output_file_name)\n", + "\n", + "print('Downloaded blob {} to {}.'.format(blob.name, output_file_name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning up" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a blob" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Blob us-states.txt deleted.\n" + ] + } + ], + "source": [ + "blob = client.get_bucket(bucket_name).get_blob(blob_name)\n", + "blob.delete()\n", + "\n", + "print('Blob {} deleted.'.format(blob.name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Bucket test-storage-bucket-1548268970715 deleted.\n" + ] + } + ], + "source": [ + "bucket = client.get_bucket(bucket_name)\n", + "bucket.delete()\n", + "\n", + "print('Bucket {} deleted.'.format(bucket.name))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/notebooks/test/executed_notebooks/Storage Commands_output.ipynb b/notebooks/test/executed_notebooks/Storage Commands_output.ipynb new file mode 100644 index 00000000000..0ace4246bc6 --- /dev/null +++ b/notebooks/test/executed_notebooks/Storage Commands_output.ipynb @@ -0,0 +1,468 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext google.cloud.bigquery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Storage Commands\n", + "\n", + "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage.\n", + "\n", + "This notebook introduces several `gsutil` commands for interacting with Cloud Storage." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## List available commands\n", + "\n", + "The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Usage: gsutil [-D] [-DD] [-h header]... [-m] [-o] [-q] [command [opts...] args...]\r\n", + "Available commands:\r\n", + " acl Get, set, or change bucket and/or object ACLs\r\n", + " cat Concatenate object content to stdout\r\n", + " compose Concatenate a sequence of objects into a new composite object.\r\n", + " config Obtain credentials and create configuration file\r\n", + " cors Get or set a CORS JSON document for one or more buckets\r\n", + " cp Copy files and objects\r\n", + " defacl Get, set, or change default ACL on buckets\r\n", + " defstorageclass Get or set the default storage class on buckets\r\n", + " du Display object size usage\r\n", + " hash Calculate file hashes\r\n", + " help Get help about commands and topics\r\n", + " iam Get, set, or change bucket and/or object IAM permissions.\r\n", + " kms Configure Cloud KMS encryption\r\n", + " label Get, set, or change the label configuration of a bucket.\r\n", + " lifecycle Get or set lifecycle configuration for a bucket\r\n", + " logging Configure or retrieve logging on buckets\r\n", + " ls List providers, buckets, or objects\r\n", + " mb Make buckets\r\n", + " mv Move/rename objects and/or subdirectories\r\n", + " notification Configure object change notification\r\n", + " perfdiag Run performance diagnostic\r\n", + " rb Remove buckets\r\n", + " requesterpays Enable or disable requester pays for one or more buckets\r\n", + " retention Provides utilities to interact with Retention Policy feature.\r\n", + " rewrite Rewrite objects\r\n", + " rm Remove objects\r\n", + " rsync Synchronize content of two buckets/directories\r\n", + " setmeta Set metadata on already uploaded objects\r\n", + " signurl Create a signed url\r\n", + " stat Display object status\r\n", + " test Run gsutil unit/integration tests (for developers)\r\n", + " update Update to the latest gsutil release\r\n", + " version Print version info about gsutil\r\n", + " versioning Enable or suspend versioning for one or more buckets\r\n", + " web Set a main page and/or error page for one or more buckets\r\n", + "\r\n", + "Additional help topics:\r\n", + " acls Working With Access Control Lists\r\n", + " anon Accessing Public Data Without Credentials\r\n", + " apis Cloud Storage APIs\r\n", + " crc32c CRC32C and Installing crcmod\r\n", + " creds Credential Types Supporting Various Use Cases\r\n", + " dev Contributing Code to gsutil\r\n", + " encoding Filename encoding and interoperability problems\r\n", + " encryption Using Encryption Keys\r\n", + " metadata Working With Object Metadata\r\n", + " naming Object and Bucket Naming\r\n", + " options Top-Level Command-Line Options\r\n", + " prod Scripting Production Transfers\r\n", + " projects Working With Projects\r\n", + " retries Retry Handling Strategy\r\n", + " security Security and Privacy Considerations\r\n", + " subdirs How Subdirectories Work\r\n", + " support Google Cloud Storage Support\r\n", + " throttling Throttling gsutil\r\n", + " versions Object Versioning and Concurrency Control\r\n", + " wildcards Wildcard Names\r\n", + "\r\n", + "Use gsutil help for detailed help." + ] + } + ], + "source": [ + "!gsutil help" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Buckets\n", + "\n", + "Buckets are the basic containers that hold your data. Everything that you\n", + "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", + "organize your data and control access to your data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create a bucket\n", + "\n", + "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", + "you specify a globally-unique name." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# Replace the string below with a unique name for the new bucket\n", + "bucket_name = 'test-storage-bucket-1548268945185'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Creating gs://test-storage-bucket-1548268945185/...\r\n" + ] + } + ], + "source": [ + "!gsutil mb gs://{bucket_name}/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List buckets in a project\n", + "\n", + "Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gs://ajhamilton-scratch/\r\n", + "gs://my-new-bucket-1548180688764/\r\n", + "gs://my-new-bucket-1548208228513/\r\n", + "gs://test-storage-bucket-1548209987490/\r\n", + "gs://test-storage-bucket-1548268945185/\r\n" + ] + } + ], + "source": [ + "!gsutil ls -p ajhamilton-scratch" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objects\n", + "\n", + "Objects are the individual pieces of data that you store in Cloud Storage.\n", + "There is no limit on the number of objects that you can create in a bucket." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload a local file to a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Copying file://resources/us-states.txt [Content-Type=text/plain]...\r\n", + "/ [0 files][ 0.0 B/ 637.0 B] \r" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/ [1 files][ 637.0 B/ 637.0 B] \r", + "-\r", + "\r\n", + "Operation completed over 1 objects/637.0 B. \r\n" + ] + } + ], + "source": [ + "!gsutil cp resources/us-states.txt gs://{bucket_name}/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List blobs in a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gs://test-storage-bucket-1548268945185/us-states.txt\r\n" + ] + } + ], + "source": [ + "!gsutil ls -r gs://{bucket_name}/**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a blob and display metadata\n", + "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gs://test-storage-bucket-1548268945185/us-states.txt:\r\n", + " Creation time: Wed, 23 Jan 2019 18:42:37 GMT\r\n", + " Update time: Wed, 23 Jan 2019 18:42:37 GMT\r\n", + " Storage class: STANDARD\r\n", + " Content-Language: en\r\n", + " Content-Length: 637\r\n", + " Content-Type: text/plain\r\n", + " Hash (crc32c): AmYMRQ==\r\n", + " Hash (md5): NmfddAHdCzyvAHCifeGtwg==\r\n", + " ETag: CIKl+anHhOACEAE=\r\n", + " Generation: 1548268957749890\r\n", + " Metageneration: 1\r\n", + " ACL: [\r\n", + " {\r\n", + " \"entity\": \"project-owners-129776587519\",\r\n", + " \"projectTeam\": {\r\n", + " \"projectNumber\": \"129776587519\",\r\n", + " \"team\": \"owners\"\r\n", + " },\r\n", + " \"role\": \"OWNER\"\r\n", + " },\r\n", + " {\r\n", + " \"entity\": \"project-editors-129776587519\",\r\n", + " \"projectTeam\": {\r\n", + " \"projectNumber\": \"129776587519\",\r\n", + " \"team\": \"editors\"\r\n", + " },\r\n", + " \"role\": \"OWNER\"\r\n", + " },\r\n", + " {\r\n", + " \"entity\": \"project-viewers-129776587519\",\r\n", + " \"projectTeam\": {\r\n", + " \"projectNumber\": \"129776587519\",\r\n", + " \"team\": \"viewers\"\r\n", + " },\r\n", + " \"role\": \"READER\"\r\n", + " },\r\n", + " {\r\n", + " \"email\": \"ajhamilton@google.com\",\r\n", + " \"entity\": \"user-ajhamilton@google.com\",\r\n", + " \"role\": \"OWNER\"\r\n", + " }\r\n", + "]\r\n", + "TOTAL: 1 objects, 637 bytes (637 B)\r\n" + ] + } + ], + "source": [ + "!gsutil ls -L gs://{bucket_name}/us-states.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download a blob to a local directory" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Copying gs://test-storage-bucket-1548268945185/us-states.txt...\r\n", + "/ [0 files][ 0.0 B/ 637.0 B] \r" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/ [1 files][ 637.0 B/ 637.0 B] \r", + "\r\n", + "Operation completed over 1 objects/637.0 B. \r\n" + ] + } + ], + "source": [ + "!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning up" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a blob" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing gs://test-storage-bucket-1548268945185/us-states.txt...\r\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/ [1 objects] \r", + "\r\n", + "Operation completed over 1 objects. \r\n" + ] + } + ], + "source": [ + "!gsutil rm gs://{bucket_name}/us-states.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Removing gs://test-storage-bucket-1548268945185/...\r\n" + ] + } + ], + "source": [ + "!gsutil rm -r gs://{bucket_name}/" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb b/notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb new file mode 100644 index 00000000000..7b938e3b6be --- /dev/null +++ b/notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb @@ -0,0 +1,763 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext google.cloud.bigquery" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Vizualizing BigQuery Data in a Jupyter Notebook\n", + "\n", + "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime.\n", + "\n", + "Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and Pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Jupyter Magics to Query BigQuery Data\n", + "\n", + "The BigQuery Python client library provides a magic command that allows you to run queries with minimal code.\n", + "\n", + "The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
\n", + "
" + ], + "text/plain": [ + " year birth_count\n", + "0 2008 4255156\n", + "1 2007 4324008\n", + "2 2006 4273225\n", + "3 2005 4145619\n", + "4 2004 4118907\n", + "5 2003 4096092\n", + "6 2002 4027376\n", + "7 2001 4031531\n", + "8 2000 4063823\n", + "9 1999 3963465\n", + "10 1998 3945192\n", + "11 1997 3884329\n", + "12 1996 3894874\n", + "13 1995 3903012\n", + "14 1994 3956925" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery\n", + "SELECT\n", + " source_year AS year,\n", + " COUNT(is_male) AS birth_count\n", + "FROM `bigquery-public-data.samples.natality`\n", + "GROUP BY year\n", + "ORDER BY year DESC\n", + "LIMIT 15" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
\n", + "
" + ], + "text/plain": [ + " year birth_count\n", + "0 2008 4255156\n", + "1 2007 4324008\n", + "2 2006 4273225\n", + "3 2005 4145619\n", + "4 2004 4118907\n", + "5 2003 4096092\n", + "6 2002 4027376\n", + "7 2001 4031531\n", + "8 2000 4063823\n", + "9 1999 3963465\n", + "10 1998 3945192\n", + "11 1997 3884329\n", + "12 1996 3894874\n", + "13 1995 3903012\n", + "14 1994 3956925" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery total_births\n", + "SELECT\n", + " source_year AS year,\n", + " COUNT(is_male) AS birth_count\n", + "FROM `bigquery-public-data.samples.natality`\n", + "GROUP BY year\n", + "ORDER BY year DESC\n", + "LIMIT 15" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next cell uses the Pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [Pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with Pandas." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "total_births.plot(kind='bar', x='year', y='birth_count');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
wdaymale_birthsfemale_births
0142935754093357
1260958405831111
2367272176412155
3466187296307782
4565830156284434
5665186366223584
6747619504530052
\n", + "
" + ], + "text/plain": [ + " wday male_births female_births\n", + "0 1 4293575 4093357\n", + "1 2 6095840 5831111\n", + "2 3 6727217 6412155\n", + "3 4 6618729 6307782\n", + "4 5 6583015 6284434\n", + "5 6 6518636 6223584\n", + "6 7 4761950 4530052" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%bigquery births_by_weekday\n", + "SELECT\n", + " wday,\n", + " SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births,\n", + " SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births\n", + "FROM `bigquery-public-data.samples.natality`\n", + "WHERE wday IS NOT NULL\n", + "GROUP BY wday\n", + "ORDER BY wday ASC" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualize the query results using a line chart." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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PvpolbGkpCSWL1/uoxk1Hw0mtRjavR2vzax2hefopjj2P7WbolKq0tixYxk7dqyvp+ETepurPiq7KU7z9UyUUsovaDCpK0c3xb4TtJuiUkrZNJjUlaOboma8K6VUJQ0mdbVloXZTVEqpajSY1MWJH2DfOhgyQ7spKhWgXnzxRfr27ctttzVNI7tnnnmmXlV7Z82axbJly2qMp6en88ADD7h8T2ZmJitXrmzwuRuDPs1VF5XdFH/q23kopertpZdeYs2aNZUFE/1damqqy2z5srIyMjMzSU9P57rrfN/+QoOJtxzdFHuN0m6KSjWGTx6DI9sb95gXDITxf3S7+Z577mHfvn2MHz+e6dOns3fv3hr9SBYsWMD7779PYWEhe/bs4eGHH6akpIRFixYRGRnJypUrad++Pa+++iqvvPIKJSUl9OrVi0WLFhEdHV3lfHv37uW+++4jLy+P6OhoXn31VS65xH1R2DVr1vDHP/6R06dP85e//IUJEyawbt06nn/+eT766COeeeYZ9u7dy759++jevTtff/01586d46uvvuLxxx8HYOfOnVx11VUcOHCAhx56iAceeIDCwkKmTp1KTk4O5eXlPPXUU0yb1rhPo+q9Gm85uinqwrtSAeuf//wnXbt2Ze3atRQWFnLNNdewceNG1q5dyyOPPEJhYSEAWVlZvPfee2zatIknnniC6OhoMjIyuPTSS1m4cCFglZHftGkTW7dupW/fvsydO7fG+ebMmcPf/vY3Nm/ezPPPP8+9997rcX779+9n48aNfPzxx9xzzz0uqxXv3LmTNWvW8Pbbb/O73/2OadOmkZmZWRkcdu/ezapVq9i4cSPPPvsspaWlfPrpp3Tt2pWtW7eSlZXVJJWF9crEW9pNUanG5eEKojm460cCcPXVVxMXF0dcXBxt2rThhhtuAGDgwIFs27YNsALOk08+ycmTJykoKKiRrFhQUMA333zDlClTKseKi4s9zmnq1KmEhITQu3dvLrroInbv3l1jnxtvvJFWrVq5Pcb1119PZGQkkZGRdOrUiaNHjzJw4EB+9atf8eijjzJhwgSuuOIKL/4XqhsNJt4oyNNuikoFGUc/kurteDds2FBrvxOwFszff/99Bg8ezIIFC1i3bl2V41RUVNC2bdvKToneaKqeJ3369GHLli2sXLmSJ598klGjRvHb3/7W63l5Q29zeWObdlNUKtjUtR9JdWfOnKFLly6UlpZW9o131rp1a5KSkli6dClgBa/aeo0sXbqUioqKynWR6oGuOm97nvz4449ER0czY8YMHnnkEbZs2VLre+pKg0ltjIEtiyBxuHZTVCqI1LUfSXW///3vGT58OCNHjnS7qP7mm28yd+5cBg8eTP/+/fnggw88HrN79+6kpaUxfvx4/vnPfxIVFeVx/6uvvpqdO3eSnJzM4sWL3e63fft20tLSSE5O5tlnn+XJJ5+s/QPWkfYzqc2BDTBvDNz4dxiqVyZKNYT2M/Fv2s+kqfUcpd0UlVLKA12Ar0334XD7e76ehVIqSDz33HOV6ygOU6ZM4YknnvDRjBqHBhOllGpGTzzxRMAHDle8vs0lIqEikiEiH9k/J4nIBhHJFpHFIhJhj0faP2fb23s4HeNxe/xbERnrND7OHssWkcecxut8DqWUf2sp67SBpqH/XeqyZvIgsMvp5z8BLxhjegEngDvt8TuBE/b4C/Z+iEg/YDrQHxgHvGQHqFDgH8B4oB9wq71vnc+hlPJvUVFR5Ofna0DxM8YY8vPza316zBOvbnOJSAJwPfAc8EuxMmmuARwVD18HngFeBibarwGWAX+3958IvGOMKQa+F5FsIM3eL9sYs88+1zvARBHZVddzGP1/qFJ+LSEhgZycHPLy8nw9FVVNVFRUg4pfertm8t/Ar4E4++d44KQxpsz+OQfoZr/uBhwEMMaUicgpe/9uwHqnYzq/52C18eH1PMcxLz+PUsoHwsPDSUpK8vU0VBOo9TaXiEwAco0xm5thPo1KROaISLqIpOtfQkop1XS8WTMZCdwoIvuBd7BuPf0VaCsijiubBOCQ/foQkAhgb28D5DuPV3uPu/H8epyjCmPMK8aYVGNMaseOHb34qEoppeqj1mBijHncGJNgjOmBtYD+hTHmNmAtMNnebSbgqBOwwv4Ze/sX9lrGCmC6/SRWEtAb2AhsAnrbT25F2OdYYb+nrudQSinlA3UqpyIiVwEPG2MmiMhFWFcq7YEMYIYxplhEooBFwBDgODDdaXH9CeBnQBnwkDHmE3v8Oqx1mVBgnjHmOXu8zufwMPc84AevP2xVHQie9Rj9LP4pWD5LsHwO0M/icKExptZbOy2mNldDiEi6N7VpAoF+Fv8ULJ8lWD4H6GepK63NpZRSqsE0mCillGowDSbeecXXE2hE+ln8U7B8lmD5HKCfpU50zUQppVSD6ZWJUkqpBtNg4oGIzBORXBHJ8vVcGkpEEkVkrYjsFJEdIvKgr+dUHyISJSIbRWSr/Tme9fWcGqp6Re5AJSL7RWS7iGSKSD3amvoPEWkrIstEZLeI7BKRS309p7oSkYvt/xaOr9Mi8lCTnU9vc7knIlcCBcBCY8wAX8+nIUSkC9DFGLNFROKAzcBNxpidPp5andhFQ2OMMQUiEg58BTxojFlfy1v9loj8EkgFWhtjJvh6PvVlV8lINcYEfG6GiLwOfGmMec1Opo42xpz09bzqy67OfggYboypb76dR3pl4oEx5v+wkiIDnjHmsDFmi/36DFY7gW6e3+V/jKXA/jHc/grYv4icKnK/5uu5KIuItAGuBOYCGGNKAjmQ2EYBe5sqkIAGkxbJbiY2BNjg25nUj31bKBPIBVYbYwLyc9gcFbkrfD2RRmCAz0Rks4jM8fVkGiAJyAPm27cfXxORGF9PqoGmA2835Qk0mLQwIhILvItVzua0r+dTH8aYcmNMMlbxzzQRCchbkIFckduNy40xQ7Ea3d1n3yYORGHAUOBlY8wQoBB4zPNb/Jd9m+5GYGlt+zaEBpMWxF5jeBd40xjznq/n01D2rYe1WJ07A1GNitwi8oZvp1R/xphD9vdcYDnnm98Fmhwgx+mKdxlWcAlU44EtxpijTXkSDSYthL1wPRfYZYz5i6/nU18i0lFE2tqvWwGjgd2+nVX9uKnIPcPH06oXEYmxH+zAviU0BgjIpyCNMUeAgyJysT00CgioB1WquZUmvsUF3ndabJFE5G3gKqCDiOQATxtj5vp2VvU2Ergd2G6vNwD8xhiz0odzqo8uwOv20ykhwBJjTEA/UhskOgPLrb9ZCAPeMsZ86tspNcgvgDftW0T7gNk+nk+92IF9NHB3k59LHw1WSinVUHqbSymlVINpMFFKKdVgGkyUUko1mAYTpZRSDabBRCmlVINpMFHKh0Rkloj83dfzUKqhNJgopZRqMA0mSjUyEXlERB6wX78gIl/Yr68RkTdFZLaIfCciG7GSSR3vu0FENtjFBdeISGcRCRGRPSLS0d4nRESyHT8r5S80mCjV+L4ErrBfpwKxdl20K4DvgGexgsjlQD+n930FjLCLC74D/NoYUwG8Adxm73MtsNUYk9fkn0KpOtBgolTj2wykiEhroBj4F1ZQuQIoBdYZY/KMMSXAYqf3JQCrRGQ78AjQ3x6fB9xhv/4ZML/pP4JSdaPBRKlGZowpBb4HZgHfYF2pXA30wmpK5s7fgL8bYwZi1VKKso93EDgqItdgVeL9pMkmr1Q9aTBRqml8CTwM/J/9+h4gA1gP/ERE4u1bX1Oc3tMGq7UqwMxqx3sN63bXUmNMeVNOXKn60GCiVNP4EqvC8b/sPhJFWD3FDwPPYN36+pqqVyrPAEtFZDNQvY/6CiAWvcWl/JRWDVYqAIhIKvCCMeaKWndWyge0n4lSfk5EHgP+jfNPdCnld/TKRCmlVIPpmolSSqkG02CilFKqwTSYKKWUajANJkoppRpMg4lSSqkG02CilFKqwf4/DTb1xr2ZPWQAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "births_by_weekday.plot(x='wday');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Python to Query BigQuery Data\n", + "\n", + "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a Pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with Pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", + "\n", + "To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import bigquery\n", + "\n", + "client = bigquery.Client()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.)." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
pluralitycountyear
021392092007
121388662008
221372392006
321332852005
421323442004
\n", + "
" + ], + "text/plain": [ + " plurality count year\n", + "0 2 139209 2007\n", + "1 2 138866 2008\n", + "2 2 137239 2006\n", + "3 2 133285 2005\n", + "4 2 132344 2004" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sql = \"\"\"\n", + "SELECT\n", + " plurality,\n", + " COUNT(1) AS count,\n", + " year\n", + "FROM\n", + " `bigquery-public-data.samples.natality`\n", + "WHERE\n", + " NOT IS_NAN(plurality) AND plurality > 1\n", + "GROUP BY\n", + " plurality, year\n", + "ORDER BY\n", + " count DESC\n", + "\"\"\"\n", + "df = client.query(sql).to_dataframe()\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA4MAAAG8CAYAAABkJHCrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XucXWV97/HPjwRBuYRbQJpAgxUlCAokAgKHghQISokIIoolIMrxwhFrWwVPe7BaFVvrhR61hwoSbCkqVkkRBORSqxYhEDRcpASIMClCyiWgGCHhd/5YT2QzmUkme8+ePTvP5/167des/ay1v/uZNTN7z2+vZz0rMhNJkiRJUl026HUHJEmSJEljz2JQkiRJkipkMShJkiRJFbIYlCRJkqQKWQxKkiRJUoUsBiVJkiSpQhaDkiRJklQhi0FJkiRJqpDFoCRJkiRVaGKvOzDattlmm5w2bVqvuyFJkiRJPXHzzTf/d2ZOXtt2610xOG3aNObPn9/rbkiSJElST0TEz0eyncNEJUmSJKlCFoOSJEmSVCGLQUmSJEmq0Hp3zuBQnnnmGQYGBli+fHmvu9KWjTfemKlTp7Lhhhv2uiuSJEmS1hNVFIMDAwNsttlmTJs2jYjodXfWSWbyyCOPMDAwwE477dTr7kiSJElaT1QxTHT58uVsvfXWfVcIAkQEW2+9dd8e1ZQkSZI0PlVRDAJ9WQiu0s99lyRJkjQ+VVMMSpIkSZKeYzE4yEEHHTRqF62//vrrOfLIIwGYN28eZ599NgDf/va3ueOOO0blOSRJkiSpHRaDHVqxYsWItjvqqKM444wzAItBSZIkSb1XbTG4ePFidtllF0444QSmT5/Osccey1NPPfW8bTbddNPfLl9yySWcdNJJAJx00km8613vYp999uGDH/wgN954I695zWvYc8892W+//bjrrrtWe74LLriA0047jR/96EfMmzePP/uzP2OPPfbgnnvuYa+99vrtdnfffffz7kuSJElSN1RxaYnh3HXXXZx33nnsv//+vP3tb+eLX/ziiB87MDDAj370IyZMmMATTzzBv//7vzNx4kS+973v8eEPf5hvfvObQz5uv/3246ijjuLII4/k2GOPBWDSpEnceuut7LHHHnzlK1/h5JNPHpXvT5IkSZKGU3UxuMMOO7D//vsD8La3vY1zzjlnxI9905vexIQJEwBYtmwZc+bM4e677yYieOaZZ9apH+94xzv4yle+wmc+8xm+9rWvceONN67T4yVJkiRpXVU7TBRWv2TDmu4Pvs7fJpts8tvlv/iLv+Dggw/mtttu41//9V/X+ZqAxxxzDFdccQWXXXYZM2bMYOutt16nx0uSJEnSuqq6GLz//vv5j//4DwAuuugiDjjggOet32677bjzzjt59tln+da3vjVszrJly5gyZQrQnBu4NpttthlPPvnkb+9vvPHGHH744bz73e92iKgkSZKkMVF1Mfjyl7+cL3zhC0yfPp3HHnuMd7/73c9bf/bZZ3PkkUey3377sf322w+b88EPfpAzzzyTPffcc0Szix5//PH8zd/8DXvuuSf33HMPACeccAIbbLABhx12WGfflCRJkiSNQGRmr/swqmbOnJmDrxN45513Mn369Oe1LV68mCOPPJLbbrttLLs3rE9/+tMsW7aMj33sY0OuH+p7kCRJktQbu8/dfcTbLpyzsIs9WV1E3JyZM9e2XdUTyIwXRx99NPfccw/XXnttr7siSZIkaQQW3nd/V3LHssisthicNm3auDkquKbzESVJkiTVo1tF5lCqPmdQkiRJkmplMShJkiRJFap2mKgkSZKk9d94nuil1ywGJUmSJK23xvIcvH5TfTE47YzvjGre4rNfv9ZtHnjgAU488UQeeughIoJTTz2V008/fVT7IUmSJElrUn0x2AsTJ07kb//2b9lrr7148sknmTFjBoceeii77rprr7smSZIkqRJOINMD22+/PXvttRcAm222GdOnT2fJkiU97pUkSZKkmlgM9tjixYtZsGAB++yzT6+7IkmSJKkiay0GI+L8iHg4Ila7QntE/ElEZERsU+5HRJwTEYsi4qcRsVfLtnMi4u5ym9PSPiMiFpbHnBMRUdq3ioiry/ZXR8SWo/Mtjx+//OUvOeaYY/jc5z7H5ptv3uvuSJIkSarISI4MXgDMGtwYETsAhwGt0/McAexcbqcCXyrbbgWcBewD7A2c1VLcfQl4Z8vjVj3XGcA1mbkzcE25v9545plnOOaYYzjhhBN44xvf2OvuSJIkSarMWovBzPw+8OgQqz4LfBDIlrbZwIXZuAHYIiK2Bw4Hrs7MRzPzMeBqYFZZt3lm3pCZCVwIvKEla25ZntvS3vcyk1NOOYXp06fz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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "pivot_table = df.pivot(index='year', columns='plurality', values='count')\n", + "pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the following query to retrieve the count of births by the number of gestation weeks." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "sql = \"\"\"\n", + "SELECT\n", + " gestation_weeks,\n", + " COUNT(1) AS count\n", + "FROM\n", + " `bigquery-public-data.samples.natality`\n", + "WHERE\n", + " NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99\n", + "GROUP BY\n", + " gestation_weeks\n", + "ORDER BY\n", + " gestation_weeks\n", + "\"\"\"\n", + "df = client.query(sql).to_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, chart the query results in your DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7))\n", + "ax.set_title('Count of Births by Gestation Weeks')\n", + "ax.set_xlabel('Gestation Weeks')\n", + "ax.set_ylabel('Count');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### What's Next\n", + "\n", + "+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more.\n", + "\n", + "+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb new file mode 100644 index 00000000000..a63957b1147 --- /dev/null +++ b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb @@ -0,0 +1,344 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery Basics\n", + "\n", + "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Import the libraries used in this tutorial" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import bigquery\n", + "import pandas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize a client\n", + "\n", + "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = bigquery.Client()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a query on a public dataset\n", + "\n", + "The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", + "\n", + "Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "query = \"\"\"\n", + " SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + " WHERE state = \"TX\"\n", + " LIMIT 10\n", + "\"\"\"\n", + "query_job = client.query(\n", + " query,\n", + " # Location must match that of the dataset(s) referenced in the query.\n", + " location=\"US\",\n", + ") # API request - starts the query\n", + "\n", + "df = query_job.to_dataframe()\n", + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a new dataset\n", + "\n", + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import time\n", + "\n", + "# Define a name for the new dataset.\n", + "dataset_id = 'my_new_dataset'\n", + "\n", + "# Create a DatasetReference using a chosen dataset ID.\n", + "# The project defaults to the Client's project if not specified.\n", + "dataset_ref = client.dataset(dataset_id)\n", + "\n", + "# Construct a full Dataset object to send to the API.\n", + "dataset = bigquery.Dataset(dataset_ref)\n", + "# Specify the geographic location where the dataset should reside.\n", + "dataset.location = 'US'\n", + "\n", + "# Send the dataset to the API for creation.\n", + "dataset = client.create_dataset(dataset) # API request" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a Pandas DataFrame to a new table" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "records = [\n", + " {\"title\": \"The Meaning of Life\", \"release_year\": 1983},\n", + " {\"title\": \"Monty Python and the Holy Grail\", \"release_year\": 1975},\n", + " {\"title\": \"Life of Brian\", \"release_year\": 1979},\n", + " {\"title\": \"And Now for Something Completely Different\", \"release_year\": 1971},\n", + "]\n", + "\n", + "# Optionally set explicit indices.\n", + "# If indices are not specified, a column will be created for the default\n", + "# indices created by pandas.\n", + "index = [\"Q24980\", \"Q25043\", \"Q24953\", \"Q16403\"]\n", + "df = pandas.DataFrame(records, index=pandas.Index(index, name=\"wikidata_id\"))\n", + "\n", + "table_ref = dataset_ref.table(\"monty_python\")\n", + "job = client.load_table_from_dataframe(df, table_ref, location=\"US\")\n", + "\n", + "job.result() # Waits for table load to complete.\n", + "print(\"Loaded dataframe to {}\".format(table_ref.path))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load query results to a table\n", + "\n", + "For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sql = \"\"\"\n", + " SELECT corpus\n", + " FROM `bigquery-public-data.samples.shakespeare`\n", + " GROUP BY corpus;\n", + "\"\"\"\n", + "table_ref = dataset.table(\"your_new_table_id\")\n", + "job_config = bigquery.QueryJobConfig(\n", + " destination=table_ref\n", + ")\n", + "\n", + "# Start the query, passing in the extra configuration.\n", + "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", + "\n", + "query_job.result() # Waits for the query to finish\n", + "print(\"Query results loaded to table {}\".format(table_ref.path))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a local file to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "source_filename = 'resources/us-states.csv'\n", + "\n", + "table_ref = dataset_ref.table('us_states_from_local_file')\n", + "job_config = bigquery.LoadJobConfig(\n", + " source_format=bigquery.SourceFormat.CSV,\n", + " skip_leading_rows=1,\n", + " autodetect=True\n", + ")\n", + "\n", + "with open(source_filename, 'rb') as source_file:\n", + " job = client.load_table_from_file(\n", + " source_file,\n", + " table_ref,\n", + " location='US', # Must match the destination dataset location.\n", + " job_config=job_config) # API request\n", + "\n", + "job.result() # Waits for table load to complete.\n", + "\n", + "print('Loaded {} rows into {}:{}.'.format(\n", + " job.output_rows, dataset_id, table_ref.path))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from Google Cloud Storage to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Configure the load job\n", + "job_config = bigquery.LoadJobConfig(\n", + " schema=[\n", + " bigquery.SchemaField('name', 'STRING'),\n", + " bigquery.SchemaField('post_abbr', 'STRING')\n", + " ],\n", + " skip_leading_rows=1,\n", + " # The source format defaults to CSV, so the line below is optional.\n", + " source_format=bigquery.SourceFormat.CSV\n", + ")\n", + "uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'\n", + "destination_table_ref = dataset.table('us_states_from_gcs')\n", + "\n", + "# Start the load job\n", + "load_job = client.load_table_from_uri(\n", + " uri, destination_table_ref, job_config=job_config)\n", + "print('Starting job {}'.format(load_job.job_id))\n", + "\n", + "load_job.result() # Waits for table load to complete.\n", + "print('Job finished.')\n", + "\n", + "# Retreive the destination table\n", + "destination_table = client.get_table(table_ref)\n", + "print('Loaded {} rows.'.format(destination_table.num_rows))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a parameterized query\n", + "\n", + "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", + "\n", + "To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", + "\n", + "For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define the query\n", + "sql = \"\"\"\n", + " SELECT word, word_count\n", + " FROM `bigquery-public-data.samples.shakespeare`\n", + " WHERE corpus = @corpus\n", + " AND word_count >= @min_word_count\n", + " ORDER BY word_count DESC;\n", + "\"\"\"\n", + "\n", + "# Define the parameter values in a query job configuration\n", + "job_config = bigquery.QueryJobConfig(\n", + " query_parameters=[\n", + " bigquery.ScalarQueryParameter(\"corpus\", \"STRING\", \"romeoandjuliet\"),\n", + " bigquery.ScalarQueryParameter(\"min_word_count\", \"INT64\", 250),\n", + " ]\n", + ")\n", + "\n", + "# Start the query job\n", + "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", + "\n", + "# Return the results as a Pandas DataFrame\n", + "query_job.to_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning Up\n", + "\n", + "The following code deletes the dataset created for this tutorial, including all tables in the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Retrieve the dataset from the API\n", + "dataset = client.get_dataset(client.dataset(dataset_id))\n", + "\n", + "# Delete the dataset and its contents\n", + "client.delete_dataset(dataset, delete_contents=True)\n", + "\n", + "print('Deleted dataset: {}'.format(dataset.path))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb new file mode 100644 index 00000000000..1131c29c452 --- /dev/null +++ b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb @@ -0,0 +1,189 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery Query Magic\n", + "\n", + "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a query on a public dataset\n", + "\n", + "The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", + "\n", + "The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "%%bigquery\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Display verbose output\n", + "\n", + "As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery --verbose\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Explicitly specify a project\n", + "\n", + "By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "project_id = 'my-project-id'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "project_id = 'ajhamilton-scratch'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery --project $project_id\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assign the query results to a variable\n", + "\n", + "If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery df\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT 10" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a parameterized query\n", + "\n", + "Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "params = {\"limit\": 10}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery --params $params\n", + "SELECT name, SUM(number) as count\n", + "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + "GROUP BY name\n", + "ORDER BY count DESC\n", + "LIMIT @limit" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb b/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb new file mode 100644 index 00000000000..84491817746 --- /dev/null +++ b/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb @@ -0,0 +1,144 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BigQuery command-line tool\n", + "\n", + "The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## View available commands\n", + "\n", + "To view the available commands for the BigQuery command-line tool, use the `--help` flag." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq help" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a new dataset\n", + "\n", + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", + "\n", + "The example below creates a new dataset in the US named \"your_new_dataset\"." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq --location=US mk --dataset \"your_dataset_id\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a local file to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq load --help" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from Google Cloud Storage to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run a query\n", + "\n", + "The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning Up\n", + "\n", + "The following code deletes the dataset created for this tutorial, including all tables in the dataset." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq rm -r -f --dataset your_dataset_id" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb b/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb new file mode 100644 index 00000000000..298491a3a22 --- /dev/null +++ b/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb @@ -0,0 +1,271 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Vizualizing BigQuery Data in a Jupyter Notebook\n", + "\n", + "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime.\n", + "\n", + "Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and Pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Jupyter Magics to Query BigQuery Data\n", + "\n", + "The BigQuery Python client library provides a magic command that allows you to run queries with minimal code.\n", + "\n", + "The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery\n", + "SELECT\n", + " source_year AS year,\n", + " COUNT(is_male) AS birth_count\n", + "FROM `bigquery-public-data.samples.natality`\n", + "GROUP BY year\n", + "ORDER BY year DESC\n", + "LIMIT 15" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery total_births\n", + "SELECT\n", + " source_year AS year,\n", + " COUNT(is_male) AS birth_count\n", + "FROM `bigquery-public-data.samples.natality`\n", + "GROUP BY year\n", + "ORDER BY year DESC\n", + "LIMIT 15" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The next cell uses the Pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [Pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with Pandas." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "total_births.plot(kind='bar', x='year', y='birth_count');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery births_by_weekday\n", + "SELECT\n", + " wday,\n", + " SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births,\n", + " SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births\n", + "FROM `bigquery-public-data.samples.natality`\n", + "WHERE wday IS NOT NULL\n", + "GROUP BY wday\n", + "ORDER BY wday ASC" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Visualize the query results using a line chart." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "births_by_weekday.plot(x='wday');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using Python to Query BigQuery Data\n", + "\n", + "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a Pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with Pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", + "\n", + "To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import bigquery\n", + "\n", + "client = bigquery.Client()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sql = \"\"\"\n", + "SELECT\n", + " plurality,\n", + " COUNT(1) AS count,\n", + " year\n", + "FROM\n", + " `bigquery-public-data.samples.natality`\n", + "WHERE\n", + " NOT IS_NAN(plurality) AND plurality > 1\n", + "GROUP BY\n", + " plurality, year\n", + "ORDER BY\n", + " count DESC\n", + "\"\"\"\n", + "df = client.query(sql).to_dataframe()\n", + "df.head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pivot_table = df.pivot(index='year', columns='plurality', values='count')\n", + "pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the following query to retrieve the count of births by the number of gestation weeks." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sql = \"\"\"\n", + "SELECT\n", + " gestation_weeks,\n", + " COUNT(1) AS count\n", + "FROM\n", + " `bigquery-public-data.samples.natality`\n", + "WHERE\n", + " NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99\n", + "GROUP BY\n", + " gestation_weeks\n", + "ORDER BY\n", + " gestation_weeks\n", + "\"\"\"\n", + "df = client.query(sql).to_dataframe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, chart the query results in your DataFrame." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7))\n", + "ax.set_title('Count of Births by Gestation Weeks')\n", + "ax.set_xlabel('Gestation Weeks')\n", + "ax.set_ylabel('Count');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### What's Next\n", + "\n", + "+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more.\n", + "\n", + "+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorials/bigquery/resources/us-states.csv b/notebooks/tutorials/bigquery/resources/us-states.csv new file mode 100644 index 00000000000..54a60e29de9 --- /dev/null +++ b/notebooks/tutorials/bigquery/resources/us-states.csv @@ -0,0 +1,51 @@ +name,post_abbr +Alabama,AL +Alaska,AK +Arizona,AZ +Arkansas,AR +California,CA +Colorado,CO +Connecticut,CT +Delaware,DE +Florida,FL +Georgia,GA +Hawaii,HI +Idaho,ID +Illinois,IL +Indiana,IN +Iowa,IA +Kansas,KS +Kentucky,KY +Louisiana,LA +Maine,ME +Maryland,MD +Massachusetts,MA +Michigan,MI +Minnesota,MN +Mississippi,MS +Missouri,MO +Montana,MT +Nebraska,NE +Nevada,NV +New Hampshire,NH +New Jersey,NJ +New Mexico,NM +New York,NY +North Carolina,NC +North Dakota,ND +Ohio,OH +Oklahoma,OK +Oregon,OR +Pennsylvania,PA +Rhode Island,RI +South Carolina,SC +South Dakota,SD +Tennessee,TN +Texas,TX +Utah,UT +Vermont,VT +Virginia,VA +Washington,WA +West Virginia,WV +Wisconsin,WI +Wyoming,WY diff --git a/notebooks/tutorials/storage/Storage Client Library.ipynb b/notebooks/tutorials/storage/Storage Client Library.ipynb new file mode 100644 index 00000000000..25465d5dbb7 --- /dev/null +++ b/notebooks/tutorials/storage/Storage Client Library.ipynb @@ -0,0 +1,294 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Google Cloud Storage\n", + "\n", + "This page shows how to get started with the Google Cloud Storage Python client library." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Import the library" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import storage" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Projects\n", + "\n", + "All data in Cloud Storage belongs inside a project. A project consists of a\n", + "set of users, a set of APIs, and billing, authentication, and monitoring\n", + "settings for those APIs. You can have one project or multiple projects." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Clients\n", + "Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = storage.Client(project=\"your-project-id\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Buckets\n", + "\n", + "Buckets are the basic containers that hold your data. Everything that you\n", + "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", + "organize your data and control access to your data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create a bucket\n", + "\n", + "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", + "you specify a globally-unique name." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Replace the string below with a unique name for the new bucket\n", + "bucket_name = 'my-new-bucket'\n", + "\n", + "# Creates the new bucket\n", + "bucket = client.create_bucket(bucket_name)\n", + "\n", + "print('Bucket {} created.'.format(bucket.name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List buckets in a project" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "buckets = client.list_buckets()\n", + "\n", + "print(\"Buckets in {}:\".format(client.project))\n", + "for item in buckets:\n", + " print(\"\\t\" + item.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bucket = client.get_bucket(bucket_name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objects\n", + "\n", + "Objects are the individual pieces of data that you store in Cloud Storage.\n", + "There is no limit on the number of objects that you can create in a bucket." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload a local file to a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "blob_name = 'us-states.txt'\n", + "blob = bucket.blob(blob_name)\n", + "\n", + "source_file_name = 'resources/us-states.txt'\n", + "blob.upload_from_filename(source_file_name)\n", + "\n", + "print('File uploaded to {}.'.format(bucket.name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List blobs in a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "blobs = bucket.list_blobs()\n", + "\n", + "print(\"Blobs in {}:\".format(bucket.name))\n", + "for item in blobs:\n", + " print(\"\\t\" + item.name)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a blob and display metadata\n", + "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "blob = bucket.get_blob(blob_name)\n", + "\n", + "print('Select metadata for blob {}:'.format(blob_name))\n", + "print('\\tID: {}'.format(blob.id))\n", + "print('\\tSize: {} bytes'.format(blob.size))\n", + "print('\\tUpdated: {}'.format(blob.updated))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download a blob to a local directory" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "output_file_name = 'resources/downloaded-us-states.txt'\n", + "blob.download_to_filename(output_file_name)\n", + "\n", + "print('Downloaded blob {} to {}.'.format(blob.name, output_file_name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning up" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a blob" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "blob = client.get_bucket(bucket_name).get_blob(blob_name)\n", + "blob.delete()\n", + "\n", + "print('Blob {} deleted.'.format(blob.name))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bucket = client.get_bucket(bucket_name)\n", + "bucket.delete()\n", + "\n", + "print('Bucket {} deleted.'.format(bucket.name))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage Commands.ipynb new file mode 100644 index 00000000000..a8972060ad7 --- /dev/null +++ b/notebooks/tutorials/storage/Storage Commands.ipynb @@ -0,0 +1,241 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Storage Commands\n", + "\n", + "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage.\n", + "\n", + "This notebook introduces several `gsutil` commands for interacting with Cloud Storage." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## List available commands\n", + "\n", + "The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "!gsutil help" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Buckets\n", + "\n", + "Buckets are the basic containers that hold your data. Everything that you\n", + "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", + "organize your data and control access to your data." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Create a bucket\n", + "\n", + "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", + "you specify a globally-unique name." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Replace the string below with a unique name for the new bucket\n", + "bucket_name = 'my-new-bucket'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil mb gs://{bucket_name}/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List buckets in a project\n", + "\n", + "Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil ls -p your-project-id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Objects\n", + "\n", + "Objects are the individual pieces of data that you store in Cloud Storage.\n", + "There is no limit on the number of objects that you can create in a bucket." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Upload a local file to a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil cp resources/us-states.txt gs://{bucket_name}/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### List blobs in a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "!gsutil ls -r gs://{bucket_name}/**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Get a blob and display metadata\n", + "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil ls -L gs://{bucket_name}/us-states.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Download a blob to a local directory" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning up" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a blob" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "!gsutil rm gs://{bucket_name}/us-states.txt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Delete a bucket" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil rm -r gs://{bucket_name}/" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/notebooks/tutorials/storage/resources/downloaded-us-states.txt b/notebooks/tutorials/storage/resources/downloaded-us-states.txt new file mode 100644 index 00000000000..54a60e29de9 --- /dev/null +++ b/notebooks/tutorials/storage/resources/downloaded-us-states.txt @@ -0,0 +1,51 @@ +name,post_abbr +Alabama,AL +Alaska,AK +Arizona,AZ +Arkansas,AR +California,CA +Colorado,CO +Connecticut,CT +Delaware,DE +Florida,FL +Georgia,GA +Hawaii,HI +Idaho,ID +Illinois,IL +Indiana,IN +Iowa,IA +Kansas,KS +Kentucky,KY +Louisiana,LA +Maine,ME +Maryland,MD +Massachusetts,MA +Michigan,MI +Minnesota,MN +Mississippi,MS +Missouri,MO +Montana,MT +Nebraska,NE +Nevada,NV +New Hampshire,NH +New Jersey,NJ +New Mexico,NM +New York,NY +North Carolina,NC +North Dakota,ND +Ohio,OH +Oklahoma,OK +Oregon,OR +Pennsylvania,PA +Rhode Island,RI +South Carolina,SC +South Dakota,SD +Tennessee,TN +Texas,TX +Utah,UT +Vermont,VT +Virginia,VA +Washington,WA +West Virginia,WV +Wisconsin,WI +Wyoming,WY diff --git a/notebooks/tutorials/storage/resources/us-states.txt b/notebooks/tutorials/storage/resources/us-states.txt new file mode 100644 index 00000000000..54a60e29de9 --- /dev/null +++ b/notebooks/tutorials/storage/resources/us-states.txt @@ -0,0 +1,51 @@ +name,post_abbr +Alabama,AL +Alaska,AK +Arizona,AZ +Arkansas,AR +California,CA +Colorado,CO +Connecticut,CT +Delaware,DE +Florida,FL +Georgia,GA +Hawaii,HI +Idaho,ID +Illinois,IL +Indiana,IN +Iowa,IA +Kansas,KS +Kentucky,KY +Louisiana,LA +Maine,ME +Maryland,MD +Massachusetts,MA +Michigan,MI +Minnesota,MN +Mississippi,MS +Missouri,MO +Montana,MT +Nebraska,NE +Nevada,NV +New Hampshire,NH +New Jersey,NJ +New Mexico,NM +New York,NY +North Carolina,NC +North Dakota,ND +Ohio,OH +Oklahoma,OK +Oregon,OR +Pennsylvania,PA +Rhode Island,RI +South Carolina,SC +South Dakota,SD +Tennessee,TN +Texas,TX +Utah,UT +Vermont,VT +Virginia,VA +Washington,WA +West Virginia,WV +Wisconsin,WI +Wyoming,WY From 1b23b58488377e3c07637acdaa600180216cf532 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Wed, 23 Jan 2019 11:07:59 -0800 Subject: [PATCH 02/24] add rendered notebooks folder --- .../BigQuery Basics_output.md | 414 ++++++++++++ .../BigQuery Query Magic_output.md | 603 +++++++++++++++++ .../BigQuery Shell Commands_output.md | 638 ++++++++++++++++++ .../Storage Client Library_output.md | 182 +++++ .../Storage Commands_output.md | 247 +++++++ .../Visualize BigQuery Public Data_output.md | 524 ++++++++++++++ 6 files changed, 2608 insertions(+) create mode 100644 notebooks/test/rendered_notebooks/BigQuery Basics_output.md create mode 100644 notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md create mode 100644 notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md create mode 100644 notebooks/test/rendered_notebooks/Storage Client Library_output.md create mode 100644 notebooks/test/rendered_notebooks/Storage Commands_output.md create mode 100644 notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md diff --git a/notebooks/test/rendered_notebooks/BigQuery Basics_output.md b/notebooks/test/rendered_notebooks/BigQuery Basics_output.md new file mode 100644 index 00000000000..6816db06513 --- /dev/null +++ b/notebooks/test/rendered_notebooks/BigQuery Basics_output.md @@ -0,0 +1,414 @@ + + +```python +%matplotlib inline +``` + + +```python +%load_ext google.cloud.bigquery +``` + +# BigQuery Basics + +[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library. + +## Import the libraries used in this tutorial + + +```python +from google.cloud import bigquery +import pandas +``` + +## Initialize a client + +To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. + + +```python +client = bigquery.Client() +``` + +## Run a query on a public dataset + +The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. + +Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). + + +```python +query = """ + SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current` + WHERE state = "TX" + LIMIT 10 +""" +query_job = client.query( + query, + # Location must match that of the dataset(s) referenced in the query. + location="US", +) # API request - starts the query + +df = query_job.to_dataframe() +df +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
name
0Mary
1Ruby
2Annie
3Willie
4Ruth
5Gladys
6Maria
7Frances
8Margaret
9Helen
+
+ + + +## Create a new dataset + +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). + + +```python +import time + +# Define a name for the new dataset. +dataset_id = 'test_dataset_1548268897503' + +# Create a DatasetReference using a chosen dataset ID. +# The project defaults to the Client's project if not specified. +dataset_ref = client.dataset(dataset_id) + +# Construct a full Dataset object to send to the API. +dataset = bigquery.Dataset(dataset_ref) +# Specify the geographic location where the dataset should reside. +dataset.location = 'US' + +# Send the dataset to the API for creation. +dataset = client.create_dataset(dataset) # API request +``` + +## Load data from a Pandas DataFrame to a new table + + +```python +records = [ + {"title": "The Meaning of Life", "release_year": 1983}, + {"title": "Monty Python and the Holy Grail", "release_year": 1975}, + {"title": "Life of Brian", "release_year": 1979}, + {"title": "And Now for Something Completely Different", "release_year": 1971}, +] + +# Optionally set explicit indices. +# If indices are not specified, a column will be created for the default +# indices created by pandas. +index = ["Q24980", "Q25043", "Q24953", "Q16403"] +df = pandas.DataFrame(records, index=pandas.Index(index, name="wikidata_id")) + +table_ref = dataset_ref.table("monty_python") +job = client.load_table_from_dataframe(df, table_ref, location="US") + +job.result() # Waits for table load to complete. +print("Loaded dataframe to {}".format(table_ref.path)) +``` + + Loaded dataframe to /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/monty_python + + +## Load query results to a table + +For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. + + +```python +sql = """ + SELECT corpus + FROM `bigquery-public-data.samples.shakespeare` + GROUP BY corpus; +""" +table_ref = dataset.table("your_new_table_id") +job_config = bigquery.QueryJobConfig( + destination=table_ref +) + +# Start the query, passing in the extra configuration. +query_job = client.query(sql, location="US", job_config=job_config) + +query_job.result() # Waits for the query to finish +print("Query results loaded to table {}".format(table_ref.path)) +``` + + Query results loaded to table /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/your_new_table_id + + +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + + +```python +source_filename = 'resources/us-states.csv' + +table_ref = dataset_ref.table('us_states_from_local_file') +job_config = bigquery.LoadJobConfig( + source_format=bigquery.SourceFormat.CSV, + skip_leading_rows=1, + autodetect=True +) + +with open(source_filename, 'rb') as source_file: + job = client.load_table_from_file( + source_file, + table_ref, + location='US', # Must match the destination dataset location. + job_config=job_config) # API request + +job.result() # Waits for table load to complete. + +print('Loaded {} rows into {}:{}.'.format( + job.output_rows, dataset_id, table_ref.path)) +``` + + Loaded 50 rows into test_dataset_1548268897503:/projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/us_states_from_local_file. + + +## Load data from Google Cloud Storage to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. + + +```python +# Configure the load job +job_config = bigquery.LoadJobConfig( + schema=[ + bigquery.SchemaField('name', 'STRING'), + bigquery.SchemaField('post_abbr', 'STRING') + ], + skip_leading_rows=1, + # The source format defaults to CSV, so the line below is optional. + source_format=bigquery.SourceFormat.CSV +) +uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +destination_table_ref = dataset.table('us_states_from_gcs') + +# Start the load job +load_job = client.load_table_from_uri( + uri, destination_table_ref, job_config=job_config) +print('Starting job {}'.format(load_job.job_id)) + +load_job.result() # Waits for table load to complete. +print('Job finished.') + +# Retreive the destination table +destination_table = client.get_table(table_ref) +print('Loaded {} rows.'.format(destination_table.num_rows)) +``` + + Starting job f65c1470-3e8b-4b0f-8a44-ff6a3f5cbaf0 + Job finished. + Loaded 50 rows. + + +## Run a parameterized query + +BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query. + +To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value. + +For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation. + + +```python +# Define the query +sql = """ + SELECT word, word_count + FROM `bigquery-public-data.samples.shakespeare` + WHERE corpus = @corpus + AND word_count >= @min_word_count + ORDER BY word_count DESC; +""" + +# Define the parameter values in a query job configuration +job_config = bigquery.QueryJobConfig( + query_parameters=[ + bigquery.ScalarQueryParameter("corpus", "STRING", "romeoandjuliet"), + bigquery.ScalarQueryParameter("min_word_count", "INT64", 250), + ] +) + +# Start the query job +query_job = client.query(sql, location="US", job_config=job_config) + +# Return the results as a Pandas DataFrame +query_job.to_dataframe() +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
wordword_count
0the614
1I577
2and490
3to486
4a407
5of367
6my314
7is307
8in291
9you271
10that270
11me263
+
+ + + +## Cleaning Up + +The following code deletes the dataset created for this tutorial, including all tables in the dataset. + + +```python +# Retrieve the dataset from the API +dataset = client.get_dataset(client.dataset(dataset_id)) + +# Delete the dataset and its contents +client.delete_dataset(dataset, delete_contents=True) + +print('Deleted dataset: {}'.format(dataset.path)) +``` + + Deleted dataset: /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503 + diff --git a/notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md b/notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md new file mode 100644 index 00000000000..8d1ae3b6154 --- /dev/null +++ b/notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md @@ -0,0 +1,603 @@ + + +```python +%matplotlib inline +``` + + +```python +%load_ext google.cloud.bigquery +``` + +# BigQuery Query Magic + +Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. + +## Run a query on a public dataset + +The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. + +The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). + + +```python +%%bigquery +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Display verbose output + +As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion. + + +```python +%%bigquery --verbose +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + Executing query with job ID: 791c0804-adf8-432a-8618-dab212848f03 + Query executing: 0.48s + Query complete after 0.93s + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Explicitly specify a project + +By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. + + +```python +project_id = 'my-project-id' +``` + + +```python +project_id = 'ajhamilton-scratch' +``` + + +```python +%%bigquery --project $project_id +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Assign the query results to a variable + +If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command. + + +```python +%%bigquery df +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + + +```python +df +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Run a parameterized query + +Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. + + +```python +params = {"limit": 10} +``` + + +```python +%%bigquery --params $params +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT @limit +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + diff --git a/notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md b/notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md new file mode 100644 index 00000000000..74bee8a29b9 --- /dev/null +++ b/notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md @@ -0,0 +1,638 @@ + + +```python +%matplotlib inline +``` + + +```python +%load_ext google.cloud.bigquery +``` + +# BigQuery command-line tool + +The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`. + +## View available commands + +To view the available commands for the BigQuery command-line tool, use the `--help` flag. + + +```python +!bq help +``` + + Python script for interacting with BigQuery. + + + USAGE: bq [--global_flags] [--command_flags] [args] + + + Any of the following commands: + cancel, cp, extract, head, help, init, insert, load, ls, mk, mkdef, partition, + query, rm, shell, show, update, version, wait + + + cancel Request a cancel and waits for the job to be cancelled. + + Requests a cancel and then either: a) waits until the job is done if + the sync flag is set [default], or b) returns immediately if the sync + flag is not set. Not all job types support a cancel, an error is + returned if it cannot be cancelled. Even for jobs that support a + cancel, success is not guaranteed, the job may have completed by the + time the cancel request is noticed, or the job may be in a stage + where it cannot be cancelled. + + Examples: + bq cancel job_id # Requests a cancel and waits until the job is done. + bq --nosync cancel job_id # Requests a cancel and returns + immediately. + + Arguments: + job_id: Job ID to cancel. + + cp Copies one table to another. + + Examples: + bq cp dataset.old_table dataset2.new_table + bq cp --destination_kms_key=kms_key dataset.old_table + dataset2.new_table + + extract Perform an extract operation of source_table into destination_uris. + + Usage: + extract + + Examples: + bq extract ds.summary gs://mybucket/summary.csv + + Arguments: + source_table: Source table to extract. + destination_uris: One or more Google Cloud Storage URIs, separated by + commas. + + head Displays rows in a table. + + Examples: + bq head dataset.table + bq head -j job + bq head -n 10 dataset.table + bq head -s 5 -n 10 dataset.table + + help Help for all or selected command: + bq help [] + + To retrieve help with global flags: + bq --help + + To retrieve help with flags only from the main module: + bq --helpshort [] + + init Authenticate and create a default .bigqueryrc file. + + insert Inserts rows in a table. + + Inserts the records formatted as newline delimited JSON from file + into the specified table. If file is not specified, reads from stdin. + If there were any insert errors it prints the errors to stdout. + + Examples: + bq insert dataset.table /tmp/mydata.json + echo '{"a":1, "b":2}' | bq insert dataset.table + + Template table examples: Insert to dataset.template_suffix table + using dataset.template table as its template. + bq insert -x=_suffix dataset.table /tmp/mydata.json + + load Perform a load operation of source into destination_table. + + Usage: + load [] + + The is the fully-qualified table name of table to + create, or append to if the table already exists. + + The argument can be a path to a single local file, or a + comma-separated list of URIs. + + The argument should be either the name of a JSON file or a + text schema. This schema should be omitted if the table already has + one. + + In the case that the schema is provided in text form, it should be a + comma-separated list of entries of the form name[:type], where type + will default to string if not specified. + + In the case that is a filename, it should contain a single + array object, each entry of which should be an object with properties + 'name', 'type', and (optionally) 'mode'. See the online documentation + for more detail: + https://developers.google.com/bigquery/preparing-data-for-bigquery + + Note: the case of a single-entry schema with no type specified is + ambiguous; one can use name:string to force interpretation as a + text schema. + + Examples: + bq load ds.new_tbl ./info.csv ./info_schema.json + bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json + bq load ds.small gs://mybucket/small.csv name:integer,value:string + bq load ds.small gs://mybucket/small.csv field1,field2,field3 + + Arguments: + destination_table: Destination table name. + source: Name of local file to import, or a comma-separated list of + URI paths to data to import. + schema: Either a text schema or JSON file, as above. + + ls List the objects contained in the named collection. + + List the objects in the named project or dataset. A trailing : or . + can be used to signify a project or dataset. + * With -j, show the jobs in the named project. + * With -p, show all projects. + + Examples: + bq ls + bq ls -j proj + bq ls -p -n 1000 + bq ls mydataset + bq ls -a + bq ls --filter labels.color:red + bq ls --filter 'labels.color:red labels.size:*' + bq ls --transfer_config --transfer_location='us' + --filter='dataSourceIds:play,adwords' + bq ls --transfer_run --filter='states:SUCCESSED,PENDING' + --run_attempt='LATEST' projects/p/locations/l/transferConfigs/c + bq ls --transfer_log --message_type='messageTypes:INFO,ERROR' + projects/p/locations/l/transferConfigs/c/runs/r + + mk Create a dataset, table, view, or transfer configuration with this + name. + + See 'bq help load' for more information on specifying the schema. + + Examples: + bq mk new_dataset + bq mk new_dataset.new_table + bq --dataset_id=new_dataset mk table + bq mk -t new_dataset.newtable name:integer,value:string + bq mk --view='select 1 as num' new_dataset.newview + (--view_udf_resource=path/to/file.js) + bq mk -d --data_location=EU new_dataset + bq mk --transfer_config --target_dataset=dataset --display_name=name + -p='{"param":"value"}' --data_source=source + bq mk --transfer_run --start_time={start_time} --end_time={end_time} + projects/p/locations/l/transferConfigs/c + + mkdef Emits a definition in JSON for a GCS backed table. + + The output of this command can be redirected to a file and used for + the external_table_definition flag with the "bq query" and "bq mk" + commands. It produces a definition with the most commonly used values + for options. You can modify the output to override option values. + + Usage: + mkdef [] + + Examples: + bq mkdef 'gs://bucket/file.csv' field1:integer,field2:string + + Arguments: + source_uris: a comma-separated list of uris. + schema: The argument should be either the name of a JSON + file or + a text schema. + + In the case that the schema is provided in text form, it should be a + comma-separated list of entries of the form name[:type], where type + will + default to string if not specified. + + In the case that is a filename, it should contain a + single array object, each entry of which should be an object with + properties 'name', 'type', and (optionally) 'mode'. See the online + documentation for more detail: + https://developers.google.com/bigquery/preparing-data-for-bigquery + + Note: the case of a single-entry schema with no type specified is + ambiguous; one can use name:string to force interpretation as a + text schema. + + partition Copies source tables into partitioned tables. + + Usage: bq partition + + + Copies tables of the format to a + destination partitioned table, with the date suffix of the source + tables becoming the partition date of the destination table + partitions. + + If the destination table does not exist, one will be created with a + schema and that matches the last table that matches the supplied + prefix. + + Examples: + bq partition dataset1.sharded_ dataset2.partitioned_table + + query Execute a query. + + Query should be specifed on command line, or passed on stdin. + + Examples: + bq query 'select count(*) from publicdata:samples.shakespeare' + echo 'select count(*) from publicdata:samples.shakespeare' | bq query + + Usage: + query [] + + rm Delete the dataset, table, or transfer config described by + identifier. + + Always requires an identifier, unlike the show and ls commands. By + default, also requires confirmation before deleting. Supports the -d + -t flags to signify that the identifier is a dataset or table. + * With -f, don't ask for confirmation before deleting. + * With -r, remove all tables in the named dataset. + + Examples: + bq rm ds.table + bq rm -r -f old_dataset + bq rm --transfer_config=projects/p/locations/l/transferConfigs/c + + shell Start an interactive bq session. + + show Show all information about an object. + + Examples: + bq show -j + bq show dataset + bq show [--schema] dataset.table + bq show [--view] dataset.view + bq show --transfer_config projects/p/locations/l/transferConfigs/c + bq show --transfer_run + projects/p/locations/l/transferConfigs/c/runs/r + bq show --encryption_service_account + + update Updates a dataset, table, view or transfer configuration with this + name. + + See 'bq help load' for more information on specifying the schema. + + Examples: + bq update --description "Dataset description" existing_dataset + bq update --description "My table" existing_dataset.existing_table + bq update -t existing_dataset.existing_table + name:integer,value:string + bq update --destination_kms_key + projects/p/locations/l/keyRings/r/cryptoKeys/k + existing_dataset.existing_table + bq update --view='select 1 as num' existing_dataset.existing_view + (--view_udf_resource=path/to/file.js) + bq update --transfer_config --display_name=name + -p='{"param":"value"}' + projects/p/locations/l/transferConfigs/c + bq update --transfer_config --target_dataset=dataset + --refresh_window_days=5 --update_credentials + projects/p/locations/l/transferConfigs/c + + version Return the version of bq. + + wait Wait some number of seconds for a job to finish. + + Poll job_id until either (1) the job is DONE or (2) the specified + number of seconds have elapsed. Waits forever if unspecified. If no + job_id is specified, and there is only one running job, we poll that + job. + + Examples: + bq wait # Waits forever for the currently running job. + bq wait job_id # Waits forever + bq wait job_id 100 # Waits 100 seconds + bq wait job_id 0 # Polls if a job is done, then returns immediately. + # These may exit with a non-zero status code to indicate "failure": + bq wait --fail_on_error job_id # Succeeds if job succeeds. + bq wait --fail_on_error job_id 100 # Succeeds if job succeeds in 100 + sec. + + Arguments: + job_id: Job ID to wait on. + secs: Number of seconds to wait (must be >= 0). + + + Run 'bq --help' to get help for global flags. + Run 'bq help ' to get help for . + + +## Create a new dataset + +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). + +The example below creates a new dataset in the US named "your_new_dataset". + + +```python +!bq --location=US mk --dataset "your_dataset_id" +``` + + Dataset 'ajhamilton-scratch:your_dataset_id' successfully created. + + +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + + +```python +!bq load --help +``` + + Python script for interacting with BigQuery. + + + USAGE: bq [--global_flags] [--command_flags] [args] + + + load Perform a load operation of source into destination_table. + + Usage: + load [] + + The is the fully-qualified table name of table to + create, or append to if the table already exists. + + The argument can be a path to a single local file, or a + comma-separated list of URIs. + + The argument should be either the name of a JSON file or a + text schema. This schema should be omitted if the table already has + one. + + In the case that the schema is provided in text form, it should be a + comma-separated list of entries of the form name[:type], where type + will default to string if not specified. + + In the case that is a filename, it should contain a single + array object, each entry of which should be an object with properties + 'name', 'type', and (optionally) 'mode'. See the online documentation + for more detail: + https://developers.google.com/bigquery/preparing-data-for-bigquery + + Note: the case of a single-entry schema with no type specified is + ambiguous; one can use name:string to force interpretation as a + text schema. + + Examples: + bq load ds.new_tbl ./info.csv ./info_schema.json + bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json + bq load ds.small gs://mybucket/small.csv name:integer,value:string + bq load ds.small gs://mybucket/small.csv field1,field2,field3 + + Arguments: + destination_table: Destination table name. + source: Name of local file to import, or a comma-separated list of + URI paths to data to import. + schema: Either a text schema or JSON file, as above. + + Flags for load: + + /Users/ajhamilton/google-cloud-sdk/platform/bq/bq.py: + --[no]allow_jagged_rows: Whether to allow missing trailing optional columns in + CSV import data. + --[no]allow_quoted_newlines: Whether to allow quoted newlines in CSV import + data. + --[no]autodetect: Enable auto detection of schema and options for formats that + are not self describing like CSV and JSON. + --clustering_fields: Comma separated field names. Can only be specified with + time based partitioning. Data will be first partitioned and subsequently + "clustered on these fields. + --destination_kms_key: Cloud KMS key for encryption of the destination table + data. + -E,--encoding: : The character encoding used by the input + file. Options include: + ISO-8859-1 (also known as Latin-1) + UTF-8 + -F,--field_delimiter: The character that indicates the boundary between + columns in the input file. "\t" and "tab" are accepted names for tab. + --[no]ignore_unknown_values: Whether to allow and ignore extra, unrecognized + values in CSV or JSON import data. + --max_bad_records: Maximum number of bad records allowed before the entire job + fails. + (default: '0') + (an integer) + --null_marker: An optional custom string that will represent a NULL valuein + CSV import data. + --projection_fields: If sourceFormat is set to "DATASTORE_BACKUP", indicates + which entity properties to load into BigQuery from a Cloud Datastore backup. + Property names are case sensitive and must refer to top-level properties. + (default: '') + (a comma separated list) + --quote: Quote character to use to enclose records. Default is ". To indicate + no quote character at all, use an empty string. + --[no]replace: If true erase existing contents before loading new data. + (default: 'false') + --[no]require_partition_filter: Whether to require partition filter for + queries over this table. Only apply to partitioned table. + --schema: Either a filename or a comma-separated list of fields in the form + name[:type]. + --schema_update_option: Can be specified when append to a table, or replace a + table partition. When specified, the schema of the destination table will be + updated with the schema of the new data. One or more of the following + options can be specified: + ALLOW_FIELD_ADDITION: allow new fields to be added + ALLOW_FIELD_RELAXATION: allow relaxing required fields to nullable; + repeat this option to specify a list of values + --skip_leading_rows: The number of rows at the beginning of the source file to + skip. + (an integer) + --source_format: + : Format of + source data. Options include: + CSV + NEWLINE_DELIMITED_JSON + DATASTORE_BACKUP + AVRO + PARQUET + ORC (experimental) + --time_partitioning_expiration: Enables time based partitioning on the table + and sets the number of seconds for which to keep the storage for the + partitions in the table. The storage in a partition will have an expiration + time of its partition time plus this value. A negative number means no + expiration. + (an integer) + --time_partitioning_field: Enables time based partitioning on the table and + the table will be partitioned based on the value of this field. If time + based partitioning is enabled without this value, the table will be + partitioned based on the loading time. + --time_partitioning_type: Enables time based partitioning on the table and set + the type. The only type accepted is DAY, which will generate one partition + per day. + + gflags: + --flagfile: Insert flag definitions from the given file into the command line. + (default: '') + --undefok: comma-separated list of flag names that it is okay to specify on + the command line even if the program does not define a flag with that name. + IMPORTANT: flags in this list that have arguments MUST use the --flag=value + format. + (default: '') + + + Global flags: + + bq_auth_flags: + --application_default_credential_file: Only for the gcloud wrapper use. + (default: '') + --credential_file: Only for the gcloud wrapper use. + (default: '/Users/ajhamilton/.bigquery.v2.token') + --service_account: Only for the gcloud wrapper use. + (default: '') + --service_account_credential_file: Only for the gcloud wrapper use. + --service_account_private_key_file: Only for the gcloud wrapper use. + (default: '') + --service_account_private_key_password: Only for the gcloud wrapper use. + (default: 'notasecret') + --[no]use_gce_service_account: Only for the gcloud wrapper use. + (default: 'false') + + bq_flags: + --api: API endpoint to talk to. + (default: 'https://www.googleapis.com') + --api_version: API version to use. + (default: 'v2') + --apilog: Log all API requests and responses to the file specified by this + flag. Also accepts "stdout" and "stderr". Specifying the empty string will + direct to stdout. + --bigqueryrc: Path to configuration file. The configuration file specifies new + defaults for any flags, and can be overrridden by specifying the flag on the + command line. If the --bigqueryrc flag is not specified, the BIGQUERYRC + environment variable is used. If that is not specified, the path + "~/.bigqueryrc" is used. + (default: '/Users/ajhamilton/.bigqueryrc') + --ca_certificates_file: Location of CA certificates file. + (default: '') + --dataset_id: Default dataset reference to use for requests (Ignored when not + applicable.). Can be set as "project:dataset" or "dataset". If project is + missing, the value of the project_id flag will be used. + (default: '') + --[no]debug_mode: Show tracebacks on Python exceptions. + (default: 'false') + --[no]disable_ssl_validation: Disables HTTPS certificates validation. This is + off by default. + (default: 'false') + --discovery_file: Filename for JSON document to read for discovery. + (default: '') + --[no]enable_gdrive: When set to true, requests new OAuth token with GDrive + scope. When set to false, requests new OAuth token without GDrive scope. + --[no]fingerprint_job_id: Whether to use a job id that is derived from a + fingerprint of the job configuration. This will prevent the same job from + running multiple times accidentally. + (default: 'false') + --format: : Format for command output. + Options include: + pretty: formatted table output + sparse: simpler table output + prettyjson: easy-to-read JSON format + json: maximally compact JSON + csv: csv format with header + The first three are intended to be human-readable, and the latter three are + for passing to another program. If no format is selected, one will be chosen + based on the command run. + --[no]headless: Whether this bq session is running without user interaction. + This affects behavior that expects user interaction, like whether debug_mode + will break into the debugger and lowers the frequency of informational + printing. + (default: 'false') + --httplib2_debuglevel: Instruct httplib2 to print debugging messages by + setting debuglevel to the given value. + --job_id: A unique job_id to use for the request. If not specified, this + client will generate a job_id. Applies only to commands that launch jobs, + such as cp, extract, load, and query. + --job_property: Additional key-value pairs to include in the properties field + of the job configuration; + repeat this option to specify a list of values + --location: Default geographic location to use when creating datasets or + determining where jobs should run (Ignored when not applicable.) + --max_rows_per_request: Specifies the max number of rows to return per read. + (an integer) + --project_id: Default project to use for requests. + (default: '') + --proxy_address: The name or IP address of the proxy host to use for + connecting to GCP. + (default: '') + --proxy_password: The password to use when authenticating with proxy host. + (default: '') + --proxy_port: The port number to use to connect to the proxy host. + (default: '') + --proxy_username: The user name to use when authenticating with proxy host. + (default: '') + -q,--[no]quiet: If True, ignore status updates while jobs are running. + (default: 'false') + -sync,--[no]synchronous_mode: If True, wait for command completion before + returning, and use the job completion status for error codes. If False, + simply create the job, and use the success of job creation as the error + code. + (default: 'true') + --trace: A tracing token of the form "token:" to include in api + requests. + + google.apputils.app: + -?,--[no]help: show this help + --[no]helpshort: show usage only for this module + --[no]helpxml: like --help, but generates XML output + --[no]run_with_pdb: Set to true for PDB debug mode + (default: 'false') + --[no]run_with_profiling: Set to true for profiling the script. Execution will + be slower, and the output format might change over time. + (default: 'false') + --[no]show_build_data: show build data and exit + --[no]use_cprofile_for_profiling: Use cProfile instead of the profile module + for profiling. This has no effect unless --run_with_profiling is set. + (default: 'true') + + gflags: + --flagfile: Insert flag definitions from the given file into the command line. + (default: '') + --undefok: comma-separated list of flag names that it is okay to specify on + the command line even if the program does not define a flag with that name. + IMPORTANT: flags in this list that have arguments MUST use the --flag=value + format. + (default: '') + + Run 'bq help' to see the list of available commands. + + + +```python +!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv' +``` + + Upload complete. + Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (2s) Current status: DONE + + +## Load data from Google Cloud Storage to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. + + +```python +!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +``` + + Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (1s) Current status: DONE + + +## Run a query + +The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose. + +## Cleaning Up + +The following code deletes the dataset created for this tutorial, including all tables in the dataset. + + +```python +!bq rm -r -f --dataset your_dataset_id +``` diff --git a/notebooks/test/rendered_notebooks/Storage Client Library_output.md b/notebooks/test/rendered_notebooks/Storage Client Library_output.md new file mode 100644 index 00000000000..5e62d56ac52 --- /dev/null +++ b/notebooks/test/rendered_notebooks/Storage Client Library_output.md @@ -0,0 +1,182 @@ + + +```python +%matplotlib inline +``` + + +```python +%load_ext google.cloud.bigquery +``` + +# Google Cloud Storage + +This page shows how to get started with the Google Cloud Storage Python client library. + +## Import the library + + +```python +from google.cloud import storage +``` + +## Projects + +All data in Cloud Storage belongs inside a project. A project consists of a +set of users, a set of APIs, and billing, authentication, and monitoring +settings for those APIs. You can have one project or multiple projects. + +## Clients +Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client. + + +```python +client = storage.Client(project="ajhamilton-scratch") +``` + +## Buckets + +Buckets are the basic containers that hold your data. Everything that you +store in Cloud Storage must be contained in a bucket. You can use buckets to +organize your data and control access to your data. + +### Create a bucket + +When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), +you specify a globally-unique name. + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'test-storage-bucket-1548268970715' + +# Creates the new bucket +bucket = client.create_bucket(bucket_name) + +print('Bucket {} created.'.format(bucket.name)) +``` + + Bucket test-storage-bucket-1548268970715 created. + + +### List buckets in a project + + +```python +buckets = client.list_buckets() + +print("Buckets in {}:".format(client.project)) +for item in buckets: + print("\t" + item.name) +``` + + Buckets in ajhamilton-scratch: + ajhamilton-scratch + my-new-bucket-1548180688764 + my-new-bucket-1548208228513 + test-storage-bucket-1548209987490 + test-storage-bucket-1548268970715 + + +### Get a bucket + + +```python +bucket = client.get_bucket(bucket_name) +``` + +## Objects + +Objects are the individual pieces of data that you store in Cloud Storage. +There is no limit on the number of objects that you can create in a bucket. + +### Upload a local file to a bucket + + +```python +blob_name = 'us-states.txt' +blob = bucket.blob(blob_name) + +source_file_name = 'resources/us-states.txt' +blob.upload_from_filename(source_file_name) + +print('File uploaded to {}.'.format(bucket.name)) +``` + + File uploaded to test-storage-bucket-1548268970715. + + +### List blobs in a bucket + + +```python +blobs = bucket.list_blobs() + +print("Blobs in {}:".format(bucket.name)) +for item in blobs: + print("\t" + item.name) +``` + + Blobs in test-storage-bucket-1548268970715: + us-states.txt + + +### Get a blob and display metadata +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +blob = bucket.get_blob(blob_name) + +print('Select metadata for blob {}:'.format(blob_name)) +print('\tID: {}'.format(blob.id)) +print('\tSize: {} bytes'.format(blob.size)) +print('\tUpdated: {}'.format(blob.updated)) +``` + + Select metadata for blob us-states.txt: + ID: test-storage-bucket-1548268970715/us-states.txt/1548268974850839 + Size: 637 bytes + Updated: 2019-01-23 18:42:54.850000+00:00 + + +### Download a blob to a local directory + + +```python +output_file_name = 'resources/downloaded-us-states.txt' +blob.download_to_filename(output_file_name) + +print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) +``` + + Downloaded blob us-states.txt to resources/downloaded-us-states.txt. + + +## Cleaning up + +### Delete a blob + + +```python +blob = client.get_bucket(bucket_name).get_blob(blob_name) +blob.delete() + +print('Blob {} deleted.'.format(blob.name)) +``` + + Blob us-states.txt deleted. + + +### Delete a bucket + + +```python +bucket = client.get_bucket(bucket_name) +bucket.delete() + +print('Bucket {} deleted.'.format(bucket.name)) +``` + + Bucket test-storage-bucket-1548268970715 deleted. + diff --git a/notebooks/test/rendered_notebooks/Storage Commands_output.md b/notebooks/test/rendered_notebooks/Storage Commands_output.md new file mode 100644 index 00000000000..df3a91a6c2b --- /dev/null +++ b/notebooks/test/rendered_notebooks/Storage Commands_output.md @@ -0,0 +1,247 @@ + + +```python +%matplotlib inline +``` + + +```python +%load_ext google.cloud.bigquery +``` + +# Storage Commands + +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. + +This notebook introduces several `gsutil` commands for interacting with Cloud Storage. + +## List available commands + +The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: + + +```python +!gsutil help +``` + + Usage: gsutil [-D] [-DD] [-h header]... [-m] [-o] [-q] [command [opts...] args...] + Available commands: + acl Get, set, or change bucket and/or object ACLs + cat Concatenate object content to stdout + compose Concatenate a sequence of objects into a new composite object. + config Obtain credentials and create configuration file + cors Get or set a CORS JSON document for one or more buckets + cp Copy files and objects + defacl Get, set, or change default ACL on buckets + defstorageclass Get or set the default storage class on buckets + du Display object size usage + hash Calculate file hashes + help Get help about commands and topics + iam Get, set, or change bucket and/or object IAM permissions. + kms Configure Cloud KMS encryption + label Get, set, or change the label configuration of a bucket. + lifecycle Get or set lifecycle configuration for a bucket + logging Configure or retrieve logging on buckets + ls List providers, buckets, or objects + mb Make buckets + mv Move/rename objects and/or subdirectories + notification Configure object change notification + perfdiag Run performance diagnostic + rb Remove buckets + requesterpays Enable or disable requester pays for one or more buckets + retention Provides utilities to interact with Retention Policy feature. + rewrite Rewrite objects + rm Remove objects + rsync Synchronize content of two buckets/directories + setmeta Set metadata on already uploaded objects + signurl Create a signed url + stat Display object status + test Run gsutil unit/integration tests (for developers) + update Update to the latest gsutil release + version Print version info about gsutil + versioning Enable or suspend versioning for one or more buckets + web Set a main page and/or error page for one or more buckets + + Additional help topics: + acls Working With Access Control Lists + anon Accessing Public Data Without Credentials + apis Cloud Storage APIs + crc32c CRC32C and Installing crcmod + creds Credential Types Supporting Various Use Cases + dev Contributing Code to gsutil + encoding Filename encoding and interoperability problems + encryption Using Encryption Keys + metadata Working With Object Metadata + naming Object and Bucket Naming + options Top-Level Command-Line Options + prod Scripting Production Transfers + projects Working With Projects + retries Retry Handling Strategy + security Security and Privacy Considerations + subdirs How Subdirectories Work + support Google Cloud Storage Support + throttling Throttling gsutil + versions Object Versioning and Concurrency Control + wildcards Wildcard Names + + Use gsutil help for detailed help. + +## Buckets + +Buckets are the basic containers that hold your data. Everything that you +store in Cloud Storage must be contained in a bucket. You can use buckets to +organize your data and control access to your data. + +### Create a bucket + +When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), +you specify a globally-unique name. + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'test-storage-bucket-1548268945185' +``` + +NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. + + +```python +!gsutil mb gs://{bucket_name}/ +``` + + Creating gs://test-storage-bucket-1548268945185/... + + +### List buckets in a project + +Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. + + +```python +!gsutil ls -p ajhamilton-scratch +``` + + gs://ajhamilton-scratch/ + gs://my-new-bucket-1548180688764/ + gs://my-new-bucket-1548208228513/ + gs://test-storage-bucket-1548209987490/ + gs://test-storage-bucket-1548268945185/ + + +## Objects + +Objects are the individual pieces of data that you store in Cloud Storage. +There is no limit on the number of objects that you can create in a bucket. + +### Upload a local file to a bucket + + +```python +!gsutil cp resources/us-states.txt gs://{bucket_name}/ +``` + + Copying file://resources/us-states.txt [Content-Type=text/plain]... + + Operation completed over 1 objects/637.0 B. + + +### List blobs in a bucket + + +```python +!gsutil ls -r gs://{bucket_name}/** +``` + + gs://test-storage-bucket-1548268945185/us-states.txt + + +### Get a blob and display metadata +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +!gsutil ls -L gs://{bucket_name}/us-states.txt +``` + + gs://test-storage-bucket-1548268945185/us-states.txt: + Creation time: Wed, 23 Jan 2019 18:42:37 GMT + Update time: Wed, 23 Jan 2019 18:42:37 GMT + Storage class: STANDARD + Content-Language: en + Content-Length: 637 + Content-Type: text/plain + Hash (crc32c): AmYMRQ== + Hash (md5): NmfddAHdCzyvAHCifeGtwg== + ETag: CIKl+anHhOACEAE= + Generation: 1548268957749890 + Metageneration: 1 + ACL: [ + { + "entity": "project-owners-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "owners" + }, + "role": "OWNER" + }, + { + "entity": "project-editors-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "editors" + }, + "role": "OWNER" + }, + { + "entity": "project-viewers-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "viewers" + }, + "role": "READER" + }, + { + "email": "ajhamilton@google.com", + "entity": "user-ajhamilton@google.com", + "role": "OWNER" + } + ] + TOTAL: 1 objects, 637 bytes (637 B) + + +### Download a blob to a local directory + + +```python +!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt +``` + + Copying gs://test-storage-bucket-1548268945185/us-states.txt... + + Operation completed over 1 objects/637.0 B. + + +## Cleaning up + +### Delete a blob + + +```python +!gsutil rm gs://{bucket_name}/us-states.txt +``` + + Removing gs://test-storage-bucket-1548268945185/us-states.txt... + + Operation completed over 1 objects. + + +### Delete a bucket + + +```python +!gsutil rm -r gs://{bucket_name}/ +``` + + Removing gs://test-storage-bucket-1548268945185/... + diff --git a/notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md b/notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md new file mode 100644 index 00000000000..e339c5d9a08 --- /dev/null +++ b/notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md @@ -0,0 +1,524 @@ + + +```python +%matplotlib inline +``` + + +```python +%load_ext google.cloud.bigquery +``` + +# Vizualizing BigQuery Data in a Jupyter Notebook + +[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. + +Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and Pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. + +## Using Jupyter Magics to Query BigQuery Data + +The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. + +The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. + + +```python +%%bigquery +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
+
+ + + +The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. + + +```python +%%bigquery total_births +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
+
+ + + +The next cell uses the Pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [Pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with Pandas. + + +```python +total_births.plot(kind='bar', x='year', y='birth_count'); +``` + + +![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_8_0.png) + + +Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. + + +```python +%%bigquery births_by_weekday +SELECT + wday, + SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, + SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births +FROM `bigquery-public-data.samples.natality` +WHERE wday IS NOT NULL +GROUP BY wday +ORDER BY wday ASC +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
wdaymale_birthsfemale_births
0142935754093357
1260958405831111
2367272176412155
3466187296307782
4565830156284434
5665186366223584
6747619504530052
+
+ + + +Visualize the query results using a line chart. + + +```python +births_by_weekday.plot(x='wday'); +``` + + +![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_12_0.png) + + +## Using Python to Query BigQuery Data + +Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a Pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with Pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. + +To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. + + +```python +from google.cloud import bigquery + +client = bigquery.Client() +``` + +Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). + + +```python +sql = """ +SELECT + plurality, + COUNT(1) AS count, + year +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(plurality) AND plurality > 1 +GROUP BY + plurality, year +ORDER BY + count DESC +""" +df = client.query(sql).to_dataframe() +df.head() +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
pluralitycountyear
021392092007
121388662008
221372392006
321332852005
421323442004
+
+ + + +To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. + + +```python +pivot_table = df.pivot(index='year', columns='plurality', values='count') +pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); +``` + + +![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_18_0.png) + + +Run the following query to retrieve the count of births by the number of gestation weeks. + + +```python +sql = """ +SELECT + gestation_weeks, + COUNT(1) AS count +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 +GROUP BY + gestation_weeks +ORDER BY + gestation_weeks +""" +df = client.query(sql).to_dataframe() +``` + +Finally, chart the query results in your DataFrame. + + +```python +ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) +ax.set_title('Count of Births by Gestation Weeks') +ax.set_xlabel('Gestation Weeks') +ax.set_ylabel('Count'); +``` + + +![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_22_0.png) + + +### What's Next + ++ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. + ++ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). From a0c7958e7943bdb59731594658355187085c7bf6 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Thu, 24 Jan 2019 09:05:59 -0800 Subject: [PATCH 03/24] ignore executed notebooks and save executed and unexecuted rendered copies --- .gitignore | 1 + .../executed/BigQuery Basics.md} | 299 +++---- .../executed/BigQuery Query Magic.md} | 24 +- .../executed/BigQuery Shell Commands.md} | 16 +- .../executed/Storage Client Library.md} | 32 +- .../executed/Storage Commands.md} | 38 +- .../Visualize BigQuery Public Data.md} | 26 +- .../Visualize BigQuery Public Data_10_0.png | Bin 0 -> 15605 bytes .../Visualize BigQuery Public Data_16_0.png | Bin 0 -> 13836 bytes .../Visualize BigQuery Public Data_20_0.png | Bin 0 -> 12721 bytes .../Visualize BigQuery Public Data_6_0.png | Bin 0 -> 7378 bytes .../rendered/unexecuted/BigQuery Basics.md | 215 +++++ .../unexecuted/BigQuery Query Magic.md | 96 ++ .../unexecuted/BigQuery Shell Commands.md | 60 ++ .../unexecuted/Storage Client Library.md | 139 +++ .../rendered/unexecuted/Storage Commands.md | 98 +++ .../Visualize BigQuery Public Data.md | 146 ++++ .../BigQuery Basics_output.ipynb | 615 ------------- .../BigQuery Query Magic_output.ipynb | 818 ------------------ .../BigQuery Shell Commands_output.ipynb | 809 ----------------- .../Storage Client Library_output.ipynb | 391 --------- .../Storage Commands_output.ipynb | 468 ---------- ...isualize BigQuery Public Data_output.ipynb | 763 ---------------- .../tutorials/bigquery/BigQuery Basics.ipynb | 153 ++-- .../bigquery/BigQuery Query Magic.ipynb | 6 +- .../Visualize BigQuery Public Data.ipynb | 8 +- .../storage/Storage Client Library.ipynb | 2 +- .../tutorials/storage/Storage Commands.ipynb | 2 +- 28 files changed, 1019 insertions(+), 4206 deletions(-) rename notebooks/{test/rendered_notebooks/BigQuery Basics_output.md => rendered/executed/BigQuery Basics.md} (88%) rename notebooks/{test/rendered_notebooks/BigQuery Query Magic_output.md => rendered/executed/BigQuery Query Magic.md} (96%) rename notebooks/{test/rendered_notebooks/BigQuery Shell Commands_output.md => rendered/executed/BigQuery Shell Commands.md} (97%) rename notebooks/{test/rendered_notebooks/Storage Client Library_output.md => rendered/executed/Storage Client Library.md} (84%) rename notebooks/{test/rendered_notebooks/Storage Commands_output.md => rendered/executed/Storage Commands.md} (88%) rename notebooks/{test/rendered_notebooks/Visualize BigQuery Public Data_output.md => rendered/executed/Visualize BigQuery Public Data.md} (91%) create mode 100644 notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_10_0.png create mode 100644 notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_16_0.png create mode 100644 notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_20_0.png create mode 100644 notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_6_0.png create mode 100644 notebooks/rendered/unexecuted/BigQuery Basics.md create mode 100644 notebooks/rendered/unexecuted/BigQuery Query Magic.md create mode 100644 notebooks/rendered/unexecuted/BigQuery Shell Commands.md create mode 100644 notebooks/rendered/unexecuted/Storage Client Library.md create mode 100644 notebooks/rendered/unexecuted/Storage Commands.md create mode 100644 notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md delete mode 100644 notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb delete mode 100644 notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb delete mode 100644 notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb delete mode 100644 notebooks/test/executed_notebooks/Storage Client Library_output.ipynb delete mode 100644 notebooks/test/executed_notebooks/Storage Commands_output.ipynb delete mode 100644 notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb diff --git a/.gitignore b/.gitignore index 0cf723b8750..08a370acb39 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .tox .pytest_cache .ipynb_checkpoints +.executed_notebooks coverage.xml python-docs-samples.json service-account.json diff --git a/notebooks/test/rendered_notebooks/BigQuery Basics_output.md b/notebooks/rendered/executed/BigQuery Basics.md similarity index 88% rename from notebooks/test/rendered_notebooks/BigQuery Basics_output.md rename to notebooks/rendered/executed/BigQuery Basics.md index 6816db06513..3f518c502b3 100644 --- a/notebooks/test/rendered_notebooks/BigQuery Basics_output.md +++ b/notebooks/rendered/executed/BigQuery Basics.md @@ -1,14 +1,4 @@ - -```python -%matplotlib inline -``` - - -```python -%load_ext google.cloud.bigquery -``` - # BigQuery Basics [BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library. @@ -25,16 +15,18 @@ import pandas To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. +Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables. + ```python -client = bigquery.Client() +client = bigquery.Client(location="US") ``` ## Run a query on a public dataset The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. -Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). +Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). ```python @@ -124,151 +116,6 @@ df -## Create a new dataset - -A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). - - -```python -import time - -# Define a name for the new dataset. -dataset_id = 'test_dataset_1548268897503' - -# Create a DatasetReference using a chosen dataset ID. -# The project defaults to the Client's project if not specified. -dataset_ref = client.dataset(dataset_id) - -# Construct a full Dataset object to send to the API. -dataset = bigquery.Dataset(dataset_ref) -# Specify the geographic location where the dataset should reside. -dataset.location = 'US' - -# Send the dataset to the API for creation. -dataset = client.create_dataset(dataset) # API request -``` - -## Load data from a Pandas DataFrame to a new table - - -```python -records = [ - {"title": "The Meaning of Life", "release_year": 1983}, - {"title": "Monty Python and the Holy Grail", "release_year": 1975}, - {"title": "Life of Brian", "release_year": 1979}, - {"title": "And Now for Something Completely Different", "release_year": 1971}, -] - -# Optionally set explicit indices. -# If indices are not specified, a column will be created for the default -# indices created by pandas. -index = ["Q24980", "Q25043", "Q24953", "Q16403"] -df = pandas.DataFrame(records, index=pandas.Index(index, name="wikidata_id")) - -table_ref = dataset_ref.table("monty_python") -job = client.load_table_from_dataframe(df, table_ref, location="US") - -job.result() # Waits for table load to complete. -print("Loaded dataframe to {}".format(table_ref.path)) -``` - - Loaded dataframe to /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/monty_python - - -## Load query results to a table - -For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. - - -```python -sql = """ - SELECT corpus - FROM `bigquery-public-data.samples.shakespeare` - GROUP BY corpus; -""" -table_ref = dataset.table("your_new_table_id") -job_config = bigquery.QueryJobConfig( - destination=table_ref -) - -# Start the query, passing in the extra configuration. -query_job = client.query(sql, location="US", job_config=job_config) - -query_job.result() # Waits for the query to finish -print("Query results loaded to table {}".format(table_ref.path)) -``` - - Query results loaded to table /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/your_new_table_id - - -## Load data from a local file to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. - - -```python -source_filename = 'resources/us-states.csv' - -table_ref = dataset_ref.table('us_states_from_local_file') -job_config = bigquery.LoadJobConfig( - source_format=bigquery.SourceFormat.CSV, - skip_leading_rows=1, - autodetect=True -) - -with open(source_filename, 'rb') as source_file: - job = client.load_table_from_file( - source_file, - table_ref, - location='US', # Must match the destination dataset location. - job_config=job_config) # API request - -job.result() # Waits for table load to complete. - -print('Loaded {} rows into {}:{}.'.format( - job.output_rows, dataset_id, table_ref.path)) -``` - - Loaded 50 rows into test_dataset_1548268897503:/projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/us_states_from_local_file. - - -## Load data from Google Cloud Storage to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. - - -```python -# Configure the load job -job_config = bigquery.LoadJobConfig( - schema=[ - bigquery.SchemaField('name', 'STRING'), - bigquery.SchemaField('post_abbr', 'STRING') - ], - skip_leading_rows=1, - # The source format defaults to CSV, so the line below is optional. - source_format=bigquery.SourceFormat.CSV -) -uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' -destination_table_ref = dataset.table('us_states_from_gcs') - -# Start the load job -load_job = client.load_table_from_uri( - uri, destination_table_ref, job_config=job_config) -print('Starting job {}'.format(load_job.job_id)) - -load_job.result() # Waits for table load to complete. -print('Job finished.') - -# Retreive the destination table -destination_table = client.get_table(table_ref) -print('Loaded {} rows.'.format(destination_table.num_rows)) -``` - - Starting job f65c1470-3e8b-4b0f-8a44-ff6a3f5cbaf0 - Job finished. - Loaded 50 rows. - - ## Run a parameterized query BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query. @@ -299,7 +146,7 @@ job_config = bigquery.QueryJobConfig( # Start the query job query_job = client.query(sql, location="US", job_config=job_config) -# Return the results as a Pandas DataFrame +# Return the results as a pandas DataFrame query_job.to_dataframe() ``` @@ -395,6 +242,140 @@ query_job.to_dataframe() +## Create a new dataset + +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). + + +```python +# Define a name for the new dataset. +dataset_id = 'your_new_dataset' + +# The project defaults to the Client's project if not specified. +dataset = client.create_dataset(dataset_id) # API request +``` + +## Write query results to a destination table + +For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. + + +```python +sql = """ + SELECT corpus + FROM `bigquery-public-data.samples.shakespeare` + GROUP BY corpus; +""" +table_ref = dataset.table("your_new_table_id") +job_config = bigquery.QueryJobConfig( + destination=table_ref +) + +# Start the query, passing in the extra configuration. +query_job = client.query(sql, location="US", job_config=job_config) + +query_job.result() # Waits for the query to finish +print("Query results loaded to table {}".format(table_ref.path)) +``` + + Query results loaded to table /projects/your-project-id/datasets/your_new_dataset/tables/your_new_table_id + + +## Load data from a pandas DataFrame to a new table + + +```python +records = [ + {"title": "The Meaning of Life", "release_year": 1983}, + {"title": "Monty Python and the Holy Grail", "release_year": 1975}, + {"title": "Life of Brian", "release_year": 1979}, + {"title": "And Now for Something Completely Different", "release_year": 1971}, +] + +# Optionally set explicit indices. +# If indices are not specified, a column will be created for the default +# indices created by pandas. +index = ["Q24980", "Q25043", "Q24953", "Q16403"] +df = pandas.DataFrame(records, index=pandas.Index(index, name="wikidata_id")) + +table_ref = dataset.table("monty_python") +job = client.load_table_from_dataframe(df, table_ref, location="US") + +job.result() # Waits for table load to complete. +print("Loaded dataframe to {}".format(table_ref.path)) +``` + + Loaded dataframe to /projects/your-project-id/datasets/your_new_dataset/tables/monty_python + + +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + + +```python +source_filename = 'resources/us-states.csv' + +table_ref = dataset.table('us_states_from_local_file') +job_config = bigquery.LoadJobConfig( + source_format=bigquery.SourceFormat.CSV, + skip_leading_rows=1, + autodetect=True +) + +with open(source_filename, 'rb') as source_file: + job = client.load_table_from_file( + source_file, + table_ref, + location='US', # Must match the destination dataset location. + job_config=job_config) # API request + +job.result() # Waits for table load to complete. + +print('Loaded {} rows into {}:{}.'.format( + job.output_rows, dataset_id, table_ref.path)) +``` + + Loaded 50 rows into your_new_dataset:/projects/your-project-id/datasets/your_new_dataset/tables/us_states_from_local_file. + + +## Load data from Google Cloud Storage to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. + + +```python +# Configure the load job +job_config = bigquery.LoadJobConfig( + schema=[ + bigquery.SchemaField('name', 'STRING'), + bigquery.SchemaField('post_abbr', 'STRING') + ], + skip_leading_rows=1, + # The source format defaults to CSV, so the line below is optional. + source_format=bigquery.SourceFormat.CSV +) +uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +destination_table_ref = dataset.table('us_states_from_gcs') + +# Start the load job +load_job = client.load_table_from_uri( + uri, destination_table_ref, job_config=job_config) +print('Starting job {}'.format(load_job.job_id)) + +load_job.result() # Waits for table load to complete. +print('Job finished.') + +# Retreive the destination table +destination_table = client.get_table(table_ref) +print('Loaded {} rows.'.format(destination_table.num_rows)) +``` + + Starting job 4c081f09-7351-4d0a-a5bd-90b6ce36371b + Job finished. + Loaded 50 rows. + + ## Cleaning Up The following code deletes the dataset created for this tutorial, including all tables in the dataset. @@ -410,5 +391,5 @@ client.delete_dataset(dataset, delete_contents=True) print('Deleted dataset: {}'.format(dataset.path)) ``` - Deleted dataset: /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503 + Deleted dataset: /projects/your-project-id/datasets/your_new_dataset diff --git a/notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md b/notebooks/rendered/executed/BigQuery Query Magic.md similarity index 96% rename from notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md rename to notebooks/rendered/executed/BigQuery Query Magic.md index 8d1ae3b6154..9527df7d224 100644 --- a/notebooks/test/rendered_notebooks/BigQuery Query Magic_output.md +++ b/notebooks/rendered/executed/BigQuery Query Magic.md @@ -1,23 +1,13 @@ - -```python -%matplotlib inline -``` - - -```python -%load_ext google.cloud.bigquery -``` - # BigQuery Query Magic -Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. +Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. ## Run a query on a public dataset The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. -The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). +The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). ```python @@ -125,9 +115,9 @@ ORDER BY count DESC LIMIT 10 ``` - Executing query with job ID: 791c0804-adf8-432a-8618-dab212848f03 - Query executing: 0.48s - Query complete after 0.93s + Executing query with job ID: 3f302a57-daa8-41ca-9e01-7fc364b69cae + Query executing: 2.44s + Query complete after 3.04s @@ -218,12 +208,12 @@ By default, the `%%bigquery` magic command uses the project associated with your ```python -project_id = 'my-project-id' +project_id = 'your-project-id' ``` ```python -project_id = 'ajhamilton-scratch' +project_id = 'your-project-id' ``` diff --git a/notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md b/notebooks/rendered/executed/BigQuery Shell Commands.md similarity index 97% rename from notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md rename to notebooks/rendered/executed/BigQuery Shell Commands.md index 74bee8a29b9..15d82b9d2b3 100644 --- a/notebooks/test/rendered_notebooks/BigQuery Shell Commands_output.md +++ b/notebooks/rendered/executed/BigQuery Shell Commands.md @@ -1,14 +1,4 @@ - -```python -%matplotlib inline -``` - - -```python -%load_ext google.cloud.bigquery -``` - # BigQuery command-line tool The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`. @@ -336,7 +326,7 @@ The example below creates a new dataset in the US named "your_new_dataset". !bq --location=US mk --dataset "your_dataset_id" ``` - Dataset 'ajhamilton-scratch:your_dataset_id' successfully created. + Dataset 'your-project-id:your_dataset_id' successfully created. ## Load data from a local file to a table @@ -609,7 +599,7 @@ The example below demonstrates how to load a local CSV file into a new or existi ``` Upload complete. - Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (2s) Current status: DONE + Waiting on bqjob_r42e105decd46e2a1_0000016880baeb55_1 ... (0s) Current status: DONE ## Load data from Google Cloud Storage to a table @@ -621,7 +611,7 @@ The example below demonstrates how to load a local CSV file into a new or existi !bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' ``` - Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (1s) Current status: DONE + Waiting on bqjob_r52ccf09d3eb8c617_0000016880bb0711_1 ... (2s) Current status: DONE ## Run a query diff --git a/notebooks/test/rendered_notebooks/Storage Client Library_output.md b/notebooks/rendered/executed/Storage Client Library.md similarity index 84% rename from notebooks/test/rendered_notebooks/Storage Client Library_output.md rename to notebooks/rendered/executed/Storage Client Library.md index 5e62d56ac52..df819ed9f4f 100644 --- a/notebooks/test/rendered_notebooks/Storage Client Library_output.md +++ b/notebooks/rendered/executed/Storage Client Library.md @@ -1,14 +1,4 @@ - -```python -%matplotlib inline -``` - - -```python -%load_ext google.cloud.bigquery -``` - # Google Cloud Storage This page shows how to get started with the Google Cloud Storage Python client library. @@ -31,7 +21,7 @@ Start by initializing a client, which is used to interact with the Google Cloud ```python -client = storage.Client(project="ajhamilton-scratch") +client = storage.Client(project="your-project-id") ``` ## Buckets @@ -48,7 +38,7 @@ you specify a globally-unique name. ```python # Replace the string below with a unique name for the new bucket -bucket_name = 'test-storage-bucket-1548268970715' +bucket_name = 'your-new-bucket' # Creates the new bucket bucket = client.create_bucket(bucket_name) @@ -56,7 +46,7 @@ bucket = client.create_bucket(bucket_name) print('Bucket {} created.'.format(bucket.name)) ``` - Bucket test-storage-bucket-1548268970715 created. + Bucket your-new-bucket created. ### List buckets in a project @@ -70,12 +60,12 @@ for item in buckets: print("\t" + item.name) ``` - Buckets in ajhamilton-scratch: - ajhamilton-scratch + Buckets in your-project-id: + your-project-id my-new-bucket-1548180688764 my-new-bucket-1548208228513 test-storage-bucket-1548209987490 - test-storage-bucket-1548268970715 + your-new-bucket ### Get a bucket @@ -103,7 +93,7 @@ blob.upload_from_filename(source_file_name) print('File uploaded to {}.'.format(bucket.name)) ``` - File uploaded to test-storage-bucket-1548268970715. + File uploaded to your-new-bucket. ### List blobs in a bucket @@ -117,7 +107,7 @@ for item in blobs: print("\t" + item.name) ``` - Blobs in test-storage-bucket-1548268970715: + Blobs in your-new-bucket: us-states.txt @@ -135,9 +125,9 @@ print('\tUpdated: {}'.format(blob.updated)) ``` Select metadata for blob us-states.txt: - ID: test-storage-bucket-1548268970715/us-states.txt/1548268974850839 + ID: your-new-bucket/us-states.txt/1548348088257223 Size: 637 bytes - Updated: 2019-01-23 18:42:54.850000+00:00 + Updated: 2019-01-24 16:41:28.256000+00:00 ### Download a blob to a local directory @@ -178,5 +168,5 @@ bucket.delete() print('Bucket {} deleted.'.format(bucket.name)) ``` - Bucket test-storage-bucket-1548268970715 deleted. + Bucket your-new-bucket deleted. diff --git a/notebooks/test/rendered_notebooks/Storage Commands_output.md b/notebooks/rendered/executed/Storage Commands.md similarity index 88% rename from notebooks/test/rendered_notebooks/Storage Commands_output.md rename to notebooks/rendered/executed/Storage Commands.md index df3a91a6c2b..7ba4de6ac32 100644 --- a/notebooks/test/rendered_notebooks/Storage Commands_output.md +++ b/notebooks/rendered/executed/Storage Commands.md @@ -1,14 +1,4 @@ - -```python -%matplotlib inline -``` - - -```python -%load_ext google.cloud.bigquery -``` - # Storage Commands The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. @@ -100,7 +90,7 @@ you specify a globally-unique name. ```python # Replace the string below with a unique name for the new bucket -bucket_name = 'test-storage-bucket-1548268945185' +bucket_name = 'your-new-bucket' ``` NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. @@ -110,7 +100,7 @@ NOTE: In the examples below, the variables are referenced in the command using ` !gsutil mb gs://{bucket_name}/ ``` - Creating gs://test-storage-bucket-1548268945185/... + Creating gs://your-new-bucket/... ### List buckets in a project @@ -119,14 +109,14 @@ Replace 'your-project-id' in the cell below with your project ID and run the cel ```python -!gsutil ls -p ajhamilton-scratch +!gsutil ls -p your-project-id ``` - gs://ajhamilton-scratch/ + gs://your-project-id/ gs://my-new-bucket-1548180688764/ gs://my-new-bucket-1548208228513/ gs://test-storage-bucket-1548209987490/ - gs://test-storage-bucket-1548268945185/ + gs://your-new-bucket/ ## Objects @@ -153,7 +143,7 @@ There is no limit on the number of objects that you can create in a bucket. !gsutil ls -r gs://{bucket_name}/** ``` - gs://test-storage-bucket-1548268945185/us-states.txt + gs://your-new-bucket/us-states.txt ### Get a blob and display metadata @@ -164,17 +154,17 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada !gsutil ls -L gs://{bucket_name}/us-states.txt ``` - gs://test-storage-bucket-1548268945185/us-states.txt: - Creation time: Wed, 23 Jan 2019 18:42:37 GMT - Update time: Wed, 23 Jan 2019 18:42:37 GMT + gs://your-new-bucket/us-states.txt: + Creation time: Thu, 24 Jan 2019 16:40:54 GMT + Update time: Thu, 24 Jan 2019 16:40:54 GMT Storage class: STANDARD Content-Language: en Content-Length: 637 Content-Type: text/plain Hash (crc32c): AmYMRQ== Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CIKl+anHhOACEAE= - Generation: 1548268957749890 + ETag: CO63hf7thuACEAE= + Generation: 1548348054133742 Metageneration: 1 ACL: [ { @@ -217,7 +207,7 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada !gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt ``` - Copying gs://test-storage-bucket-1548268945185/us-states.txt... + Copying gs://your-new-bucket/us-states.txt... Operation completed over 1 objects/637.0 B. @@ -231,7 +221,7 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada !gsutil rm gs://{bucket_name}/us-states.txt ``` - Removing gs://test-storage-bucket-1548268945185/us-states.txt... + Removing gs://your-new-bucket/us-states.txt... Operation completed over 1 objects. @@ -243,5 +233,5 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada !gsutil rm -r gs://{bucket_name}/ ``` - Removing gs://test-storage-bucket-1548268945185/... + Removing gs://your-new-bucket/... diff --git a/notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md b/notebooks/rendered/executed/Visualize BigQuery Public Data.md similarity index 91% rename from notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md rename to notebooks/rendered/executed/Visualize BigQuery Public Data.md index e339c5d9a08..da41e68c022 100644 --- a/notebooks/test/rendered_notebooks/Visualize BigQuery Public Data_output.md +++ b/notebooks/rendered/executed/Visualize BigQuery Public Data.md @@ -1,25 +1,15 @@ - -```python -%matplotlib inline -``` - - -```python -%load_ext google.cloud.bigquery -``` - # Vizualizing BigQuery Data in a Jupyter Notebook [BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. -Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and Pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. +Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. ## Using Jupyter Magics to Query BigQuery Data The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. -The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. +The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. ```python @@ -261,7 +251,7 @@ LIMIT 15 -The next cell uses the Pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [Pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with Pandas. +The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. ```python @@ -269,7 +259,7 @@ total_births.plot(kind='bar', x='year', y='birth_count'); ``` -![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_8_0.png) +![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_6_0.png) Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. @@ -370,12 +360,12 @@ births_by_weekday.plot(x='wday'); ``` -![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_12_0.png) +![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_10_0.png) ## Using Python to Query BigQuery Data -Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a Pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with Pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. +Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. @@ -480,7 +470,7 @@ pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); ``` -![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_18_0.png) +![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_16_0.png) Run the following query to retrieve the count of births by the number of gestation weeks. @@ -514,7 +504,7 @@ ax.set_ylabel('Count'); ``` -![png](Visualize%20BigQuery%20Public%20Data_output_files/Visualize%20BigQuery%20Public%20Data_output_22_0.png) +![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_20_0.png) ### What's Next diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_10_0.png b/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_10_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f844443cd7cbb8c0051a2f7adb068d85c2edd6e7 GIT binary patch literal 15605 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 LijdORMuGniR-C7w literal 0 HcmV?d00001 diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_16_0.png b/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_16_0.png new file mode 100644 index 0000000000000000000000000000000000000000..a2fe7be8157f3c42c3f958c052cd41b5342dfdec GIT binary patch literal 13836 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 Mz;9~4jym#x01<_zn*aa+ literal 0 HcmV?d00001 diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_6_0.png b/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_6_0.png new file mode 100644 index 0000000000000000000000000000000000000000..120d3e2e5082dcd44533e0dd37f57bfbd900d44c GIT binary patch literal 7378 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 M(jHm%v+pne4= @min_word_count + ORDER BY word_count DESC; +""" + +# Define the parameter values in a query job configuration +job_config = bigquery.QueryJobConfig( + query_parameters=[ + bigquery.ScalarQueryParameter("corpus", "STRING", "romeoandjuliet"), + bigquery.ScalarQueryParameter("min_word_count", "INT64", 250), + ] +) + +# Start the query job +query_job = client.query(sql, location="US", job_config=job_config) + +# Return the results as a pandas DataFrame +query_job.to_dataframe() +``` + +## Create a new dataset + +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). + + +```python +# Define a name for the new dataset. +dataset_id = 'your_new_dataset' + +# The project defaults to the Client's project if not specified. +dataset = client.create_dataset(dataset_id) # API request +``` + +## Write query results to a destination table + +For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. + + +```python +sql = """ + SELECT corpus + FROM `bigquery-public-data.samples.shakespeare` + GROUP BY corpus; +""" +table_ref = dataset.table("your_new_table_id") +job_config = bigquery.QueryJobConfig( + destination=table_ref +) + +# Start the query, passing in the extra configuration. +query_job = client.query(sql, location="US", job_config=job_config) + +query_job.result() # Waits for the query to finish +print("Query results loaded to table {}".format(table_ref.path)) +``` + +## Load data from a pandas DataFrame to a new table + + +```python +records = [ + {"title": "The Meaning of Life", "release_year": 1983}, + {"title": "Monty Python and the Holy Grail", "release_year": 1975}, + {"title": "Life of Brian", "release_year": 1979}, + {"title": "And Now for Something Completely Different", "release_year": 1971}, +] + +# Optionally set explicit indices. +# If indices are not specified, a column will be created for the default +# indices created by pandas. +index = ["Q24980", "Q25043", "Q24953", "Q16403"] +df = pandas.DataFrame(records, index=pandas.Index(index, name="wikidata_id")) + +table_ref = dataset.table("monty_python") +job = client.load_table_from_dataframe(df, table_ref, location="US") + +job.result() # Waits for table load to complete. +print("Loaded dataframe to {}".format(table_ref.path)) +``` + +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + + +```python +source_filename = 'resources/us-states.csv' + +table_ref = dataset.table('us_states_from_local_file') +job_config = bigquery.LoadJobConfig( + source_format=bigquery.SourceFormat.CSV, + skip_leading_rows=1, + autodetect=True +) + +with open(source_filename, 'rb') as source_file: + job = client.load_table_from_file( + source_file, + table_ref, + location='US', # Must match the destination dataset location. + job_config=job_config) # API request + +job.result() # Waits for table load to complete. + +print('Loaded {} rows into {}:{}.'.format( + job.output_rows, dataset_id, table_ref.path)) +``` + +## Load data from Google Cloud Storage to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. + + +```python +# Configure the load job +job_config = bigquery.LoadJobConfig( + schema=[ + bigquery.SchemaField('name', 'STRING'), + bigquery.SchemaField('post_abbr', 'STRING') + ], + skip_leading_rows=1, + # The source format defaults to CSV, so the line below is optional. + source_format=bigquery.SourceFormat.CSV +) +uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +destination_table_ref = dataset.table('us_states_from_gcs') + +# Start the load job +load_job = client.load_table_from_uri( + uri, destination_table_ref, job_config=job_config) +print('Starting job {}'.format(load_job.job_id)) + +load_job.result() # Waits for table load to complete. +print('Job finished.') + +# Retreive the destination table +destination_table = client.get_table(table_ref) +print('Loaded {} rows.'.format(destination_table.num_rows)) +``` + +## Cleaning Up + +The following code deletes the dataset created for this tutorial, including all tables in the dataset. + + +```python +# Retrieve the dataset from the API +dataset = client.get_dataset(client.dataset(dataset_id)) + +# Delete the dataset and its contents +client.delete_dataset(dataset, delete_contents=True) + +print('Deleted dataset: {}'.format(dataset.path)) +``` diff --git a/notebooks/rendered/unexecuted/BigQuery Query Magic.md b/notebooks/rendered/unexecuted/BigQuery Query Magic.md new file mode 100644 index 00000000000..afe92c911f0 --- /dev/null +++ b/notebooks/rendered/unexecuted/BigQuery Query Magic.md @@ -0,0 +1,96 @@ + +# BigQuery Query Magic + +Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. + +## Run a query on a public dataset + +The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. + +The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). + + +```python +%%bigquery +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + +## Display verbose output + +As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion. + + +```python +%%bigquery --verbose +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + +## Explicitly specify a project + +By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. + + +```python +project_id = 'your-project-id' +``` + + +```python +project_id = 'ajhamilton-scratch' +``` + + +```python +%%bigquery --project $project_id +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + +## Assign the query results to a variable + +If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command. + + +```python +%%bigquery df +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + +```python +df +``` + +## Run a parameterized query + +Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. + + +```python +params = {"limit": 10} +``` + + +```python +%%bigquery --params $params +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT @limit +``` diff --git a/notebooks/rendered/unexecuted/BigQuery Shell Commands.md b/notebooks/rendered/unexecuted/BigQuery Shell Commands.md new file mode 100644 index 00000000000..f6a0d1d976d --- /dev/null +++ b/notebooks/rendered/unexecuted/BigQuery Shell Commands.md @@ -0,0 +1,60 @@ + +# BigQuery command-line tool + +The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`. + +## View available commands + +To view the available commands for the BigQuery command-line tool, use the `--help` flag. + + +```python +!bq help +``` + +## Create a new dataset + +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). + +The example below creates a new dataset in the US named "your_new_dataset". + + +```python +!bq --location=US mk --dataset "your_dataset_id" +``` + +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + + +```python +!bq load --help +``` + + +```python +!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv' +``` + +## Load data from Google Cloud Storage to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. + + +```python +!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +``` + +## Run a query + +The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose. + +## Cleaning Up + +The following code deletes the dataset created for this tutorial, including all tables in the dataset. + + +```python +!bq rm -r -f --dataset your_dataset_id +``` diff --git a/notebooks/rendered/unexecuted/Storage Client Library.md b/notebooks/rendered/unexecuted/Storage Client Library.md new file mode 100644 index 00000000000..45fd8f529a2 --- /dev/null +++ b/notebooks/rendered/unexecuted/Storage Client Library.md @@ -0,0 +1,139 @@ + +# Google Cloud Storage + +This page shows how to get started with the Google Cloud Storage Python client library. + +## Import the library + + +```python +from google.cloud import storage +``` + +## Projects + +All data in Cloud Storage belongs inside a project. A project consists of a +set of users, a set of APIs, and billing, authentication, and monitoring +settings for those APIs. You can have one project or multiple projects. + +## Clients +Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client. + + +```python +client = storage.Client(project="your-project-id") +``` + +## Buckets + +Buckets are the basic containers that hold your data. Everything that you +store in Cloud Storage must be contained in a bucket. You can use buckets to +organize your data and control access to your data. + +### Create a bucket + +When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), +you specify a globally-unique name. + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'your-new-bucket' + +# Creates the new bucket +bucket = client.create_bucket(bucket_name) + +print('Bucket {} created.'.format(bucket.name)) +``` + +### List buckets in a project + + +```python +buckets = client.list_buckets() + +print("Buckets in {}:".format(client.project)) +for item in buckets: + print("\t" + item.name) +``` + +### Get a bucket + + +```python +bucket = client.get_bucket(bucket_name) +``` + +## Objects + +Objects are the individual pieces of data that you store in Cloud Storage. +There is no limit on the number of objects that you can create in a bucket. + +### Upload a local file to a bucket + + +```python +blob_name = 'us-states.txt' +blob = bucket.blob(blob_name) + +source_file_name = 'resources/us-states.txt' +blob.upload_from_filename(source_file_name) + +print('File uploaded to {}.'.format(bucket.name)) +``` + +### List blobs in a bucket + + +```python +blobs = bucket.list_blobs() + +print("Blobs in {}:".format(bucket.name)) +for item in blobs: + print("\t" + item.name) +``` + +### Get a blob and display metadata +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +blob = bucket.get_blob(blob_name) + +print('Select metadata for blob {}:'.format(blob_name)) +print('\tID: {}'.format(blob.id)) +print('\tSize: {} bytes'.format(blob.size)) +print('\tUpdated: {}'.format(blob.updated)) +``` + +### Download a blob to a local directory + + +```python +output_file_name = 'resources/downloaded-us-states.txt' +blob.download_to_filename(output_file_name) + +print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) +``` + +## Cleaning up + +### Delete a blob + + +```python +blob = client.get_bucket(bucket_name).get_blob(blob_name) +blob.delete() + +print('Blob {} deleted.'.format(blob.name)) +``` + +### Delete a bucket + + +```python +bucket = client.get_bucket(bucket_name) +bucket.delete() + +print('Bucket {} deleted.'.format(bucket.name)) +``` diff --git a/notebooks/rendered/unexecuted/Storage Commands.md b/notebooks/rendered/unexecuted/Storage Commands.md new file mode 100644 index 00000000000..b75eaca831b --- /dev/null +++ b/notebooks/rendered/unexecuted/Storage Commands.md @@ -0,0 +1,98 @@ + +# Storage Commands + +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. + +This notebook introduces several `gsutil` commands for interacting with Cloud Storage. + +## List available commands + +The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: + + +```python +!gsutil help +``` + +## Buckets + +Buckets are the basic containers that hold your data. Everything that you +store in Cloud Storage must be contained in a bucket. You can use buckets to +organize your data and control access to your data. + +### Create a bucket + +When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), +you specify a globally-unique name. + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'your-new-bucket' +``` + +NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. + + +```python +!gsutil mb gs://{bucket_name}/ +``` + +### List buckets in a project + +Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. + + +```python +!gsutil ls -p your-project-id +``` + +## Objects + +Objects are the individual pieces of data that you store in Cloud Storage. +There is no limit on the number of objects that you can create in a bucket. + +### Upload a local file to a bucket + + +```python +!gsutil cp resources/us-states.txt gs://{bucket_name}/ +``` + +### List blobs in a bucket + + +```python +!gsutil ls -r gs://{bucket_name}/** +``` + +### Get a blob and display metadata +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +!gsutil ls -L gs://{bucket_name}/us-states.txt +``` + +### Download a blob to a local directory + + +```python +!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt +``` + +## Cleaning up + +### Delete a blob + + +```python +!gsutil rm gs://{bucket_name}/us-states.txt +``` + +### Delete a bucket + + +```python +!gsutil rm -r gs://{bucket_name}/ +``` diff --git a/notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md b/notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md new file mode 100644 index 00000000000..16785c06716 --- /dev/null +++ b/notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md @@ -0,0 +1,146 @@ + +# Vizualizing BigQuery Data in a Jupyter Notebook + +[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. + +Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. + +## Using Jupyter Magics to Query BigQuery Data + +The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. + +The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. + + +```python +%%bigquery +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + +The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. + + +```python +%%bigquery total_births +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + +The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. + + +```python +total_births.plot(kind='bar', x='year', y='birth_count'); +``` + +Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. + + +```python +%%bigquery births_by_weekday +SELECT + wday, + SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, + SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births +FROM `bigquery-public-data.samples.natality` +WHERE wday IS NOT NULL +GROUP BY wday +ORDER BY wday ASC +``` + +Visualize the query results using a line chart. + + +```python +births_by_weekday.plot(x='wday'); +``` + +## Using Python to Query BigQuery Data + +Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. + +To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. + + +```python +from google.cloud import bigquery + +client = bigquery.Client() +``` + +Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). + + +```python +sql = """ +SELECT + plurality, + COUNT(1) AS count, + year +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(plurality) AND plurality > 1 +GROUP BY + plurality, year +ORDER BY + count DESC +""" +df = client.query(sql).to_dataframe() +df.head() +``` + +To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. + + +```python +pivot_table = df.pivot(index='year', columns='plurality', values='count') +pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); +``` + +Run the following query to retrieve the count of births by the number of gestation weeks. + + +```python +sql = """ +SELECT + gestation_weeks, + COUNT(1) AS count +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 +GROUP BY + gestation_weeks +ORDER BY + gestation_weeks +""" +df = client.query(sql).to_dataframe() +``` + +Finally, chart the query results in your DataFrame. + + +```python +ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) +ax.set_title('Count of Births by Gestation Weeks') +ax.set_xlabel('Gestation Weeks') +ax.set_ylabel('Count'); +``` + +### What's Next + ++ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. + ++ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). diff --git a/notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb b/notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb deleted file mode 100644 index fc0d6c2674a..00000000000 --- a/notebooks/test/executed_notebooks/BigQuery Basics_output.ipynb +++ /dev/null @@ -1,615 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext google.cloud.bigquery" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# BigQuery Basics\n", - "\n", - "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Import the libraries used in this tutorial" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "from google.cloud import bigquery\n", - "import pandas" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialize a client\n", - "\n", - "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "client = bigquery.Client()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run a query on a public dataset\n", - "\n", - "The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", - "\n", - "Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
name
0Mary
1Ruby
2Annie
3Willie
4Ruth
5Gladys
6Maria
7Frances
8Margaret
9Helen
\n", - "
" - ], - "text/plain": [ - " name\n", - "0 Mary\n", - "1 Ruby\n", - "2 Annie\n", - "3 Willie\n", - "4 Ruth\n", - "5 Gladys\n", - "6 Maria\n", - "7 Frances\n", - "8 Margaret\n", - "9 Helen" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "query = \"\"\"\n", - " SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - " WHERE state = \"TX\"\n", - " LIMIT 10\n", - "\"\"\"\n", - "query_job = client.query(\n", - " query,\n", - " # Location must match that of the dataset(s) referenced in the query.\n", - " location=\"US\",\n", - ") # API request - starts the query\n", - "\n", - "df = query_job.to_dataframe()\n", - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create a new dataset\n", - "\n", - "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "import time\n", - "\n", - "# Define a name for the new dataset.\n", - "dataset_id = 'test_dataset_1548268897503'\n", - "\n", - "# Create a DatasetReference using a chosen dataset ID.\n", - "# The project defaults to the Client's project if not specified.\n", - "dataset_ref = client.dataset(dataset_id)\n", - "\n", - "# Construct a full Dataset object to send to the API.\n", - "dataset = bigquery.Dataset(dataset_ref)\n", - "# Specify the geographic location where the dataset should reside.\n", - "dataset.location = 'US'\n", - "\n", - "# Send the dataset to the API for creation.\n", - "dataset = client.create_dataset(dataset) # API request" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load data from a Pandas DataFrame to a new table" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Loaded dataframe to /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/monty_python\n" - ] - } - ], - "source": [ - "records = [\n", - " {\"title\": \"The Meaning of Life\", \"release_year\": 1983},\n", - " {\"title\": \"Monty Python and the Holy Grail\", \"release_year\": 1975},\n", - " {\"title\": \"Life of Brian\", \"release_year\": 1979},\n", - " {\"title\": \"And Now for Something Completely Different\", \"release_year\": 1971},\n", - "]\n", - "\n", - "# Optionally set explicit indices.\n", - "# If indices are not specified, a column will be created for the default\n", - "# indices created by pandas.\n", - "index = [\"Q24980\", \"Q25043\", \"Q24953\", \"Q16403\"]\n", - "df = pandas.DataFrame(records, index=pandas.Index(index, name=\"wikidata_id\"))\n", - "\n", - "table_ref = dataset_ref.table(\"monty_python\")\n", - "job = client.load_table_from_dataframe(df, table_ref, location=\"US\")\n", - "\n", - "job.result() # Waits for table load to complete.\n", - "print(\"Loaded dataframe to {}\".format(table_ref.path))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load query results to a table\n", - "\n", - "For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Query results loaded to table /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/your_new_table_id\n" - ] - } - ], - "source": [ - "sql = \"\"\"\n", - " SELECT corpus\n", - " FROM `bigquery-public-data.samples.shakespeare`\n", - " GROUP BY corpus;\n", - "\"\"\"\n", - "table_ref = dataset.table(\"your_new_table_id\")\n", - "job_config = bigquery.QueryJobConfig(\n", - " destination=table_ref\n", - ")\n", - "\n", - "# Start the query, passing in the extra configuration.\n", - "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", - "\n", - "query_job.result() # Waits for the query to finish\n", - "print(\"Query results loaded to table {}\".format(table_ref.path))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load data from a local file to a table\n", - "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Loaded 50 rows into test_dataset_1548268897503:/projects/ajhamilton-scratch/datasets/test_dataset_1548268897503/tables/us_states_from_local_file.\n" - ] - } - ], - "source": [ - "source_filename = 'resources/us-states.csv'\n", - "\n", - "table_ref = dataset_ref.table('us_states_from_local_file')\n", - "job_config = bigquery.LoadJobConfig(\n", - " source_format=bigquery.SourceFormat.CSV,\n", - " skip_leading_rows=1,\n", - " autodetect=True\n", - ")\n", - "\n", - "with open(source_filename, 'rb') as source_file:\n", - " job = client.load_table_from_file(\n", - " source_file,\n", - " table_ref,\n", - " location='US', # Must match the destination dataset location.\n", - " job_config=job_config) # API request\n", - "\n", - "job.result() # Waits for table load to complete.\n", - "\n", - "print('Loaded {} rows into {}:{}.'.format(\n", - " job.output_rows, dataset_id, table_ref.path))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load data from Google Cloud Storage to a table\n", - "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Starting job f65c1470-3e8b-4b0f-8a44-ff6a3f5cbaf0\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Job finished.\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Loaded 50 rows.\n" - ] - } - ], - "source": [ - "# Configure the load job\n", - "job_config = bigquery.LoadJobConfig(\n", - " schema=[\n", - " bigquery.SchemaField('name', 'STRING'),\n", - " bigquery.SchemaField('post_abbr', 'STRING')\n", - " ],\n", - " skip_leading_rows=1,\n", - " # The source format defaults to CSV, so the line below is optional.\n", - " source_format=bigquery.SourceFormat.CSV\n", - ")\n", - "uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'\n", - "destination_table_ref = dataset.table('us_states_from_gcs')\n", - "\n", - "# Start the load job\n", - "load_job = client.load_table_from_uri(\n", - " uri, destination_table_ref, job_config=job_config)\n", - "print('Starting job {}'.format(load_job.job_id))\n", - "\n", - "load_job.result() # Waits for table load to complete.\n", - "print('Job finished.')\n", - "\n", - "# Retreive the destination table\n", - "destination_table = client.get_table(table_ref)\n", - "print('Loaded {} rows.'.format(destination_table.num_rows))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run a parameterized query\n", - "\n", - "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", - "\n", - "To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", - "\n", - "For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
wordword_count
0the614
1I577
2and490
3to486
4a407
5of367
6my314
7is307
8in291
9you271
10that270
11me263
\n", - "
" - ], - "text/plain": [ - " word word_count\n", - "0 the 614\n", - "1 I 577\n", - "2 and 490\n", - "3 to 486\n", - "4 a 407\n", - "5 of 367\n", - "6 my 314\n", - "7 is 307\n", - "8 in 291\n", - "9 you 271\n", - "10 that 270\n", - "11 me 263" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Define the query\n", - "sql = \"\"\"\n", - " SELECT word, word_count\n", - " FROM `bigquery-public-data.samples.shakespeare`\n", - " WHERE corpus = @corpus\n", - " AND word_count >= @min_word_count\n", - " ORDER BY word_count DESC;\n", - "\"\"\"\n", - "\n", - "# Define the parameter values in a query job configuration\n", - "job_config = bigquery.QueryJobConfig(\n", - " query_parameters=[\n", - " bigquery.ScalarQueryParameter(\"corpus\", \"STRING\", \"romeoandjuliet\"),\n", - " bigquery.ScalarQueryParameter(\"min_word_count\", \"INT64\", 250),\n", - " ]\n", - ")\n", - "\n", - "# Start the query job\n", - "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", - "\n", - "# Return the results as a Pandas DataFrame\n", - "query_job.to_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cleaning Up\n", - "\n", - "The following code deletes the dataset created for this tutorial, including all tables in the dataset." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Deleted dataset: /projects/ajhamilton-scratch/datasets/test_dataset_1548268897503\n" - ] - } - ], - "source": [ - "# Retrieve the dataset from the API\n", - "dataset = client.get_dataset(client.dataset(dataset_id))\n", - "\n", - "# Delete the dataset and its contents\n", - "client.delete_dataset(dataset, delete_contents=True)\n", - "\n", - "print('Deleted dataset: {}'.format(dataset.path))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Local google-cloud-bigquery development", - "language": "python", - "name": "venv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb b/notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb deleted file mode 100644 index 16d78b6438a..00000000000 --- a/notebooks/test/executed_notebooks/BigQuery Query Magic_output.ipynb +++ /dev/null @@ -1,818 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext google.cloud.bigquery" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# BigQuery Query Magic\n", - "\n", - "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run a query on a public dataset\n", - "\n", - "The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", - "\n", - "The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", - "
" - ], - "text/plain": [ - " name count\n", - "0 James 5001762\n", - "1 John 4875934\n", - "2 Robert 4743843\n", - "3 Michael 4354622\n", - "4 William 3886371\n", - "5 Mary 3748377\n", - "6 David 3595923\n", - "7 Richard 2542659\n", - "8 Joseph 2518578\n", - "9 Charles 2273860" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery\n", - "SELECT name, SUM(number) as count\n", - "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - "GROUP BY name\n", - "ORDER BY count DESC\n", - "LIMIT 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Display verbose output\n", - "\n", - "As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Executing query with job ID: 791c0804-adf8-432a-8618-dab212848f03\n", - "\r", - "Query executing: 0.48s" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Query complete after 0.93s\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", - "
" - ], - "text/plain": [ - " name count\n", - "0 James 5001762\n", - "1 John 4875934\n", - "2 Robert 4743843\n", - "3 Michael 4354622\n", - "4 William 3886371\n", - "5 Mary 3748377\n", - "6 David 3595923\n", - "7 Richard 2542659\n", - "8 Joseph 2518578\n", - "9 Charles 2273860" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery --verbose\n", - "SELECT name, SUM(number) as count\n", - "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - "GROUP BY name\n", - "ORDER BY count DESC\n", - "LIMIT 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Explicitly specify a project\n", - "\n", - "By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "project_id = 'my-project-id'" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "project_id = 'ajhamilton-scratch'" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", - "
" - ], - "text/plain": [ - " name count\n", - "0 James 5001762\n", - "1 John 4875934\n", - "2 Robert 4743843\n", - "3 Michael 4354622\n", - "4 William 3886371\n", - "5 Mary 3748377\n", - "6 David 3595923\n", - "7 Richard 2542659\n", - "8 Joseph 2518578\n", - "9 Charles 2273860" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery --project $project_id\n", - "SELECT name, SUM(number) as count\n", - "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - "GROUP BY name\n", - "ORDER BY count DESC\n", - "LIMIT 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Assign the query results to a variable\n", - "\n", - "If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", - "
" - ], - "text/plain": [ - " name count\n", - "0 James 5001762\n", - "1 John 4875934\n", - "2 Robert 4743843\n", - "3 Michael 4354622\n", - "4 William 3886371\n", - "5 Mary 3748377\n", - "6 David 3595923\n", - "7 Richard 2542659\n", - "8 Joseph 2518578\n", - "9 Charles 2273860" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery df\n", - "SELECT name, SUM(number) as count\n", - "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - "GROUP BY name\n", - "ORDER BY count DESC\n", - "LIMIT 10" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", - "
" - ], - "text/plain": [ - " name count\n", - "0 James 5001762\n", - "1 John 4875934\n", - "2 Robert 4743843\n", - "3 Michael 4354622\n", - "4 William 3886371\n", - "5 Mary 3748377\n", - "6 David 3595923\n", - "7 Richard 2542659\n", - "8 Joseph 2518578\n", - "9 Charles 2273860" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "df" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run a parameterized query\n", - "\n", - "Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [], - "source": [ - "params = {\"limit\": 10}" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
\n", - "
" - ], - "text/plain": [ - " name count\n", - "0 James 5001762\n", - "1 John 4875934\n", - "2 Robert 4743843\n", - "3 Michael 4354622\n", - "4 William 3886371\n", - "5 Mary 3748377\n", - "6 David 3595923\n", - "7 Richard 2542659\n", - "8 Joseph 2518578\n", - "9 Charles 2273860" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery --params $params\n", - "SELECT name, SUM(number) as count\n", - "FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - "GROUP BY name\n", - "ORDER BY count DESC\n", - "LIMIT @limit" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Local google-cloud-bigquery development", - "language": "python", - "name": "venv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb b/notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb deleted file mode 100644 index 64c5a311e93..00000000000 --- a/notebooks/test/executed_notebooks/BigQuery Shell Commands_output.ipynb +++ /dev/null @@ -1,809 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext google.cloud.bigquery" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# BigQuery command-line tool\n", - "\n", - "The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## View available commands\n", - "\n", - "To view the available commands for the BigQuery command-line tool, use the `--help` flag." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Python script for interacting with BigQuery.\r\n", - "\r\n", - "\r\n", - "USAGE: bq [--global_flags] [--command_flags] [args]\r\n", - "\r\n", - "\r\n", - "Any of the following commands:\r\n", - " cancel, cp, extract, head, help, init, insert, load, ls, mk, mkdef, partition,\r\n", - " query, rm, shell, show, update, version, wait\r\n", - "\r\n", - "\r\n", - "cancel Request a cancel and waits for the job to be cancelled.\r\n", - "\r\n", - " Requests a cancel and then either: a) waits until the job is done if\r\n", - " the sync flag is set [default], or b) returns immediately if the sync\r\n", - " flag is not set. Not all job types support a cancel, an error is\r\n", - " returned if it cannot be cancelled. Even for jobs that support a\r\n", - " cancel, success is not guaranteed, the job may have completed by the\r\n", - " time the cancel request is noticed, or the job may be in a stage\r\n", - " where it cannot be cancelled.\r\n", - "\r\n", - " Examples:\r\n", - " bq cancel job_id # Requests a cancel and waits until the job is done.\r\n", - " bq --nosync cancel job_id # Requests a cancel and returns\r\n", - " immediately.\r\n", - "\r\n", - " Arguments:\r\n", - " job_id: Job ID to cancel.\r\n", - "\r\n", - "cp Copies one table to another.\r\n", - "\r\n", - " Examples:\r\n", - " bq cp dataset.old_table dataset2.new_table\r\n", - " bq cp --destination_kms_key=kms_key dataset.old_table\r\n", - " dataset2.new_table\r\n", - "\r\n", - "extract Perform an extract operation of source_table into destination_uris.\r\n", - "\r\n", - " Usage:\r\n", - " extract \r\n", - "\r\n", - " Examples:\r\n", - " bq extract ds.summary gs://mybucket/summary.csv\r\n", - "\r\n", - " Arguments:\r\n", - " source_table: Source table to extract.\r\n", - " destination_uris: One or more Google Cloud Storage URIs, separated by\r\n", - " commas.\r\n", - "\r\n", - "head Displays rows in a table.\r\n", - "\r\n", - " Examples:\r\n", - " bq head dataset.table\r\n", - " bq head -j job\r\n", - " bq head -n 10 dataset.table\r\n", - " bq head -s 5 -n 10 dataset.table\r\n", - "\r\n", - "help Help for all or selected command:\r\n", - " bq help []\r\n", - "\r\n", - " To retrieve help with global flags:\r\n", - " bq --help\r\n", - "\r\n", - " To retrieve help with flags only from the main module:\r\n", - " bq --helpshort []\r\n", - "\r\n", - "init Authenticate and create a default .bigqueryrc file.\r\n", - "\r\n", - "insert Inserts rows in a table.\r\n", - "\r\n", - " Inserts the records formatted as newline delimited JSON from file\r\n", - " into the specified table. If file is not specified, reads from stdin.\r\n", - " If there were any insert errors it prints the errors to stdout.\r\n", - "\r\n", - " Examples:\r\n", - " bq insert dataset.table /tmp/mydata.json\r\n", - " echo '{\"a\":1, \"b\":2}' | bq insert dataset.table\r\n", - "\r\n", - " Template table examples: Insert to dataset.template_suffix table\r\n", - " using dataset.template table as its template.\r\n", - " bq insert -x=_suffix dataset.table /tmp/mydata.json\r\n", - "\r\n", - "load Perform a load operation of source into destination_table.\r\n", - "\r\n", - " Usage:\r\n", - " load []\r\n", - "\r\n", - " The is the fully-qualified table name of table to\r\n", - " create, or append to if the table already exists.\r\n", - "\r\n", - " The argument can be a path to a single local file, or a\r\n", - " comma-separated list of URIs.\r\n", - "\r\n", - " The argument should be either the name of a JSON file or a\r\n", - " text schema. This schema should be omitted if the table already has\r\n", - " one.\r\n", - "\r\n", - " In the case that the schema is provided in text form, it should be a\r\n", - " comma-separated list of entries of the form name[:type], where type\r\n", - " will default to string if not specified.\r\n", - "\r\n", - " In the case that is a filename, it should contain a single\r\n", - " array object, each entry of which should be an object with properties\r\n", - " 'name', 'type', and (optionally) 'mode'. See the online documentation\r\n", - " for more detail:\r\n", - " https://developers.google.com/bigquery/preparing-data-for-bigquery\r\n", - "\r\n", - " Note: the case of a single-entry schema with no type specified is\r\n", - " ambiguous; one can use name:string to force interpretation as a\r\n", - " text schema.\r\n", - "\r\n", - " Examples:\r\n", - " bq load ds.new_tbl ./info.csv ./info_schema.json\r\n", - " bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json\r\n", - " bq load ds.small gs://mybucket/small.csv name:integer,value:string\r\n", - " bq load ds.small gs://mybucket/small.csv field1,field2,field3\r\n", - "\r\n", - " Arguments:\r\n", - " destination_table: Destination table name.\r\n", - " source: Name of local file to import, or a comma-separated list of\r\n", - " URI paths to data to import.\r\n", - " schema: Either a text schema or JSON file, as above.\r\n", - "\r\n", - "ls List the objects contained in the named collection.\r\n", - "\r\n", - " List the objects in the named project or dataset. A trailing : or .\r\n", - " can be used to signify a project or dataset.\r\n", - " * With -j, show the jobs in the named project.\r\n", - " * With -p, show all projects.\r\n", - "\r\n", - " Examples:\r\n", - " bq ls\r\n", - " bq ls -j proj\r\n", - " bq ls -p -n 1000\r\n", - " bq ls mydataset\r\n", - " bq ls -a\r\n", - " bq ls --filter labels.color:red\r\n", - " bq ls --filter 'labels.color:red labels.size:*'\r\n", - " bq ls --transfer_config --transfer_location='us'\r\n", - " --filter='dataSourceIds:play,adwords'\r\n", - " bq ls --transfer_run --filter='states:SUCCESSED,PENDING'\r\n", - " --run_attempt='LATEST' projects/p/locations/l/transferConfigs/c\r\n", - " bq ls --transfer_log --message_type='messageTypes:INFO,ERROR'\r\n", - " projects/p/locations/l/transferConfigs/c/runs/r\r\n", - "\r\n", - "mk Create a dataset, table, view, or transfer configuration with this\r\n", - " name.\r\n", - "\r\n", - " See 'bq help load' for more information on specifying the schema.\r\n", - "\r\n", - " Examples:\r\n", - " bq mk new_dataset\r\n", - " bq mk new_dataset.new_table\r\n", - " bq --dataset_id=new_dataset mk table\r\n", - " bq mk -t new_dataset.newtable name:integer,value:string\r\n", - " bq mk --view='select 1 as num' new_dataset.newview\r\n", - " (--view_udf_resource=path/to/file.js)\r\n", - " bq mk -d --data_location=EU new_dataset\r\n", - " bq mk --transfer_config --target_dataset=dataset --display_name=name\r\n", - " -p='{\"param\":\"value\"}' --data_source=source\r\n", - " bq mk --transfer_run --start_time={start_time} --end_time={end_time}\r\n", - " projects/p/locations/l/transferConfigs/c\r\n", - "\r\n", - "mkdef Emits a definition in JSON for a GCS backed table.\r\n", - "\r\n", - " The output of this command can be redirected to a file and used for\r\n", - " the external_table_definition flag with the \"bq query\" and \"bq mk\"\r\n", - " commands. It produces a definition with the most commonly used values\r\n", - " for options. You can modify the output to override option values.\r\n", - "\r\n", - " Usage:\r\n", - " mkdef []\r\n", - "\r\n", - " Examples:\r\n", - " bq mkdef 'gs://bucket/file.csv' field1:integer,field2:string\r\n", - "\r\n", - " Arguments:\r\n", - " source_uris: a comma-separated list of uris.\r\n", - " schema: The argument should be either the name of a JSON\r\n", - " file or\r\n", - " a text schema.\r\n", - "\r\n", - " In the case that the schema is provided in text form, it should be a\r\n", - " comma-separated list of entries of the form name[:type], where type\r\n", - " will\r\n", - " default to string if not specified.\r\n", - "\r\n", - " In the case that is a filename, it should contain a\r\n", - " single array object, each entry of which should be an object with\r\n", - " properties 'name', 'type', and (optionally) 'mode'. See the online\r\n", - " documentation for more detail:\r\n", - " https://developers.google.com/bigquery/preparing-data-for-bigquery\r\n", - "\r\n", - " Note: the case of a single-entry schema with no type specified is\r\n", - " ambiguous; one can use name:string to force interpretation as a\r\n", - " text schema.\r\n", - "\r\n", - "partition Copies source tables into partitioned tables.\r\n", - "\r\n", - " Usage: bq partition \r\n", - " \r\n", - "\r\n", - " Copies tables of the format to a\r\n", - " destination partitioned table, with the date suffix of the source\r\n", - " tables becoming the partition date of the destination table\r\n", - " partitions.\r\n", - "\r\n", - " If the destination table does not exist, one will be created with a\r\n", - " schema and that matches the last table that matches the supplied\r\n", - " prefix.\r\n", - "\r\n", - " Examples:\r\n", - " bq partition dataset1.sharded_ dataset2.partitioned_table\r\n", - "\r\n", - "query Execute a query.\r\n", - "\r\n", - " Query should be specifed on command line, or passed on stdin.\r\n", - "\r\n", - " Examples:\r\n", - " bq query 'select count(*) from publicdata:samples.shakespeare'\r\n", - " echo 'select count(*) from publicdata:samples.shakespeare' | bq query\r\n", - "\r\n", - " Usage:\r\n", - " query []\r\n", - "\r\n", - "rm Delete the dataset, table, or transfer config described by\r\n", - " identifier.\r\n", - "\r\n", - " Always requires an identifier, unlike the show and ls commands. By\r\n", - " default, also requires confirmation before deleting. Supports the -d\r\n", - " -t flags to signify that the identifier is a dataset or table.\r\n", - " * With -f, don't ask for confirmation before deleting.\r\n", - " * With -r, remove all tables in the named dataset.\r\n", - "\r\n", - " Examples:\r\n", - " bq rm ds.table\r\n", - " bq rm -r -f old_dataset\r\n", - " bq rm --transfer_config=projects/p/locations/l/transferConfigs/c\r\n", - "\r\n", - "shell Start an interactive bq session.\r\n", - "\r\n", - "show Show all information about an object.\r\n", - "\r\n", - " Examples:\r\n", - " bq show -j \r\n", - " bq show dataset\r\n", - " bq show [--schema] dataset.table\r\n", - " bq show [--view] dataset.view\r\n", - " bq show --transfer_config projects/p/locations/l/transferConfigs/c\r\n", - " bq show --transfer_run\r\n", - " projects/p/locations/l/transferConfigs/c/runs/r\r\n", - " bq show --encryption_service_account\r\n", - "\r\n", - "update Updates a dataset, table, view or transfer configuration with this\r\n", - " name.\r\n", - "\r\n", - " See 'bq help load' for more information on specifying the schema.\r\n", - "\r\n", - " Examples:\r\n", - " bq update --description \"Dataset description\" existing_dataset\r\n", - " bq update --description \"My table\" existing_dataset.existing_table\r\n", - " bq update -t existing_dataset.existing_table\r\n", - " name:integer,value:string\r\n", - " bq update --destination_kms_key\r\n", - " projects/p/locations/l/keyRings/r/cryptoKeys/k\r\n", - " existing_dataset.existing_table\r\n", - " bq update --view='select 1 as num' existing_dataset.existing_view\r\n", - " (--view_udf_resource=path/to/file.js)\r\n", - " bq update --transfer_config --display_name=name\r\n", - " -p='{\"param\":\"value\"}'\r\n", - " projects/p/locations/l/transferConfigs/c\r\n", - " bq update --transfer_config --target_dataset=dataset\r\n", - " --refresh_window_days=5 --update_credentials\r\n", - " projects/p/locations/l/transferConfigs/c\r\n", - "\r\n", - "version Return the version of bq.\r\n", - "\r\n", - "wait Wait some number of seconds for a job to finish.\r\n", - "\r\n", - " Poll job_id until either (1) the job is DONE or (2) the specified\r\n", - " number of seconds have elapsed. Waits forever if unspecified. If no\r\n", - " job_id is specified, and there is only one running job, we poll that\r\n", - " job.\r\n", - "\r\n", - " Examples:\r\n", - " bq wait # Waits forever for the currently running job.\r\n", - " bq wait job_id # Waits forever\r\n", - " bq wait job_id 100 # Waits 100 seconds\r\n", - " bq wait job_id 0 # Polls if a job is done, then returns immediately.\r\n", - " # These may exit with a non-zero status code to indicate \"failure\":\r\n", - " bq wait --fail_on_error job_id # Succeeds if job succeeds.\r\n", - " bq wait --fail_on_error job_id 100 # Succeeds if job succeeds in 100\r\n", - " sec.\r\n", - "\r\n", - " Arguments:\r\n", - " job_id: Job ID to wait on.\r\n", - " secs: Number of seconds to wait (must be >= 0).\r\n", - "\r\n", - "\r\n", - "Run 'bq --help' to get help for global flags.\r\n", - "Run 'bq help ' to get help for .\r\n" - ] - } - ], - "source": [ - "!bq help" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Create a new dataset\n", - "\n", - "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", - "\n", - "The example below creates a new dataset in the US named \"your_new_dataset\"." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Dataset 'ajhamilton-scratch:your_dataset_id' successfully created.\r\n" - ] - } - ], - "source": [ - "!bq --location=US mk --dataset \"your_dataset_id\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load data from a local file to a table\n", - "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Python script for interacting with BigQuery.\r\n", - "\r\n", - "\r\n", - "USAGE: bq [--global_flags] [--command_flags] [args]\r\n", - "\r\n", - "\r\n", - "load Perform a load operation of source into destination_table.\r\n", - "\r\n", - " Usage:\r\n", - " load []\r\n", - "\r\n", - " The is the fully-qualified table name of table to\r\n", - " create, or append to if the table already exists.\r\n", - "\r\n", - " The argument can be a path to a single local file, or a\r\n", - " comma-separated list of URIs.\r\n", - "\r\n", - " The argument should be either the name of a JSON file or a\r\n", - " text schema. This schema should be omitted if the table already has\r\n", - " one.\r\n", - "\r\n", - " In the case that the schema is provided in text form, it should be a\r\n", - " comma-separated list of entries of the form name[:type], where type\r\n", - " will default to string if not specified.\r\n", - "\r\n", - " In the case that is a filename, it should contain a single\r\n", - " array object, each entry of which should be an object with properties\r\n", - " 'name', 'type', and (optionally) 'mode'. See the online documentation\r\n", - " for more detail:\r\n", - " https://developers.google.com/bigquery/preparing-data-for-bigquery\r\n", - "\r\n", - " Note: the case of a single-entry schema with no type specified is\r\n", - " ambiguous; one can use name:string to force interpretation as a\r\n", - " text schema.\r\n", - "\r\n", - " Examples:\r\n", - " bq load ds.new_tbl ./info.csv ./info_schema.json\r\n", - " bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json\r\n", - " bq load ds.small gs://mybucket/small.csv name:integer,value:string\r\n", - " bq load ds.small gs://mybucket/small.csv field1,field2,field3\r\n", - "\r\n", - " Arguments:\r\n", - " destination_table: Destination table name.\r\n", - " source: Name of local file to import, or a comma-separated list of\r\n", - " URI paths to data to import.\r\n", - " schema: Either a text schema or JSON file, as above.\r\n", - "\r\n", - " Flags for load:\r\n", - "\r\n", - "/Users/ajhamilton/google-cloud-sdk/platform/bq/bq.py:\r\n", - " --[no]allow_jagged_rows: Whether to allow missing trailing optional columns in\r\n", - " CSV import data.\r\n", - " --[no]allow_quoted_newlines: Whether to allow quoted newlines in CSV import\r\n", - " data.\r\n", - " --[no]autodetect: Enable auto detection of schema and options for formats that\r\n", - " are not self describing like CSV and JSON.\r\n", - " --clustering_fields: Comma separated field names. Can only be specified with\r\n", - " time based partitioning. Data will be first partitioned and subsequently\r\n", - " \"clustered on these fields.\r\n", - " --destination_kms_key: Cloud KMS key for encryption of the destination table\r\n", - " data.\r\n", - " -E,--encoding: : The character encoding used by the input\r\n", - " file. Options include:\r\n", - " ISO-8859-1 (also known as Latin-1)\r\n", - " UTF-8\r\n", - " -F,--field_delimiter: The character that indicates the boundary between\r\n", - " columns in the input file. \"\\t\" and \"tab\" are accepted names for tab.\r\n", - " --[no]ignore_unknown_values: Whether to allow and ignore extra, unrecognized\r\n", - " values in CSV or JSON import data.\r\n", - " --max_bad_records: Maximum number of bad records allowed before the entire job\r\n", - " fails.\r\n", - " (default: '0')\r\n", - " (an integer)\r\n", - " --null_marker: An optional custom string that will represent a NULL valuein\r\n", - " CSV import data.\r\n", - " --projection_fields: If sourceFormat is set to \"DATASTORE_BACKUP\", indicates\r\n", - " which entity properties to load into BigQuery from a Cloud Datastore backup.\r\n", - " Property names are case sensitive and must refer to top-level properties.\r\n", - " (default: '')\r\n", - " (a comma separated list)\r\n", - " --quote: Quote character to use to enclose records. Default is \". To indicate\r\n", - " no quote character at all, use an empty string.\r\n", - " --[no]replace: If true erase existing contents before loading new data.\r\n", - " (default: 'false')\r\n", - " --[no]require_partition_filter: Whether to require partition filter for\r\n", - " queries over this table. Only apply to partitioned table.\r\n", - " --schema: Either a filename or a comma-separated list of fields in the form\r\n", - " name[:type].\r\n", - " --schema_update_option: Can be specified when append to a table, or replace a\r\n", - " table partition. When specified, the schema of the destination table will be\r\n", - " updated with the schema of the new data. One or more of the following\r\n", - " options can be specified:\r\n", - " ALLOW_FIELD_ADDITION: allow new fields to be added\r\n", - " ALLOW_FIELD_RELAXATION: allow relaxing required fields to nullable;\r\n", - " repeat this option to specify a list of values\r\n", - " --skip_leading_rows: The number of rows at the beginning of the source file to\r\n", - " skip.\r\n", - " (an integer)\r\n", - " --source_format:\r\n", - " : Format of\r\n", - " source data. Options include:\r\n", - " CSV\r\n", - " NEWLINE_DELIMITED_JSON\r\n", - " DATASTORE_BACKUP\r\n", - " AVRO\r\n", - " PARQUET\r\n", - " ORC (experimental)\r\n", - " --time_partitioning_expiration: Enables time based partitioning on the table\r\n", - " and sets the number of seconds for which to keep the storage for the\r\n", - " partitions in the table. The storage in a partition will have an expiration\r\n", - " time of its partition time plus this value. A negative number means no\r\n", - " expiration.\r\n", - " (an integer)\r\n", - " --time_partitioning_field: Enables time based partitioning on the table and\r\n", - " the table will be partitioned based on the value of this field. If time\r\n", - " based partitioning is enabled without this value, the table will be\r\n", - " partitioned based on the loading time.\r\n", - " --time_partitioning_type: Enables time based partitioning on the table and set\r\n", - " the type. The only type accepted is DAY, which will generate one partition\r\n", - " per day.\r\n", - "\r\n", - "gflags:\r\n", - " --flagfile: Insert flag definitions from the given file into the command line.\r\n", - " (default: '')\r\n", - " --undefok: comma-separated list of flag names that it is okay to specify on\r\n", - " the command line even if the program does not define a flag with that name.\r\n", - " IMPORTANT: flags in this list that have arguments MUST use the --flag=value\r\n", - " format.\r\n", - " (default: '')\r\n", - "\r\n", - "\r\n", - "Global flags:\r\n", - "\r\n", - "bq_auth_flags:\r\n", - " --application_default_credential_file: Only for the gcloud wrapper use.\r\n", - " (default: '')\r\n", - " --credential_file: Only for the gcloud wrapper use.\r\n", - " (default: '/Users/ajhamilton/.bigquery.v2.token')\r\n", - " --service_account: Only for the gcloud wrapper use.\r\n", - " (default: '')\r\n", - " --service_account_credential_file: Only for the gcloud wrapper use.\r\n", - " --service_account_private_key_file: Only for the gcloud wrapper use.\r\n", - " (default: '')\r\n", - " --service_account_private_key_password: Only for the gcloud wrapper use.\r\n", - " (default: 'notasecret')\r\n", - " --[no]use_gce_service_account: Only for the gcloud wrapper use.\r\n", - " (default: 'false')\r\n", - "\r\n", - "bq_flags:\r\n", - " --api: API endpoint to talk to.\r\n", - " (default: 'https://www.googleapis.com')\r\n", - " --api_version: API version to use.\r\n", - " (default: 'v2')\r\n", - " --apilog: Log all API requests and responses to the file specified by this\r\n", - " flag. Also accepts \"stdout\" and \"stderr\". Specifying the empty string will\r\n", - " direct to stdout.\r\n", - " --bigqueryrc: Path to configuration file. The configuration file specifies new\r\n", - " defaults for any flags, and can be overrridden by specifying the flag on the\r\n", - " command line. If the --bigqueryrc flag is not specified, the BIGQUERYRC\r\n", - " environment variable is used. If that is not specified, the path\r\n", - " \"~/.bigqueryrc\" is used.\r\n", - " (default: '/Users/ajhamilton/.bigqueryrc')\r\n", - " --ca_certificates_file: Location of CA certificates file.\r\n", - " (default: '')\r\n", - " --dataset_id: Default dataset reference to use for requests (Ignored when not\r\n", - " applicable.). Can be set as \"project:dataset\" or \"dataset\". If project is\r\n", - " missing, the value of the project_id flag will be used.\r\n", - " (default: '')\r\n", - " --[no]debug_mode: Show tracebacks on Python exceptions.\r\n", - " (default: 'false')\r\n", - " --[no]disable_ssl_validation: Disables HTTPS certificates validation. This is\r\n", - " off by default.\r\n", - " (default: 'false')\r\n", - " --discovery_file: Filename for JSON document to read for discovery.\r\n", - " (default: '')\r\n", - " --[no]enable_gdrive: When set to true, requests new OAuth token with GDrive\r\n", - " scope. When set to false, requests new OAuth token without GDrive scope.\r\n", - " --[no]fingerprint_job_id: Whether to use a job id that is derived from a\r\n", - " fingerprint of the job configuration. This will prevent the same job from\r\n", - " running multiple times accidentally.\r\n", - " (default: 'false')\r\n", - " --format: : Format for command output.\r\n", - " Options include:\r\n", - " pretty: formatted table output\r\n", - " sparse: simpler table output\r\n", - " prettyjson: easy-to-read JSON format\r\n", - " json: maximally compact JSON\r\n", - " csv: csv format with header\r\n", - " The first three are intended to be human-readable, and the latter three are\r\n", - " for passing to another program. If no format is selected, one will be chosen\r\n", - " based on the command run.\r\n", - " --[no]headless: Whether this bq session is running without user interaction.\r\n", - " This affects behavior that expects user interaction, like whether debug_mode\r\n", - " will break into the debugger and lowers the frequency of informational\r\n", - " printing.\r\n", - " (default: 'false')\r\n", - " --httplib2_debuglevel: Instruct httplib2 to print debugging messages by\r\n", - " setting debuglevel to the given value.\r\n", - " --job_id: A unique job_id to use for the request. If not specified, this\r\n", - " client will generate a job_id. Applies only to commands that launch jobs,\r\n", - " such as cp, extract, load, and query.\r\n", - " --job_property: Additional key-value pairs to include in the properties field\r\n", - " of the job configuration;\r\n", - " repeat this option to specify a list of values\r\n", - " --location: Default geographic location to use when creating datasets or\r\n", - " determining where jobs should run (Ignored when not applicable.)\r\n", - " --max_rows_per_request: Specifies the max number of rows to return per read.\r\n", - " (an integer)\r\n", - " --project_id: Default project to use for requests.\r\n", - " (default: '')\r\n", - " --proxy_address: The name or IP address of the proxy host to use for\r\n", - " connecting to GCP.\r\n", - " (default: '')\r\n", - " --proxy_password: The password to use when authenticating with proxy host.\r\n", - " (default: '')\r\n", - " --proxy_port: The port number to use to connect to the proxy host.\r\n", - " (default: '')\r\n", - " --proxy_username: The user name to use when authenticating with proxy host.\r\n", - " (default: '')\r\n", - " -q,--[no]quiet: If True, ignore status updates while jobs are running.\r\n", - " (default: 'false')\r\n", - " -sync,--[no]synchronous_mode: If True, wait for command completion before\r\n", - " returning, and use the job completion status for error codes. If False,\r\n", - " simply create the job, and use the success of job creation as the error\r\n", - " code.\r\n", - " (default: 'true')\r\n", - " --trace: A tracing token of the form \"token:\" to include in api\r\n", - " requests.\r\n", - "\r\n", - "google.apputils.app:\r\n", - " -?,--[no]help: show this help\r\n", - " --[no]helpshort: show usage only for this module\r\n", - " --[no]helpxml: like --help, but generates XML output\r\n", - " --[no]run_with_pdb: Set to true for PDB debug mode\r\n", - " (default: 'false')\r\n", - " --[no]run_with_profiling: Set to true for profiling the script. Execution will\r\n", - " be slower, and the output format might change over time.\r\n", - " (default: 'false')\r\n", - " --[no]show_build_data: show build data and exit\r\n", - " --[no]use_cprofile_for_profiling: Use cProfile instead of the profile module\r\n", - " for profiling. This has no effect unless --run_with_profiling is set.\r\n", - " (default: 'true')\r\n", - "\r\n", - "gflags:\r\n", - " --flagfile: Insert flag definitions from the given file into the command line.\r\n", - " (default: '')\r\n", - " --undefok: comma-separated list of flag names that it is okay to specify on\r\n", - " the command line even if the program does not define a flag with that name.\r\n", - " IMPORTANT: flags in this list that have arguments MUST use the --flag=value\r\n", - " format.\r\n", - " (default: '')\r\n", - "\r\n", - "Run 'bq help' to see the list of available commands.\r\n" - ] - } - ], - "source": [ - "!bq load --help" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - "Upload complete.\r\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (0s) Current status: RUNNING" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - " \r", - "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (1s) Current status: RUNNING" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - " \r", - "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (2s) Current status: RUNNING" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - " \r", - "Waiting on bqjob_r3fea50bb473556c6_000001687c0441ee_1 ... (2s) Current status: DONE \r\n" - ] - } - ], - "source": [ - "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Load data from Google Cloud Storage to a table\n", - "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - "Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (0s) Current status: RUNNING" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - " \r", - "Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (1s) Current status: RUNNING" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\r", - " \r", - "Waiting on bqjob_r3c677e7ba7eb1551_000001687c045ffb_1 ... (1s) Current status: DONE \r\n" - ] - } - ], - "source": [ - "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run a query\n", - "\n", - "The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cleaning Up\n", - "\n", - "The following code deletes the dataset created for this tutorial, including all tables in the dataset." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "!bq rm -r -f --dataset your_dataset_id" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Local google-cloud-bigquery development", - "language": "python", - "name": "venv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/test/executed_notebooks/Storage Client Library_output.ipynb b/notebooks/test/executed_notebooks/Storage Client Library_output.ipynb deleted file mode 100644 index 16baab9ff01..00000000000 --- a/notebooks/test/executed_notebooks/Storage Client Library_output.ipynb +++ /dev/null @@ -1,391 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext google.cloud.bigquery" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Google Cloud Storage\n", - "\n", - "This page shows how to get started with the Google Cloud Storage Python client library." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Import the library" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "from google.cloud import storage" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Projects\n", - "\n", - "All data in Cloud Storage belongs inside a project. A project consists of a\n", - "set of users, a set of APIs, and billing, authentication, and monitoring\n", - "settings for those APIs. You can have one project or multiple projects." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Clients\n", - "Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "client = storage.Client(project=\"ajhamilton-scratch\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Buckets\n", - "\n", - "Buckets are the basic containers that hold your data. Everything that you\n", - "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", - "organize your data and control access to your data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create a bucket\n", - "\n", - "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", - "you specify a globally-unique name." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bucket test-storage-bucket-1548268970715 created.\n" - ] - } - ], - "source": [ - "# Replace the string below with a unique name for the new bucket\n", - "bucket_name = 'test-storage-bucket-1548268970715'\n", - "\n", - "# Creates the new bucket\n", - "bucket = client.create_bucket(bucket_name)\n", - "\n", - "print('Bucket {} created.'.format(bucket.name))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List buckets in a project" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Buckets in ajhamilton-scratch:\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\tajhamilton-scratch\n", - "\tmy-new-bucket-1548180688764\n", - "\tmy-new-bucket-1548208228513\n", - "\ttest-storage-bucket-1548209987490\n", - "\ttest-storage-bucket-1548268970715\n" - ] - } - ], - "source": [ - "buckets = client.list_buckets()\n", - "\n", - "print(\"Buckets in {}:\".format(client.project))\n", - "for item in buckets:\n", - " print(\"\\t\" + item.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Get a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [], - "source": [ - "bucket = client.get_bucket(bucket_name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Objects\n", - "\n", - "Objects are the individual pieces of data that you store in Cloud Storage.\n", - "There is no limit on the number of objects that you can create in a bucket." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Upload a local file to a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "File uploaded to test-storage-bucket-1548268970715.\n" - ] - } - ], - "source": [ - "blob_name = 'us-states.txt'\n", - "blob = bucket.blob(blob_name)\n", - "\n", - "source_file_name = 'resources/us-states.txt'\n", - "blob.upload_from_filename(source_file_name)\n", - "\n", - "print('File uploaded to {}.'.format(bucket.name))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List blobs in a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Blobs in test-storage-bucket-1548268970715:\n", - "\tus-states.txt\n" - ] - } - ], - "source": [ - "blobs = bucket.list_blobs()\n", - "\n", - "print(\"Blobs in {}:\".format(bucket.name))\n", - "for item in blobs:\n", - " print(\"\\t\" + item.name)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Get a blob and display metadata\n", - "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Select metadata for blob us-states.txt:\n", - "\tID: test-storage-bucket-1548268970715/us-states.txt/1548268974850839\n", - "\tSize: 637 bytes\n", - "\tUpdated: 2019-01-23 18:42:54.850000+00:00\n" - ] - } - ], - "source": [ - "blob = bucket.get_blob(blob_name)\n", - "\n", - "print('Select metadata for blob {}:'.format(blob_name))\n", - "print('\\tID: {}'.format(blob.id))\n", - "print('\\tSize: {} bytes'.format(blob.size))\n", - "print('\\tUpdated: {}'.format(blob.updated))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Download a blob to a local directory" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Downloaded blob us-states.txt to resources/downloaded-us-states.txt.\n" - ] - } - ], - "source": [ - "output_file_name = 'resources/downloaded-us-states.txt'\n", - "blob.download_to_filename(output_file_name)\n", - "\n", - "print('Downloaded blob {} to {}.'.format(blob.name, output_file_name))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cleaning up" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Delete a blob" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Blob us-states.txt deleted.\n" - ] - } - ], - "source": [ - "blob = client.get_bucket(bucket_name).get_blob(blob_name)\n", - "blob.delete()\n", - "\n", - "print('Blob {} deleted.'.format(blob.name))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Delete a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Bucket test-storage-bucket-1548268970715 deleted.\n" - ] - } - ], - "source": [ - "bucket = client.get_bucket(bucket_name)\n", - "bucket.delete()\n", - "\n", - "print('Bucket {} deleted.'.format(bucket.name))" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Local google-cloud-bigquery development", - "language": "python", - "name": "venv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.4" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/notebooks/test/executed_notebooks/Storage Commands_output.ipynb b/notebooks/test/executed_notebooks/Storage Commands_output.ipynb deleted file mode 100644 index 0ace4246bc6..00000000000 --- a/notebooks/test/executed_notebooks/Storage Commands_output.ipynb +++ /dev/null @@ -1,468 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext google.cloud.bigquery" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Storage Commands\n", - "\n", - "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage.\n", - "\n", - "This notebook introduces several `gsutil` commands for interacting with Cloud Storage." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## List available commands\n", - "\n", - "The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Usage: gsutil [-D] [-DD] [-h header]... [-m] [-o] [-q] [command [opts...] args...]\r\n", - "Available commands:\r\n", - " acl Get, set, or change bucket and/or object ACLs\r\n", - " cat Concatenate object content to stdout\r\n", - " compose Concatenate a sequence of objects into a new composite object.\r\n", - " config Obtain credentials and create configuration file\r\n", - " cors Get or set a CORS JSON document for one or more buckets\r\n", - " cp Copy files and objects\r\n", - " defacl Get, set, or change default ACL on buckets\r\n", - " defstorageclass Get or set the default storage class on buckets\r\n", - " du Display object size usage\r\n", - " hash Calculate file hashes\r\n", - " help Get help about commands and topics\r\n", - " iam Get, set, or change bucket and/or object IAM permissions.\r\n", - " kms Configure Cloud KMS encryption\r\n", - " label Get, set, or change the label configuration of a bucket.\r\n", - " lifecycle Get or set lifecycle configuration for a bucket\r\n", - " logging Configure or retrieve logging on buckets\r\n", - " ls List providers, buckets, or objects\r\n", - " mb Make buckets\r\n", - " mv Move/rename objects and/or subdirectories\r\n", - " notification Configure object change notification\r\n", - " perfdiag Run performance diagnostic\r\n", - " rb Remove buckets\r\n", - " requesterpays Enable or disable requester pays for one or more buckets\r\n", - " retention Provides utilities to interact with Retention Policy feature.\r\n", - " rewrite Rewrite objects\r\n", - " rm Remove objects\r\n", - " rsync Synchronize content of two buckets/directories\r\n", - " setmeta Set metadata on already uploaded objects\r\n", - " signurl Create a signed url\r\n", - " stat Display object status\r\n", - " test Run gsutil unit/integration tests (for developers)\r\n", - " update Update to the latest gsutil release\r\n", - " version Print version info about gsutil\r\n", - " versioning Enable or suspend versioning for one or more buckets\r\n", - " web Set a main page and/or error page for one or more buckets\r\n", - "\r\n", - "Additional help topics:\r\n", - " acls Working With Access Control Lists\r\n", - " anon Accessing Public Data Without Credentials\r\n", - " apis Cloud Storage APIs\r\n", - " crc32c CRC32C and Installing crcmod\r\n", - " creds Credential Types Supporting Various Use Cases\r\n", - " dev Contributing Code to gsutil\r\n", - " encoding Filename encoding and interoperability problems\r\n", - " encryption Using Encryption Keys\r\n", - " metadata Working With Object Metadata\r\n", - " naming Object and Bucket Naming\r\n", - " options Top-Level Command-Line Options\r\n", - " prod Scripting Production Transfers\r\n", - " projects Working With Projects\r\n", - " retries Retry Handling Strategy\r\n", - " security Security and Privacy Considerations\r\n", - " subdirs How Subdirectories Work\r\n", - " support Google Cloud Storage Support\r\n", - " throttling Throttling gsutil\r\n", - " versions Object Versioning and Concurrency Control\r\n", - " wildcards Wildcard Names\r\n", - "\r\n", - "Use gsutil help for detailed help." - ] - } - ], - "source": [ - "!gsutil help" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Buckets\n", - "\n", - "Buckets are the basic containers that hold your data. Everything that you\n", - "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", - "organize your data and control access to your data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create a bucket\n", - "\n", - "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", - "you specify a globally-unique name." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# Replace the string below with a unique name for the new bucket\n", - "bucket_name = 'test-storage-bucket-1548268945185'" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Creating gs://test-storage-bucket-1548268945185/...\r\n" - ] - } - ], - "source": [ - "!gsutil mb gs://{bucket_name}/" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List buckets in a project\n", - "\n", - "Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gs://ajhamilton-scratch/\r\n", - "gs://my-new-bucket-1548180688764/\r\n", - "gs://my-new-bucket-1548208228513/\r\n", - "gs://test-storage-bucket-1548209987490/\r\n", - "gs://test-storage-bucket-1548268945185/\r\n" - ] - } - ], - "source": [ - "!gsutil ls -p ajhamilton-scratch" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Objects\n", - "\n", - "Objects are the individual pieces of data that you store in Cloud Storage.\n", - "There is no limit on the number of objects that you can create in a bucket." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Upload a local file to a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Copying file://resources/us-states.txt [Content-Type=text/plain]...\r\n", - "/ [0 files][ 0.0 B/ 637.0 B] \r" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/ [1 files][ 637.0 B/ 637.0 B] \r", - "-\r", - "\r\n", - "Operation completed over 1 objects/637.0 B. \r\n" - ] - } - ], - "source": [ - "!gsutil cp resources/us-states.txt gs://{bucket_name}/" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List blobs in a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gs://test-storage-bucket-1548268945185/us-states.txt\r\n" - ] - } - ], - "source": [ - "!gsutil ls -r gs://{bucket_name}/**" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Get a blob and display metadata\n", - "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "gs://test-storage-bucket-1548268945185/us-states.txt:\r\n", - " Creation time: Wed, 23 Jan 2019 18:42:37 GMT\r\n", - " Update time: Wed, 23 Jan 2019 18:42:37 GMT\r\n", - " Storage class: STANDARD\r\n", - " Content-Language: en\r\n", - " Content-Length: 637\r\n", - " Content-Type: text/plain\r\n", - " Hash (crc32c): AmYMRQ==\r\n", - " Hash (md5): NmfddAHdCzyvAHCifeGtwg==\r\n", - " ETag: CIKl+anHhOACEAE=\r\n", - " Generation: 1548268957749890\r\n", - " Metageneration: 1\r\n", - " ACL: [\r\n", - " {\r\n", - " \"entity\": \"project-owners-129776587519\",\r\n", - " \"projectTeam\": {\r\n", - " \"projectNumber\": \"129776587519\",\r\n", - " \"team\": \"owners\"\r\n", - " },\r\n", - " \"role\": \"OWNER\"\r\n", - " },\r\n", - " {\r\n", - " \"entity\": \"project-editors-129776587519\",\r\n", - " \"projectTeam\": {\r\n", - " \"projectNumber\": \"129776587519\",\r\n", - " \"team\": \"editors\"\r\n", - " },\r\n", - " \"role\": \"OWNER\"\r\n", - " },\r\n", - " {\r\n", - " \"entity\": \"project-viewers-129776587519\",\r\n", - " \"projectTeam\": {\r\n", - " \"projectNumber\": \"129776587519\",\r\n", - " \"team\": \"viewers\"\r\n", - " },\r\n", - " \"role\": \"READER\"\r\n", - " },\r\n", - " {\r\n", - " \"email\": \"ajhamilton@google.com\",\r\n", - " \"entity\": \"user-ajhamilton@google.com\",\r\n", - " \"role\": \"OWNER\"\r\n", - " }\r\n", - "]\r\n", - "TOTAL: 1 objects, 637 bytes (637 B)\r\n" - ] - } - ], - "source": [ - "!gsutil ls -L gs://{bucket_name}/us-states.txt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Download a blob to a local directory" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Copying gs://test-storage-bucket-1548268945185/us-states.txt...\r\n", - "/ [0 files][ 0.0 B/ 637.0 B] \r" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/ [1 files][ 637.0 B/ 637.0 B] \r", - "\r\n", - "Operation completed over 1 objects/637.0 B. \r\n" - ] - } - ], - "source": [ - "!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Cleaning up" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Delete a blob" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Removing gs://test-storage-bucket-1548268945185/us-states.txt...\r\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/ [1 objects] \r", - "\r\n", - "Operation completed over 1 objects. \r\n" - ] - } - ], - "source": [ - "!gsutil rm gs://{bucket_name}/us-states.txt" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Delete a bucket" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Removing gs://test-storage-bucket-1548268945185/...\r\n" - ] - } - ], - "source": [ - "!gsutil rm -r gs://{bucket_name}/" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Local google-cloud-bigquery development", - "language": "python", - "name": "venv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.4" - } - }, - "nbformat": 4, - "nbformat_minor": 1 -} diff --git a/notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb b/notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb deleted file mode 100644 index 7b938e3b6be..00000000000 --- a/notebooks/test/executed_notebooks/Visualize BigQuery Public Data_output.ipynb +++ /dev/null @@ -1,763 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext google.cloud.bigquery" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Vizualizing BigQuery Data in a Jupyter Notebook\n", - "\n", - "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime.\n", - "\n", - "Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and Pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Jupyter Magics to Query BigQuery Data\n", - "\n", - "The BigQuery Python client library provides a magic command that allows you to run queries with minimal code.\n", - "\n", - "The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
\n", - "
" - ], - "text/plain": [ - " year birth_count\n", - "0 2008 4255156\n", - "1 2007 4324008\n", - "2 2006 4273225\n", - "3 2005 4145619\n", - "4 2004 4118907\n", - "5 2003 4096092\n", - "6 2002 4027376\n", - "7 2001 4031531\n", - "8 2000 4063823\n", - "9 1999 3963465\n", - "10 1998 3945192\n", - "11 1997 3884329\n", - "12 1996 3894874\n", - "13 1995 3903012\n", - "14 1994 3956925" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery\n", - "SELECT\n", - " source_year AS year,\n", - " COUNT(is_male) AS birth_count\n", - "FROM `bigquery-public-data.samples.natality`\n", - "GROUP BY year\n", - "ORDER BY year DESC\n", - "LIMIT 15" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
\n", - "
" - ], - "text/plain": [ - " year birth_count\n", - "0 2008 4255156\n", - "1 2007 4324008\n", - "2 2006 4273225\n", - "3 2005 4145619\n", - "4 2004 4118907\n", - "5 2003 4096092\n", - "6 2002 4027376\n", - "7 2001 4031531\n", - "8 2000 4063823\n", - "9 1999 3963465\n", - "10 1998 3945192\n", - "11 1997 3884329\n", - "12 1996 3894874\n", - "13 1995 3903012\n", - "14 1994 3956925" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery total_births\n", - "SELECT\n", - " source_year AS year,\n", - " COUNT(is_male) AS birth_count\n", - "FROM `bigquery-public-data.samples.natality`\n", - "GROUP BY year\n", - "ORDER BY year DESC\n", - "LIMIT 15" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next cell uses the Pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [Pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with Pandas." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "total_births.plot(kind='bar', x='year', y='birth_count');" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
wdaymale_birthsfemale_births
0142935754093357
1260958405831111
2367272176412155
3466187296307782
4565830156284434
5665186366223584
6747619504530052
\n", - "
" - ], - "text/plain": [ - " wday male_births female_births\n", - "0 1 4293575 4093357\n", - "1 2 6095840 5831111\n", - "2 3 6727217 6412155\n", - "3 4 6618729 6307782\n", - "4 5 6583015 6284434\n", - "5 6 6518636 6223584\n", - "6 7 4761950 4530052" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%bigquery births_by_weekday\n", - "SELECT\n", - " wday,\n", - " SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births,\n", - " SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births\n", - "FROM `bigquery-public-data.samples.natality`\n", - "WHERE wday IS NOT NULL\n", - "GROUP BY wday\n", - "ORDER BY wday ASC" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Visualize the query results using a line chart." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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PvpolbGkpCSWL1/uoxk1Hw0mtRjavR2vzax2hefopjj2P7WbolKq0tixYxk7dqyvp+ETepurPiq7KU7z9UyUUsovaDCpK0c3xb4TtJuiUkrZNJjUlaOboma8K6VUJQ0mdbVloXZTVEqpajSY1MWJH2DfOhgyQ7spKhWgXnzxRfr27ctttzVNI7tnnnmmXlV7Z82axbJly2qMp6en88ADD7h8T2ZmJitXrmzwuRuDPs1VF5XdFH/q23kopertpZdeYs2aNZUFE/1damqqy2z5srIyMjMzSU9P57rrfN/+QoOJtxzdFHuN0m6KSjWGTx6DI9sb95gXDITxf3S7+Z577mHfvn2MHz+e6dOns3fv3hr9SBYsWMD7779PYWEhe/bs4eGHH6akpIRFixYRGRnJypUrad++Pa+++iqvvPIKJSUl9OrVi0WLFhEdHV3lfHv37uW+++4jLy+P6OhoXn31VS65xH1R2DVr1vDHP/6R06dP85e//IUJEyawbt06nn/+eT766COeeeYZ9u7dy759++jevTtff/01586d46uvvuLxxx8HYOfOnVx11VUcOHCAhx56iAceeIDCwkKmTp1KTk4O5eXlPPXUU0yb1rhPo+q9Gm85uinqwrtSAeuf//wnXbt2Ze3atRQWFnLNNdewceNG1q5dyyOPPEJhYSEAWVlZvPfee2zatIknnniC6OhoMjIyuPTSS1m4cCFglZHftGkTW7dupW/fvsydO7fG+ebMmcPf/vY3Nm/ezPPPP8+9997rcX779+9n48aNfPzxx9xzzz0uqxXv3LmTNWvW8Pbbb/O73/2OadOmkZmZWRkcdu/ezapVq9i4cSPPPvsspaWlfPrpp3Tt2pWtW7eSlZXVJJWF9crEW9pNUanG5eEKojm460cCcPXVVxMXF0dcXBxt2rThhhtuAGDgwIFs27YNsALOk08+ycmTJykoKKiRrFhQUMA333zDlClTKseKi4s9zmnq1KmEhITQu3dvLrroInbv3l1jnxtvvJFWrVq5Pcb1119PZGQkkZGRdOrUiaNHjzJw4EB+9atf8eijjzJhwgSuuOIKL/4XqhsNJt4oyNNuikoFGUc/kurteDds2FBrvxOwFszff/99Bg8ezIIFC1i3bl2V41RUVNC2bdvKToneaKqeJ3369GHLli2sXLmSJ598klGjRvHb3/7W63l5Q29z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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "births_by_weekday.plot(x='wday');" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Using Python to Query BigQuery Data\n", - "\n", - "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a Pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with Pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", - "\n", - "To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "from google.cloud import bigquery\n", - "\n", - "client = bigquery.Client()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.)." - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
pluralitycountyear
021392092007
121388662008
221372392006
321332852005
421323442004
\n", - "
" - ], - "text/plain": [ - " plurality count year\n", - "0 2 139209 2007\n", - "1 2 138866 2008\n", - "2 2 137239 2006\n", - "3 2 133285 2005\n", - "4 2 132344 2004" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sql = \"\"\"\n", - "SELECT\n", - " plurality,\n", - " COUNT(1) AS count,\n", - " year\n", - "FROM\n", - " `bigquery-public-data.samples.natality`\n", - "WHERE\n", - " NOT IS_NAN(plurality) AND plurality > 1\n", - "GROUP BY\n", - " plurality, year\n", - "ORDER BY\n", - " count DESC\n", - "\"\"\"\n", - "df = client.query(sql).to_dataframe()\n", - "df.head()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA4MAAAG8CAYAAABkJHCrAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvOIA7rQAAIABJREFUeJzt3XucXWV97/HPjwRBuYRbQJpAgxUlCAokAgKHghQISokIIoolIMrxwhFrWwVPe7BaFVvrhR61hwoSbCkqVkkRBORSqxYhEDRcpASIMClCyiWgGCHhd/5YT2QzmUkme8+ePTvP5/167des/ay1v/uZNTN7z2+vZz0rMhNJkiRJUl026HUHJEmSJEljz2JQkiRJkipkMShJkiRJFbIYlCRJkqQKWQxKkiRJUoUsBiVJkiSpQhaDkiRJklQhi0FJkiRJqpDFoCRJkiRVaGKvOzDattlmm5w2bVqvuyFJkiRJPXHzzTf/d2ZOXtt2610xOG3aNObPn9/rbkiSJElST0TEz0eyncNEJUmSJKlCFoOSJEmSVCGLQUmSJEmq0Hp3zuBQnnnmGQYGBli+fHmvu9KWjTfemKlTp7Lhhhv2uiuSJEmS1hNVFIMDAwNsttlmTJs2jYjodXfWSWbyyCOPMDAwwE477dTr7kiSJElaT1QxTHT58uVsvfXWfVcIAkQEW2+9dd8e1ZQkSZI0PlVRDAJ9WQiu0s99lyRJkjQ+VVMMSpIkSZKeYzE4yEEHHTRqF62//vrrOfLIIwGYN28eZ599NgDf/va3ueOOO0blOSRJkiSpHRaDHVqxYsWItjvqqKM444wzAItBSZIkSb1XbTG4ePFidtllF0444QSmT5/Osccey1NPPfW8bTbddNPfLl9yySWcdNJJAJx00km8613vYp999uGDH/wgN954I695zWvYc8892W+//bjrrrtWe74LLriA0047jR/96EfMmzePP/uzP2OPPfbgnnvuYa+99vrtdnfffffz7kuSJElSN1RxaYnh3HXXXZx33nnsv//+vP3tb+eLX/ziiB87MDDAj370IyZMmMATTzzBv//7vzNx4kS+973v8eEPf5hvfvObQz5uv/3246ijjuLII4/k2GOPBWDSpEnceuut7LHHHnzlK1/h5JNPHpXvT5IkSZKGU3UxuMMOO7D//vsD8La3vY1zzjlnxI9905vexIQJEwBYtmwZc+bM4e677yYieOaZZ9apH+94xzv4yle+wmc+8xm+9rWvceONN67T4yVJkiRpXVU7TBRWv2TDmu4Pvs7fJpts8tvlv/iLv+Dggw/mtttu41//9V/X+ZqAxxxzDFdccQWXXXYZM2bMYOutt16nx0uSJEnSuqq6GLz//vv5j//4DwAuuugiDjjggOet32677bjzzjt59tln+da3vjVszrJly5gyZQrQnBu4NpttthlPPvnkb+9vvPHGHH744bz73e92iKgkSZKkMVF1Mfjyl7+cL3zhC0yfPp3HHnuMd7/73c9bf/bZZ3PkkUey3377sf322w+b88EPfpAzzzyTPffcc0Szix5//PH8zd/8DXvuuSf33HMPACeccAIbbLABhx12WGfflCRJkiSNQGRmr/swqmbOnJmDrxN45513Mn369Oe1LV68mCOPPJLbbrttLLs3rE9/+tMsW7aMj33sY0OuH+p7kCRJktQbu8/dfcTbLpyzsIs9WV1E3JyZM9e2XdUTyIwXRx99NPfccw/XXnttr7siSZIkaQQW3nd/V3LHssisthicNm3auDkquKbzESVJkiTVo1tF5lCqPmdQkiRJkmplMShJkiRJFap2mKgkSZKk9d94nuil1ywGJUmSJK23xvIcvH5TfTE47YzvjGre4rNfv9ZtHnjgAU488UQeeughIoJTTz2V008/fVT7IUmSJElrUn0x2AsTJ07kb//2b9lrr7148sknmTFjBoceeii77rprr7smSZIkqRJOINMD22+/PXvttRcAm222GdOnT2fJkiU97pUkSZKkmlgM9tjixYtZsGAB++yzT6+7IkmSJKkiay0GI+L8iHg4Ila7QntE/ElEZERsU+5HRJwTEYsi4qcRsVfLtnMi4u5ym9PSPiMiFpbHnBMRUdq3ioiry/ZXR8SWo/Mtjx+//OUvOeaYY/jc5z7H5ptv3uvuSJIkSarISI4MXgDMGtwYETsAhwGt0/McAexcbqcCXyrbbgWcBewD7A2c1VLcfQl4Z8vjVj3XGcA1mbkzcE25v9545plnOOaYYzjhhBN44xvf2OvuSJIkSarMWovBzPw+8OgQqz4LfBDIlrbZwIXZuAHYIiK2Bw4Hrs7MRzPzMeBqYFZZt3lm3pCZCVwIvKEla25ZntvS3vcyk1NOOYXp06fzgQ98oNfdkSRJklShtmYTjYjZwJLM/EkZ1bnKFOCBlvsDpW1N7QNDtANsl5kPluVfANutoT+n0hyJZMcdd1yn72Ukl4IYbT/84Q/56le/yu67784ee+wBwCc+8Qle97rXjXlfJEmSpPHAi8OPvXUuBiPiRcCHaYaIjonMzIjINaw/FzgXYObMmcNuN14ccMABNAdCJUmSpP7SraLNi8OPvXaODP4esBOw6qjgVOCWiNgbWALs0LLt1NK2BDhoUPv1pX3qENsDPBQR22fmg2U46cNt9FWSJEnSKLJoa0xbftGIt13cvW50ZJ2LwcxcCGy76n5ELAZmZuZ/R8Q84LSIuJhmsphlpZi7EvhEy6QxhwFnZuajEfFEROwL/Bg4Efi7ss08YA5wdvl6aVvfoSRJkiT1ibEsMkdyaYl/Bv4DeHlEDETEKWvY/HLgXmAR8A/AewAy81HgY8BN5fbR0kbZ5svlMfcAV5T2s4FDI+Ju4A/KfUmSJEnSKFjrkcHMfMta1k9rWU7gvcNsdz5w/hDt84Hdhmh/BDhkbf2TJEmSJK27kVxnUJIkSZK0nmnr0hKSJEmS1A/Wh4leusVi8COTRjlv2Vo3Wb58OQceeCC/+c1vWLFiBcceeyx/+Zd/Obr9kCRJkqQ1sBjsgY022ohrr72WTTfdlGeeeYYDDjiAI444gn333bfXXZMkSdJ6wou4a20sBnsgIth0000BeOaZZ3jmmWco12yUJEmSRoXXA9TaOIFMj6xcuZI99tiDbbfdlkMPPZR99tmn112SJEmSVBGLwR6ZMGECt956KwMDA9x4443cdtttve6SJEmSpIpYDPbYFltswcEHH8x3v/vdXndFkiRJUkUsBntg6dKlPP744wD8+te/5uqrr2aXXXbpca8kSZIk1cQJZEZwKYjR9uCDDzJnzhxWrlzJs88+y3HHHceRRx455v2QJEmSVC+LwR545StfyYIFC3rdDUmSJEkVsxiUJEmS1HPTll804m0Xd68bVbEYlCRJknrIi8OrVywGJUmSJI2YR/DWHxaDkiRJUg8tvO/+XndBlfLSEpIkSZJUIYtBSZIkSapQ9cNE1+WE3ZFYl5N6V65cycyZM5kyZQqXXXbZqPZDkiRJktbEI4M99PnPf57p06f3uhuSJEmSKmQx2CMDAwN85zvf4R3veEevuyJJkiSpQhaDPfL+97+fv/7rv2aDDfwRSJIkSRp7ViI9cNlll7HtttsyY8aMXndFkiRJUqWqn0CmF374wx8yb948Lr/8cpYvX84TTzzB2972Nv7xH/+x112TJEnSMNZl4sF1mVSwW7w4vNbGYrAHPvnJT/LJT34SgOuvv55Pf/rTFoKSJEnjnBeH1/qm+mJwPHxqI0mSJEljrfpisNcOOuggDjrooF53Q5IkSVJlnEBGkiRJkipkMShJkiRJFXKYqCRJktYr/Tbrp9QrFoOSJElarzjrpzQyDhOVJEmSpAp5ZFCSJEnqIS8Or16pvhi8c5fpo5o3/Wd3jmi7adOmsdlmmzFhwgQmTpzI/PnzR7UfkiRJkrQm1ReDvXTdddexzTbb9LobkiRJkirkOYOSJEmSVCGLwR6JCA477DBmzJjBueee2+vuSJIkSaqMw0R75Ac/+AFTpkzh4Ycf5tBDD2WXXXbhwAMP7HW3JEmSJFXCI4M9MmXKFAC23XZbjj76aG688cYe90iSJElSTSwGe+BXv/oVTz755G+Xr7rqKnbbbbce90qSJElSTaofJjrSS0GMpoceeoijjz4agBUrVvDWt76VWbNmjXk/JEmSemldLvHVi//ZpPVd9cVgL7zkJS/hJz/5Sa+7IUmS1FPHnTnyf0UXdrEfI+XF4bW+WetfYEScDxwJPJyZu5W2vwH+EHgauAc4OTMfL+vOBE4BVgLvy8wrS/ss4PPABODLmXl2ad8JuBjYGrgZ+KPMfDoiNgIuBGYAjwBvzszFo/R9S5IkqccW3nd/r7sgVW0k5wxeAAwew3g1sFtmvhL4T+BMgIjYFTgeeEV5zBcjYkJETAC+ABwB7Aq8pWwL8Cngs5n5UuAxmkKS8vWx0v7Zsp0kSZIkaRSstRjMzO8Djw5quyozV5S7NwBTy/Js4OLM/E1m3gcsAvYut0WZeW9mPk1zJHB2RATwWuCS8vi5wBtasuaW5UuAQ8r2bcnMdh/ac/3cd0mSJEnj02jMJvp24IqyPAV4oGXdQGkbrn1r4PGWwnJV+/OyyvplZfvVRMSpETE/IuYvXbp0tfUbb7wxjzzySF8WVZnJI488wsYbb9zrrkiSJElaj3Q0gUxE/G9gBfBPo9Od9mTmucC5ADNnzlyt4ps6dSoDAwMMVSj2g4033pipU6eufUNJkiRJGqG2i8GIOIlmYplD8rlDbkuAHVo2m1raGKb9EWCLiJhYjv61br8qayAiJgKTyvbrbMMNN2SnnXZq56GSJEnqM876KY1MW8NEy8ygHwSOysynWlbNA46PiI3KLKE7AzcCNwE7R8ROEfECmklm5pUi8jrg2PL4OcClLVlzyvKxwLXZj+M8JUmSJGkcGsmlJf4ZOAjYJiIGgLNoZg/dCLi6zOlyQ2a+KzNvj4ivA3fQDB99b2auLDmnAVfSXFri/My8vTzFh4CLI+KvgAXAeaX9POCrEbGIZgKb40fh+5UkSdI62n3u7iPeduGc8XBFQEkjsdZiMDPfMkTzeUO0rdr+48DHh2i/HLh8iPZ7aWYbHdy+HHjT2vonSZIkSVp3HU0gI0mSpPWfF4eX1k+jcWkJSZIkSVKfsRiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXI6wxKkiSpJ6Ytv2jE2y7uXjekanlkUJIkSZIqZDEoSZIkSRWyGJQkSZKkClkMSpIkSVKFLAYlSZIkqUIWg5IkSZJUIYtBSZIkSaqQ1xmUJElaT+w+d/cRb7twzsIu9kRSP7AYlCRJ0hp5cXhp/WQxKEmStJ5YeN/9ve6CpD7iOYOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCXnRekiRpjO0+d/cRb7twzsIu9kRSzSwGJUmSxtjC++7vdRckyWGikiRJklQji0FJkiRJqpDFoCRJkiRVyGJQkiRJkirkBDKSJEnriWnLLxrxtou71w1JfcIjg5IkSZJUIYtBSZIkSaqQxaAkSZIkVchiUJIkSZIqZDEoSZIkSRVyNlFJktT3dp+7+4i3XThnYc9zJWk8WGsxGBHnA0cCD2fmbqVtK+BrwDSamYmPy8zHIiKAzwOvA54CTsrMW8pj5gB/XmL/KjPnlvYZwAXAC4HLgdMzM4d7jo6/Y0mStN5ZeN/9fZUrSePBSI4MXgD8X+DClrYzgGsy8+yIOKPc/xBwBLBzue0DfAnYpxR2ZwEzgQRujoh5pbj7EvBO4Mc0xeAs4Io1PIckSVJf83qAksaDtRaDmfn9iJg2qHk2cFBZngtcT1OozQYuzMwEboiILSJi+7Lt1Zn5KEBEXA3Miojrgc0z84bSfiHwBppicLjnkCRJfcphl5I0frR7zuB2mflgWf4FsF1ZngI80LLdQGlbU/vAEO1reo7VRMSpwKkAO+6447p+L5IkaYw47FKSxo+OZxMtRwFzFPrS9nNk5rmZOTMzZ06ePLmbXZEkSZKk9UK7RwYfiojtM/PBMgz04dK+BNihZbuppW0Jzw35XNV+fWmfOsT2a3oOSZLUZQ7nlKT1X7vF4DxgDnB2+XppS/tpEXExzQQyy0oxdyXwiYjYsmx3GHBmZj4aEU9ExL40E8icCPzdWp5DkiR1mcM5JWn9N5JLS/wzzVG9bSJigGZW0LOBr0fEKcDPgePK5pfTXFZiEc2lJU4GKEXfx4CbynYfXTWZDPAenru0xBXlxhqeQ5IkSZLUoZHMJvqWYVYdMsS2Cbx3mJzzgfOHaJ8P7DZE+yNDPYckSWrxkUnrsO2y7vVDktR3Op5ARpIkSZLUfywGJUmSJKlC7U4gI0mS1oXDObtq2vKLRrzt4nGQK0njgcWgJEkaMxZXkjR+OExUkiRJkipkMShJkiRJFXKYqCRJWo3DOSVp/WcxKElSH7NokyS1y2GikiRJklQhi0FJkiRJqpDDRCVJGgMO55QkjTceGZQkSZKkCnlkUJKkFrvP3X3E2y6cs7CLPZEkqbssBiVJarHwvvt73QVJksaEw0QlSZIkqUIWg5IkSZJUIYtBSZIkSaqQxaAkSZIkVchiUJIkSZIq5GyikiS18OLwkqRaeGRQkiRJkipkMShJkiRJFbIYlCRJkqQKWQxKkiRJUoUsBiVJkiSpQs4mKknqTx+ZtA7bLutePyRJ6lMeGZQkSZKkClkMSpIkSVKFLAYlSZIkqUIWg5IkSZJUIYtBSZIkSaqQs4lKkvrStOUXjXjbxd3rhiRJfcsjg5IkSZJUIYtBSZIkSaqQw0QlSd3lxeElSRqXPDIoSZIkSRWyGJQkSZKkClkMSpIkSVKFLAYlSZIkqUIWg5IkSZJUIWcTlSR1lReHlyRpfOqoGIyIPwbeASSwEDgZ2B64GNgauBn4o8x8OiI2Ai4EZgCPAG/OzMUl50zgFGAl8L7MvLK0zwI+D0wAvpyZZ3fSX0nSGngJCEmSqtL2MNGImAK8D5iZmbvRFGzHA58CPpuZLwUeoynyKF8fK+2fLdsREbuWx70CmAV8MSImRMQE4AvAEcCuwFvKtpIkSZKkDnV6zuBE4IURMRF4EfAg8FrgkrJ+LvCGsjy73KesPyQiorRfnJm/ycz7gEXA3uW2KDPvzcynaY42zu6wv5IkSZIkOigGM3MJ8GngfpoicBnNsNDHM3NF2WwAmFKWpwAPlMeuKNtv3do+6DHDta8mIk6NiPkRMX/p0qXtfkuSJEmSVI22zxmMiC1pjtTtBDwOfINmmOeYy8xzgXMBZs6cmb3ogyT1Oyd6kSSpLp1MIPMHwH2ZuRQgIv4F2B/YIiImlqN/U4ElZfslwA7AQBlWOolmIplV7au0Pma4dkmqlxO9SJKkUdDJOYP3A/tGxIvKuX+HAHcA1wHHlm3mAJeW5XnlPmX9tZmZpf34iNgoInYCdgZuBG4Cdo6InSLiBTSTzMzroL+SJEmSpKLtI4OZ+eOIuAS4BVgBLKAZqvkd4OKI+KvSdl55yHnAVyNiEfAoTXFHZt4eEV+nKSRXAO/NzJUAEXEacCXNTKXnZ+bt7fZXkiRJkvScjq4zmJlnAWcNar6XZibQwdsuB940TM7HgY8P0X45cHknfZQkSZIkra7TS0tIkiRJkvpQR0cGJUljz1k/JUnSaPDIoCRJkiRVyGJQkiRJkipkMShJkiRJFbIYlCRJkqQKWQxKkiRJUoUsBiVJkiSpQhaDkiRJklQhi0FJkiRJqpDFoCRJkiRVyGJQkiRJkipkMShJkiRJFbIYlCRJkqQKWQxKkiRJUoUsBiVJkiSpQhaDkiRJklQhi0FJkiRJqpDFoCRJkiRVyGJQkiRJkipkMShJkiRJFZrY6w5I0nrrI5PWYdtl3euHJEnSEDwyKEmSJEkV8sigJHkET5IkVcgjg5IkSZJUIY8MSuoffXYEb9ryi0a87eLudUOSJGlIHhmUJEmSpAp5ZFBS9TyCJ0mSamQxKKlvWLRJkiSNHoeJSpIkSVKFPDIoafT12UQvkiRJNfLIoCRJkiRVyGJQkiRJkirkMFGpZl0azulEL5IkSeOfRwYlSZIkqUIWg5IkSZJUIYeJShVzOKckSVK9LAalfuClGiRJkjTKHCYqSZIkSRWyGJQkSZKkCjlMVOoDntsnSZKk0dbRkcGI2CIiLomIn0XEnRHxmojYKiKujoi7y9cty7YREedExKKI+GlE7NWSM6dsf3dEzGlpnxERC8tjzomI6KS/kiRJkqRGp8NEPw98NzN3AV4F3AmcAVyTmTsD15T7AEcAO5fbqcCXACJiK+AsYB9gb+CsVQVk2eadLY+b1WF/JUmSJEl0UAxGxCTgQOA8gMx8OjMfB2YDc8tmc4E3lOXZwIXZuAHYIiK2Bw4Hrs7MRzPzMeBqYFZZt3lm3pCZCVzYkiVJkiRJ6kAnRwZ3ApYCX4mIBRHx5YjYBNguMx8s2/wC2K4sTwEeaHn8QGlbU/vAEO2riYhTI2J+RMxfunRpB9+SJEmSJNWhk2JwIrAX8KXM3BP4Fc8NCQWgHNHLDp5jRDLz3MycmZkzJ0+e3O2nkyRJkqS+10kxOAAMZOaPy/1LaIrDh8oQT8rXh8v6JcAOLY+fWtrW1D51iHZJkiRJUofaLgYz8xfAAxHx8tJ0CHAHMA9YNSPoHODSsjwPOLHMKrovsKwMJ70SOCwitiwTxxwGXFnWPRER+5ZZRE9syZIkSZIkdaDT6wz+L+CfIuIFwL3AyTQF5tcj4hTg58BxZdvLgdcBi4CnyrZk5qMR8THgprLdRzPz0bL8HuAC4IXAFeUmSZIkSepQR8VgZt4KzBxi1SFDbJvAe4fJOR84f4j2+cBunfRRkiRJkrS6Tq8zKEmSJEnqQxaDkiRJklQhi0FJkiRJqlCnE8hIavWRSeuw7bLu9UOSJElaC48MSpIkSVKFLAYlSZIkqUIOE5VG0bTlF41428Xd64YkSZK0Vh4ZlCRJkqQKWQxKkiRJUoUsBiVJkiSpQp4zqDp5CQhJkiRVziODkiRJklQhjwyqSs76KUmSpNp5ZFCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVmtjrDkhr9JFJ67Dtsu71Q5IkSVrPeGRQkiRJkirkkUGNa9OWXzTibRd3rxuSJEnSescjg5IkSZJUIYtBSZIkSaqQxaAkSZIkVchiUJIkSZIqZDEoSZIkSRWyGJQkSZKkClkMSpIkSVKFLAYlSZIkqUIWg5IkSZJUIYtBSZIkSarQxF53QOuJj0xah22Xda8fkiRJkkbEI4OSJEmSVCGPDGpUTFt+0Yi3Xdy9bkiSJEkaIY8MSpIkSVKFLAYlSZIkqUIdF4MRMSEiFkTEZeX+ThHx44hYFBFfi4gXlPaNyv1FZf20lowzS/tdEXF4S/us0rYoIs7otK+SJEmSpMZoHBk8Hbiz5f6ngM9m5kuBx4BTSvspwGOl/bNlOyJiV+B44BXALOCLpcCcAHwBOALYFXhL2VaSJEmS1KGOisGImAq8HvhyuR/Aa4FLyiZzgTeU5dnlPmX9IWX72cDFmfmbzLwPWATsXW6LMvPezHwauLhsK0mSJEnqUKdHBj8HfBB4ttzfGng8M1eU+wPAlLI8BXgAoKxfVrb/bfugxwzXvpqIODUi5kfE/KVLl3b4LUmSJEnS+q/tYjAijgQezsybR7E/bcnMczNzZmbOnDx5cq+7I0mSJEnjXifXGdwfOCoiXgdsDGwOfB7YIiImlqN/U4ElZfslwA7AQERMBCYBj7S0r9L6mOHaJUmSJEkdaPvIYGaemZlTM3MazQQw12bmCcB1wLFlsznApWV5XrlPWX9tZmZpP77MNroTsDNwI3ATsHOZnfQF5TnmtdtfSZIkSdJzOjkyOJwPARdHxF8BC4DzSvt5wFcjYhHwKE1xR2beHhFfB+4AVgDvzcyVABFxGnAlMAE4PzNv70J/JUmSJKk6o1IMZub1wPVl+V6amUAHb7MceNMwj/848PEh2i8HLh+NPqr4yKR12HZZ9/ohSZIkqae6cWRQ49i05ReNeNvF3euGJEmSpB4bjYvOS5IkSZL6jMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCEvOj9efWTSOmy7rHv9kCRJkrReshgcp6Ytv2jE2y7uXjckSZIkraccJipJkiRJFbIYlCRJkqQK1TFMtFvn33lenyRJkqQ+VUUx2K3z7zyvT5IkSVK/cpioJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFWo7WIwInaIiOsi4o6IuD0iTi/tW0XE1RFxd/m6ZWmPiDgnIhZFxE8jYq+WrDll+7sjYk5L+4yIWFgec05ERCffrCRJkiSp0cmRwRXAn2TmrsC+wHsjYlfgDOCazNwZuKbcBzgC2LncTgW+BE3xCJwF7APsDZy1qoAs27yz5XGzOuivJEmSJKlouxjMzAcz85ay/CRwJzAFmA3MLZvNBd5QlmcDF2bjBmCLiNgeOBy4OjMfzczHgKuBWWXd5pl5Q2YmcGFLliRJkiSpA6NyzmBETAP2BH4MbJeZD5ZVvwC2K8tTgAdaHjZQ2tbUPjBEuyRJkiSpQx0XgxGxKfBN4P2Z+UTrunJELzt9jhH04dSImB8R85cuXdrtp5MkSZKkvtdRMRgRG9IUgv+Umf9Smh8qQzwpXx8u7UuAHVoePrW0ral96hDtq8nMczNVJbcuAAAVXUlEQVRzZmbOnDx5ciffkiRJkiRVoZPZRAM4D7gzMz/TsmoesGpG0DnApS3tJ5ZZRfcFlpXhpFcCh0XElmXimMOAK8u6JyJi3/JcJ7ZkSZIkSZI6MLGDx+4P/BGwMCJuLW0fBs4Gvh4RpwA/B44r6y4HXgcsAp4CTgbIzEcj4mPATWW7j2bmo2X5PcAFwAuBK8pNkiRJktShtovBzPwBMNx1/w4ZYvsE3jtM1vnA+UO0zwd2a7ePkiRJkqShjcpsopIkSZKk/mIxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKmQxKEmSJEkVshiUJEmSpApZDEqSJElShSwGJUmSJKlCFoOSJEmSVCGLQUmSJEmqkMWgJEmSJFXIYlCSJEmSKjTui8GImBURd0XEoog4o9f9kSRJkqT1wbguBiNiAvAF4AhgV+AtEbFrb3slSZIkSf1vXBeDwN7Aosy8NzOfBi4GZve4T5IkSZLU9yIze92HYUXEscCszHxHuf9HwD6Zedqg7U4FTi13Xw7cNcKn2Ab471Hqrrnmmmuuueau77ndzDbXXHPNNXf0cn83MyevbaOJnfVnfMjMc4Fz1/VxETE/M2eOdn/MNddcc801d33M7Wa2ueaaa665Y5873oeJLgF2aLk/tbRJkiRJkjow3ovBm4CdI2KniHgBcDwwr8d9kiRJkqS+N66HiWbmiog4DbgSmACcn5m3j+JTrPPQUnPNNddcc82tOLeb2eaaa6655o5x7rieQEaSJEmS1B3jfZioJEmSJKkLLAYlSZIkqUIWg5IkSZJUIYtBSZIkSaqQxaAkSZLWOxExKSLeHBEfKLc3R8QWXX7OQzt8/OYR8XtDtL+yw9wXR8SLy/LkiHhjRLyik8xhnucTXcjcqfR3lw5zdoyIjctyRMTJEfF3EfHuiGj7CgsRcdSq3NEWEQdGxMvL8v4R8acR8fpRfQ5nE5XqVl5cZwNTStMSYF5m3tm7Xo29iNgbyMy8KSJ2BWYBP8vMy0f5eS7MzBNHM7NmLdeg/a/M/F5EvBXYD7gTODczn+lpByX1REScCJwFXEXzvgYwFTgU+MvMvLBLz3t/Zu7Y5mOPAz4HPAxsCJyUmTeVdbdk5l5t5v5P4AwggE8BJwG3AQcAf52Z57WZe87gJuCPgAsBMvN9beZ+OzPfUJZn0+yT62le2z+ZmRe0mXsbsHdmPhURnwJ+D/g28NrS37e3mftr4FfAFcA/A1dm5sp2sgblfg7Ym+ZSgFcCh5Tn+H1gQWb+WafPARaDAETE/8nMj3bw+MNpXmCuyczFLe1vz8zz28wM4E1AApfQ/KLOBn4G/H1mPttuf4d4rmsz87UdZmyTmf/dcv9tNL/AtwH/kG3+okXE0cC/ZeajETEZ+FtgT+AO4E8yc6DN3M8A38zMH7bz+DXkbgWcBvwXcB7wYeA1NP+YfiIzH+sg+2DgGGAHYCXwn8CXM3NRB5kfAt4CXAys2pdTaf65vjgzz243ew3PeXJmfqWDx+9CU7j+ODN/2dI+KzO/22bmWcARNC+4VwP7ANfR/NNwZWZ+vM3ceYObgIOBawEy86h2cod4ngMof2+ZeVUHOfsAd2bmExHxQpp/Hvai+Xv7RGYu6yD7fcC3MvOBdjOGyf0nmp/bi4DHgU2Bf6F504zMnNNB9kuAN/L8v7mLMvOJDvt8OPAGnv8BzKXt/v6O4Pl8j/M9blT003tcRNwF7JOZjw9q35Lm/eNlHfR18Gv7b1cBr83MTdrMvRU4IjMfLB9QXgicmZnfiogFmblnm7kLad7XXgj8HHhpZv6i7IvrMnOPNnMfAP6NpuCO0vxp4E8BMnNum7m//V4j4kfACZl5X0RsQ/M69Ko2c+/IzF3L8s3Aq1e91kTETzrIXUDzGnYszf9PuwHfAv45M/+tncySe3vJeiHN+8SUUshuSFMM7tZu9vOex2Kw409xPkHzycotwB8Cn8vMvyvrOvkU54vAtsALgCeAjYB5wOuBhzLz9DZzfzq4CXgZcBdAZrY1DKH1e42IPwf+B3ARcCQwkJl/3GZu6x/u14AbgG8Af0Dz4tDWcIyIWErzgjgZ+BrNH+yCdrIG5V4OLAQ2B6aX5a/TFBWvyszZbeZ+EngxcA3NP5H30bxRvofmDfgbbeb+J/CKwUdPytGW2zNz53Zy1/Kcnfy9vQ94L80/HnsAp2fmpWVdJ39vC0veRsAvgKktBdGPO/m7oPmn7ss0//QGzaeGxwO0+yYRETdm5t5l+Z00++RbwGHAv7ZbxJc3nldl5oqIOBd4iuYf9UNK+xvbyS3Zy2g+Ob2HZh98IzOXtpvXkvvTzHxlGeKzBPidzFxZio2fdPCzex/N69f3gdcBC2iKzaOB92Tm9W3mfo7mNfdCnv8BzInA3e2+tq/lOX2P8z2uuve48v726sEfYkXEJGB+J+9vEfEY8Dbgl4NXAV/LzO3azF2Ymbu33N8euAyYS3OUsN2/t9bf3+cVPR0WmZsBH6P5W/7TzPyviLg3M1/STt4w/f3t+90o9PdK4FOZeW1EfBP4QGb+PCK2Bq7toBh83mthNMNxj6P5sH1qZu7QZu5tmblbNENQH6R5f/t1REwAFq567ehYZlZxo3mzGer2JLCig9yFwMSyvAVwOfDZcn9BJ7nl64bAI8ALyv2JwE87yJ0H/COwC/C7wDTggbL8ux3kLmhZvgXYpKX/CzvIvatl+eZB627ttL80/yT8BXA7zSfSZwEv6yD31vI1gCWj2N+FLcsTgR+W5S1pjga1m/uzoX7u5ffhrg5yfzrMbSHwm072A7BpWZ4GzKcpCDv9e1sw1PIo/Nw2AP6Y5mjjHqXt3nbzhunvTcDksrxJh39vd7Ys3zJa+2FVn8v+OIzmiMJS4LvAHGCzDnJvoykotqR5Pd+qtG/c+v20+bs2oSy/CLi+LO/Y4e/afw7THjTFYLu5vsel73GD+0vF73HlteUe4Es0RzA/DPx9aTup3b6W7CuAg4dZ9/0Ocn8E/N6gts1oiuRO3jtvBjYsy1Nb2jem+dCs7X1RcmbQjKb5U2DxKOStbHn9ehrYvrS/oMPXhx1KP78P/CvwWLm/ADikg9xhXws7fN35FPDvNO/zf1P6/L9pjsT+faf7edWt7ZMl+9DjNJ8QPTR4RTnM3a6JmbkCIDMfj4g/BM6NiG/Q/NK2a1XmMxFxU2Y+Xe6viIi2h89k5lFlWMq5wKczc15EPJOZP++grwAvjIg9af7Zm5CZv2rpfyfjpq+PiI8CnyzLR2czXOJgoO0hazRHacjM/6T5VOtj0Zyc/Raaf3Ze2mbuBmXYxWbAphExLTMXl0+dOvl9eDYitsrMR4HfASaU/j9WjoC06/3ANRFxN80/TND8s/tSmqFA7doOOJzmhbZV0LzZtWuDLENDy349CLgkIn6X54aotOPpiHhRZj5F86bWdLb5BLmTv7dngc+W14PPRsRDMCqvu6t+zzagGeGxtDzfryJiRQe5t8Vzw3h/EhEzM3N+RLwM6PTcuyz74yrgqjLM5Qiav7lP0xzBaMd5NP/kTqB5k/xGRNwL7Esz/LkTE2n+KdmIZvgpmXl/6Xu7lkfEq7OcB9Ti1cDyDnJ9j8P3uBbVv8dl5txohnMeznNDsq+nGXbZ9nDWkn3EGtYd2EH0uxk0uWNmPhkRs2iONLXr6Ja81qHHWwN/0kHuqsybI+K1NEdyfzAKeROGWfUi4H92kPsAcHBETKf5oOQCmhEaN2VnQ9OHHRnQyWtPZn4oIl7TLOYN0UwsdDTNaKNL2s0d6omquAF/RXPS6JCVdwe5lwG/P8zzPdtB7hWUIyCD2l8M3DgK+2MT4DPApTRDXDrNu57m05VVt1Wf4mxNMxyj3dwNgY8A95fbszSfFF0E7NhBbtufaK8l9y3AQ+V2DPA9mqNCS4BTO8h9M82Qn6vLfnh9aZ9Mcw5TJ33egOYf52PKbV/KEZEOMs8DDhhmXdv9pTnXbo9BbRNphtyt7CB3o2HatwF2H8Xfj9fTDHnqNGcxcC/NUKp7W/7eNqWzT+cn0bw53gP8mKYAvJfmnJBXddjnNX1y+qIOs3+HZvgMNEevjh3u9X4dMk+nOZr9DzTF5smlfTKdffK/V9m3d1AKY5phzzcAMzrI9T3u+Tmj/R53Hb7HQX++x21X/u72ArYb5f3RlWxzzR2L3FU3zxnsUDmniMz89RDrpmTmktUf1dHzbUIzPOXhUcp7FfCazPz70cgbIn8CzT/aT41C1iSaT6kfGYWsTbNl8pHRVL7nyOYT7ok056ItycwHO8zdCngJsCgHnRDfYe6OwBPZfOo/DZhJM7zu9tF6jtESEVNphrz9Yoh1+2cHkyUMsx9+lpm3tZvZzdxhnutFNG8U93WYszmwE02hPZBDHG1qI/Nl2RylGHVd/Nm9gua8qNsy82cdd/T52S+mZQKZoX6nxwPf49aa73vcOH2Pi4g9aIaFTqI5+hM05+c+TnPe7y0dZO9JM/x0Es+fqbSj7EF9Hpz77mzzvM8e5XayH9a0f8djf/sqdzWjXV2O1xvwSnPNNXe13DNoji79DHhH+XoezfklH+gwe0dgi7I8jeZozW6j0OdRz+3WfnD/9u/Pbgz2xUya4T5HAbuMRqa55pr7vKxbaWYTHdy+Lx2eJ9etbHPNHYvc1fJGK2i832jO+7ibZuz8ruaaa25C8w/zC2mGOj3J8yci6WRimr4qrrq4H9y//fuz61Z/f59m4qPv0ZxTexnwQ5qh9juYa665o5PLGiZkojn62FZfu5ltrrljkbta1mgFjfcbzUxBuwEfBxYBP6F5s59mrrkV5/60fJ1Ac5HbDVrWjcciqFu53doP7t/+/dl1q78LWrJ2orn2IjRT819lrrnmjk4ucA7wHZrzEfcrtzeXtv/bbl+7mW2uuWP1O9x6q+acwSGuAbI3zbW+jgPuz8z9zDW3wtwLaGaA24TmmnIraKb7fy3NdP9tzV4Wz137bQLNtXFenM9d2PW2bPNCqV3MvYDu7Idu5fbV/u1yny+gD/dxWZ5AM4vdqutp3Z6ZrzDXXHNHLfcIYDYt5+cC8zLz8nbyxiLbXHPHIvd5z1FRMTjkRSojIoADs/2LP5trbj/nTgTeRDMN+SXAPjSzxd0PfCHL9Olt5F5AfxVX3doP7t/u97nf9vH5pa/X0pwXtSQzPxDN5D+3ZOYu5ppr7ujkSlq7morBt2bmReaaa2739Vtx1W/6cf/228+ui/t4Q+CdwK40w73Pz8yV0czauW22eU0qc801d7XMScCZNEdVtqP5W36Y5nIjZ2cHM5Z2K9tcc8cid7XnqaUYlLS6iNgU+CDN9aKmAk/TXGPuS5k5t5d9G0vd2g/u3+5zH0saSkRcSXOkcW6WS7dEc0mXk4DXZuZh4y3bXHPHInc1OUonH473G83FmD9KMynAMmApzUV+TzLX3IpzL6V5UZkKfAD4C2BnYC4dXBx9Df2d06X90Glut/aD+7d/f3bd3se3dek1wlxzzW0y72pnXS+zzTV3LHIH36o5MhgRlwLfopm2+Dia80AuBv6cZmz6h801t8Lcn2Tmq1ru35SZr46IDYA7sv3zP9wP3c3tq/3b5T67j80119yhMq8qeXMz86HSth3Nh0eHZuYftNPXbmaba+5Y5K5mtKrK8X5j0MUZaWaqAtgA+Jm55laa+yPggLJ8FHBly7pOPs1yP7h/+/1n11f72FxzzV0tc0vgUzTXCH0MeBS4s7Rt1W5fu5ltrrlj9TvcetuAevwqIg4AiIijaHYo2UwVHuaaW2nuu4DPRMRjNOdd/a/yHJOBL4zD/vbbfnD/dj/bfWyuueauJjMfA74CnEZz4fqtMnN6Zn4I2LuDvnYt21xzxyJ3qCeq4ga8EriRprL+AfCy0j4ZeJ+55taYu5bnPHm89bff9oP7t39/dv22j80119zVMt8H3AV8G1gMzG5Zd0u7fe1mtrnmjkXuas8zWkH9fGMc/rNnrrnjIPf+Putvv+0H92///uz6ah+ba26NucBCYNOyPA2YD5xe7i/osE9dyTbX3LHIHXyrZgKZNYmI+zNzR3PNrS03In463CqaT2Y3ar9nwz5nNfvB/dv9bPexueaaO8zjbs/MV7Tc35TmmqF30EzLv0cHfepKtrnmjkXuYBNHI6QfrOUfhu3MNbfG3PLYw2mG5gzO/VG7oe6H7ub24f7tu59dv+1jc801dzUPRcQemXkrQGb+MiKOBM4Hdm8zs9vZ5po7FrnPU00xSJ/9s2euuWOUexnNEIRbB6+IiOs7yHU/dDe33/ZvN7Pdx+aaa+5QTgRWtDZk5grgxIj4f21mdjvbXHPHIvd5aioG++2fPXPN7XpuZp6yhnVvbTcX90NXc+mz/dvNbPexueaaO5TMHFjDuh+2k9ntbHPNHYvcwTxnUJIkSZIqVNN1BiVJkiRJhcWgJEmSJFXIYlCSJEmSKmQxKElSj0TEhF73QZJUL4tBSZJGICI+GhHvb7n/8Yg4PSL+LCJuioifRsRftqz/dkTcHBG3R8SpLe2/jIi/jYifAK8Z429DkqTfshiUJGlkzqe57hMRsQFwPPALYGdgb2APYEZEHFi2f3tmzgBmAu+LiK1L+ybAjzPzVZn5g7H8BiRJalXTdQYlSWpbZi6OiEciYk+ai2QvAF4NHFaWATalKQ6/T1MAHl3adyjtjwArgW+OZd8lSRqKxaAkSSP3ZeAk4MU0RwoPAT6Zmf+vdaOIOAj4A+A1mflUuXD2xmX18sxcOVYdliRpOA4TlSRp5L4FzKI5Inhlub09IjYFiIgpEbEtMAl4rBSCuwD79qrDkiQNxyODkiSNUGY+HRHXAY+Xo3tXRcR04D8iAuCXwNuA7wLviog7gbuAG3rVZ0mShhOZ2es+SJLUF8rEMbcAb8rMu3vdH0mSOuEwUUmSRiAidgUWAddYCEqS1gceGZQkSZKkCnlkUJIkSZIqZDEoSZIkSRWyGJQkSZKkClkMSpIkSVKFLAYlSZIkqUL/H4uvUJhGZmJMAAAAAElFTkSuQmCC\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "pivot_table = df.pivot(index='year', columns='plurality', values='count')\n", - "pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7));" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Run the following query to retrieve the count of births by the number of gestation weeks." - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "sql = \"\"\"\n", - "SELECT\n", - " gestation_weeks,\n", - " COUNT(1) AS count\n", - "FROM\n", - " `bigquery-public-data.samples.natality`\n", - "WHERE\n", - " NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99\n", - "GROUP BY\n", - " gestation_weeks\n", - "ORDER BY\n", - " gestation_weeks\n", - "\"\"\"\n", - "df = client.query(sql).to_dataframe()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, chart the query results in your DataFrame." - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7))\n", - "ax.set_title('Count of Births by Gestation Weeks')\n", - "ax.set_xlabel('Gestation Weeks')\n", - "ax.set_ylabel('Count');" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### What's Next\n", - "\n", - "+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more.\n", - "\n", - "+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference)." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Local google-cloud-bigquery development", - "language": "python", - "name": "venv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.6.4" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb index a63957b1147..8fa8b6fcb55 100644 --- a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb @@ -32,7 +32,9 @@ "source": [ "## Initialize a client\n", "\n", - "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." + "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API.\n", + "\n", + "Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables." ] }, { @@ -41,7 +43,7 @@ "metadata": {}, "outputs": [], "source": [ - "client = bigquery.Client()" + "client = bigquery.Client(location=\"US\")" ] }, { @@ -52,7 +54,7 @@ "\n", "The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", "\n", - "Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + "Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." ] }, { @@ -80,9 +82,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Create a new dataset\n", + "## Run a parameterized query\n", "\n", - "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." + "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", + "\n", + "To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", + "\n", + "For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." ] }, { @@ -91,29 +97,37 @@ "metadata": {}, "outputs": [], "source": [ - "import time\n", - "\n", - "# Define a name for the new dataset.\n", - "dataset_id = 'my_new_dataset'\n", + "# Define the query\n", + "sql = \"\"\"\n", + " SELECT word, word_count\n", + " FROM `bigquery-public-data.samples.shakespeare`\n", + " WHERE corpus = @corpus\n", + " AND word_count >= @min_word_count\n", + " ORDER BY word_count DESC;\n", + "\"\"\"\n", "\n", - "# Create a DatasetReference using a chosen dataset ID.\n", - "# The project defaults to the Client's project if not specified.\n", - "dataset_ref = client.dataset(dataset_id)\n", + "# Define the parameter values in a query job configuration\n", + "job_config = bigquery.QueryJobConfig(\n", + " query_parameters=[\n", + " bigquery.ScalarQueryParameter(\"corpus\", \"STRING\", \"romeoandjuliet\"),\n", + " bigquery.ScalarQueryParameter(\"min_word_count\", \"INT64\", 250),\n", + " ]\n", + ")\n", "\n", - "# Construct a full Dataset object to send to the API.\n", - "dataset = bigquery.Dataset(dataset_ref)\n", - "# Specify the geographic location where the dataset should reside.\n", - "dataset.location = 'US'\n", + "# Start the query job\n", + "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", "\n", - "# Send the dataset to the API for creation.\n", - "dataset = client.create_dataset(dataset) # API request" + "# Return the results as a pandas DataFrame\n", + "query_job.to_dataframe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Load data from a Pandas DataFrame to a new table" + "## Create a new dataset\n", + "\n", + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." ] }, { @@ -122,31 +136,18 @@ "metadata": {}, "outputs": [], "source": [ - "records = [\n", - " {\"title\": \"The Meaning of Life\", \"release_year\": 1983},\n", - " {\"title\": \"Monty Python and the Holy Grail\", \"release_year\": 1975},\n", - " {\"title\": \"Life of Brian\", \"release_year\": 1979},\n", - " {\"title\": \"And Now for Something Completely Different\", \"release_year\": 1971},\n", - "]\n", - "\n", - "# Optionally set explicit indices.\n", - "# If indices are not specified, a column will be created for the default\n", - "# indices created by pandas.\n", - "index = [\"Q24980\", \"Q25043\", \"Q24953\", \"Q16403\"]\n", - "df = pandas.DataFrame(records, index=pandas.Index(index, name=\"wikidata_id\"))\n", - "\n", - "table_ref = dataset_ref.table(\"monty_python\")\n", - "job = client.load_table_from_dataframe(df, table_ref, location=\"US\")\n", + "# Define a name for the new dataset.\n", + "dataset_id = 'your_new_dataset'\n", "\n", - "job.result() # Waits for table load to complete.\n", - "print(\"Loaded dataframe to {}\".format(table_ref.path))" + "# The project defaults to the Client's project if not specified.\n", + "dataset = client.create_dataset(dataset_id) # API request" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Load query results to a table\n", + "## Write query results to a destination table\n", "\n", "For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation." ] @@ -174,6 +175,39 @@ "print(\"Query results loaded to table {}\".format(table_ref.path))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a pandas DataFrame to a new table" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "records = [\n", + " {\"title\": \"The Meaning of Life\", \"release_year\": 1983},\n", + " {\"title\": \"Monty Python and the Holy Grail\", \"release_year\": 1975},\n", + " {\"title\": \"Life of Brian\", \"release_year\": 1979},\n", + " {\"title\": \"And Now for Something Completely Different\", \"release_year\": 1971},\n", + "]\n", + "\n", + "# Optionally set explicit indices.\n", + "# If indices are not specified, a column will be created for the default\n", + "# indices created by pandas.\n", + "index = [\"Q24980\", \"Q25043\", \"Q24953\", \"Q16403\"]\n", + "df = pandas.DataFrame(records, index=pandas.Index(index, name=\"wikidata_id\"))\n", + "\n", + "table_ref = dataset.table(\"monty_python\")\n", + "job = client.load_table_from_dataframe(df, table_ref, location=\"US\")\n", + "\n", + "job.result() # Waits for table load to complete.\n", + "print(\"Loaded dataframe to {}\".format(table_ref.path))" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -191,7 +225,7 @@ "source": [ "source_filename = 'resources/us-states.csv'\n", "\n", - "table_ref = dataset_ref.table('us_states_from_local_file')\n", + "table_ref = dataset.table('us_states_from_local_file')\n", "job_config = bigquery.LoadJobConfig(\n", " source_format=bigquery.SourceFormat.CSV,\n", " skip_leading_rows=1,\n", @@ -252,49 +286,6 @@ "print('Loaded {} rows.'.format(destination_table.num_rows))" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run a parameterized query\n", - "\n", - "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", - "\n", - "To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", - "\n", - "For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Define the query\n", - "sql = \"\"\"\n", - " SELECT word, word_count\n", - " FROM `bigquery-public-data.samples.shakespeare`\n", - " WHERE corpus = @corpus\n", - " AND word_count >= @min_word_count\n", - " ORDER BY word_count DESC;\n", - "\"\"\"\n", - "\n", - "# Define the parameter values in a query job configuration\n", - "job_config = bigquery.QueryJobConfig(\n", - " query_parameters=[\n", - " bigquery.ScalarQueryParameter(\"corpus\", \"STRING\", \"romeoandjuliet\"),\n", - " bigquery.ScalarQueryParameter(\"min_word_count\", \"INT64\", 250),\n", - " ]\n", - ")\n", - "\n", - "# Start the query job\n", - "query_job = client.query(sql, location=\"US\", job_config=job_config)\n", - "\n", - "# Return the results as a Pandas DataFrame\n", - "query_job.to_dataframe()" - ] - }, { "cell_type": "markdown", "metadata": {}, diff --git a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb index 1131c29c452..5298b3ae004 100644 --- a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb @@ -6,7 +6,7 @@ "source": [ "# BigQuery Query Magic\n", "\n", - "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame." + "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame." ] }, { @@ -17,7 +17,7 @@ "\n", "The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", "\n", - "The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [Pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + "The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." ] }, { @@ -74,7 +74,7 @@ "metadata": {}, "outputs": [], "source": [ - "project_id = 'my-project-id'" + "project_id = 'your-project-id'" ] }, { diff --git a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb b/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb index 298491a3a22..606871bad30 100644 --- a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb +++ b/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb @@ -8,7 +8,7 @@ "\n", "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime.\n", "\n", - "Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and Pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table." + "Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table." ] }, { @@ -19,7 +19,7 @@ "\n", "The BigQuery Python client library provides a magic command that allows you to run queries with minimal code.\n", "\n", - "The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a Pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year." + "The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year." ] }, { @@ -65,7 +65,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The next cell uses the Pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [Pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with Pandas." + "The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas." ] }, { @@ -123,7 +123,7 @@ "source": [ "## Using Python to Query BigQuery Data\n", "\n", - "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a Pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with Pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", + "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", "\n", "To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." ] diff --git a/notebooks/tutorials/storage/Storage Client Library.ipynb b/notebooks/tutorials/storage/Storage Client Library.ipynb index 25465d5dbb7..7ff62cb79bc 100644 --- a/notebooks/tutorials/storage/Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Storage Client Library.ipynb @@ -81,7 +81,7 @@ "outputs": [], "source": [ "# Replace the string below with a unique name for the new bucket\n", - "bucket_name = 'my-new-bucket'\n", + "bucket_name = 'your-new-bucket'\n", "\n", "# Creates the new bucket\n", "bucket = client.create_bucket(bucket_name)\n", diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage Commands.ipynb index a8972060ad7..5e43099e8ad 100644 --- a/notebooks/tutorials/storage/Storage Commands.ipynb +++ b/notebooks/tutorials/storage/Storage Commands.ipynb @@ -59,7 +59,7 @@ "outputs": [], "source": [ "# Replace the string below with a unique name for the new bucket\n", - "bucket_name = 'my-new-bucket'" + "bucket_name = 'your-new-bucket'" ] }, { From ffadfbf274f42e9c487864d0999aa6aa06b2d222 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 25 Jan 2019 12:19:00 -0800 Subject: [PATCH 04/24] remove extra cell with explicit project name --- notebooks/rendered/executed/BigQuery Query Magic.md | 11 +++-------- notebooks/rendered/unexecuted/BigQuery Query Magic.md | 5 ----- .../tutorials/bigquery/BigQuery Query Magic.ipynb | 9 --------- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/notebooks/rendered/executed/BigQuery Query Magic.md b/notebooks/rendered/executed/BigQuery Query Magic.md index 9527df7d224..0543d2e867a 100644 --- a/notebooks/rendered/executed/BigQuery Query Magic.md +++ b/notebooks/rendered/executed/BigQuery Query Magic.md @@ -115,9 +115,9 @@ ORDER BY count DESC LIMIT 10 ``` - Executing query with job ID: 3f302a57-daa8-41ca-9e01-7fc364b69cae - Query executing: 2.44s - Query complete after 3.04s + Executing query with job ID: 77a52d0b-6a50-409c-a4dc-cc0cb4f4317a + Query executing: 0.78s + Query complete after 1.30s @@ -212,11 +212,6 @@ project_id = 'your-project-id' ``` -```python -project_id = 'your-project-id' -``` - - ```python %%bigquery --project $project_id SELECT name, SUM(number) as count diff --git a/notebooks/rendered/unexecuted/BigQuery Query Magic.md b/notebooks/rendered/unexecuted/BigQuery Query Magic.md index afe92c911f0..31080347455 100644 --- a/notebooks/rendered/unexecuted/BigQuery Query Magic.md +++ b/notebooks/rendered/unexecuted/BigQuery Query Magic.md @@ -43,11 +43,6 @@ project_id = 'your-project-id' ``` -```python -project_id = 'ajhamilton-scratch' -``` - - ```python %%bigquery --project $project_id SELECT name, SUM(number) as count diff --git a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb index 5298b3ae004..3a167d41734 100644 --- a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb @@ -77,15 +77,6 @@ "project_id = 'your-project-id'" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "project_id = 'ajhamilton-scratch'" - ] - }, { "cell_type": "code", "execution_count": null, From 29daa2f4f2015947b5656e54b30eeafc5482e501 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 25 Jan 2019 13:08:21 -0800 Subject: [PATCH 05/24] add list datasets command --- .../executed/BigQuery Shell Commands.md | 280 ++---------------- .../unexecuted/BigQuery Shell Commands.md | 12 +- .../bigquery/BigQuery Shell Commands.ipynb | 17 +- 3 files changed, 41 insertions(+), 268 deletions(-) diff --git a/notebooks/rendered/executed/BigQuery Shell Commands.md b/notebooks/rendered/executed/BigQuery Shell Commands.md index 15d82b9d2b3..ed81b8504c7 100644 --- a/notebooks/rendered/executed/BigQuery Shell Commands.md +++ b/notebooks/rendered/executed/BigQuery Shell Commands.md @@ -157,7 +157,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he bq ls --transfer_log --message_type='messageTypes:INFO,ERROR' projects/p/locations/l/transferConfigs/c/runs/r - mk Create a dataset, table, view, or transfer configuration with this + name. See 'bq help load' for more information on specifying the schema. @@ -319,7 +319,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). -The example below creates a new dataset in the US named "your_new_dataset". +The command below creates a new dataset in the US named "your_new_dataset". ```python @@ -329,269 +329,29 @@ The example below creates a new dataset in the US named "your_new_dataset". Dataset 'your-project-id:your_dataset_id' successfully created. -## Load data from a local file to a table +## List datasets -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. +The command below lists lists all datasets in your current project. ```python -!bq load --help +!bq ls ``` - Python script for interacting with BigQuery. - - - USAGE: bq [--global_flags] [--command_flags] [args] - - - load Perform a load operation of source into destination_table. - - Usage: - load [] - - The is the fully-qualified table name of table to - create, or append to if the table already exists. - - The argument can be a path to a single local file, or a - comma-separated list of URIs. - - The argument should be either the name of a JSON file or a - text schema. This schema should be omitted if the table already has - one. - - In the case that the schema is provided in text form, it should be a - comma-separated list of entries of the form name[:type], where type - will default to string if not specified. - - In the case that is a filename, it should contain a single - array object, each entry of which should be an object with properties - 'name', 'type', and (optionally) 'mode'. See the online documentation - for more detail: - https://developers.google.com/bigquery/preparing-data-for-bigquery - - Note: the case of a single-entry schema with no type specified is - ambiguous; one can use name:string to force interpretation as a - text schema. - - Examples: - bq load ds.new_tbl ./info.csv ./info_schema.json - bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json - bq load ds.small gs://mybucket/small.csv name:integer,value:string - bq load ds.small gs://mybucket/small.csv field1,field2,field3 - - Arguments: - destination_table: Destination table name. - source: Name of local file to import, or a comma-separated list of - URI paths to data to import. - schema: Either a text schema or JSON file, as above. - - Flags for load: - - /Users/ajhamilton/google-cloud-sdk/platform/bq/bq.py: - --[no]allow_jagged_rows: Whether to allow missing trailing optional columns in - CSV import data. - --[no]allow_quoted_newlines: Whether to allow quoted newlines in CSV import - data. - --[no]autodetect: Enable auto detection of schema and options for formats that - are not self describing like CSV and JSON. - --clustering_fields: Comma separated field names. Can only be specified with - time based partitioning. Data will be first partitioned and subsequently - "clustered on these fields. - --destination_kms_key: Cloud KMS key for encryption of the destination table - data. - -E,--encoding: : The character encoding used by the input - file. Options include: - ISO-8859-1 (also known as Latin-1) - UTF-8 - -F,--field_delimiter: The character that indicates the boundary between - columns in the input file. "\t" and "tab" are accepted names for tab. - --[no]ignore_unknown_values: Whether to allow and ignore extra, unrecognized - values in CSV or JSON import data. - --max_bad_records: Maximum number of bad records allowed before the entire job - fails. - (default: '0') - (an integer) - --null_marker: An optional custom string that will represent a NULL valuein - CSV import data. - --projection_fields: If sourceFormat is set to "DATASTORE_BACKUP", indicates - which entity properties to load into BigQuery from a Cloud Datastore backup. - Property names are case sensitive and must refer to top-level properties. - (default: '') - (a comma separated list) - --quote: Quote character to use to enclose records. Default is ". To indicate - no quote character at all, use an empty string. - --[no]replace: If true erase existing contents before loading new data. - (default: 'false') - --[no]require_partition_filter: Whether to require partition filter for - queries over this table. Only apply to partitioned table. - --schema: Either a filename or a comma-separated list of fields in the form - name[:type]. - --schema_update_option: Can be specified when append to a table, or replace a - table partition. When specified, the schema of the destination table will be - updated with the schema of the new data. One or more of the following - options can be specified: - ALLOW_FIELD_ADDITION: allow new fields to be added - ALLOW_FIELD_RELAXATION: allow relaxing required fields to nullable; - repeat this option to specify a list of values - --skip_leading_rows: The number of rows at the beginning of the source file to - skip. - (an integer) - --source_format: - : Format of - source data. Options include: - CSV - NEWLINE_DELIMITED_JSON - DATASTORE_BACKUP - AVRO - PARQUET - ORC (experimental) - --time_partitioning_expiration: Enables time based partitioning on the table - and sets the number of seconds for which to keep the storage for the - partitions in the table. The storage in a partition will have an expiration - time of its partition time plus this value. A negative number means no - expiration. - (an integer) - --time_partitioning_field: Enables time based partitioning on the table and - the table will be partitioned based on the value of this field. If time - based partitioning is enabled without this value, the table will be - partitioned based on the loading time. - --time_partitioning_type: Enables time based partitioning on the table and set - the type. The only type accepted is DAY, which will generate one partition - per day. - - gflags: - --flagfile: Insert flag definitions from the given file into the command line. - (default: '') - --undefok: comma-separated list of flag names that it is okay to specify on - the command line even if the program does not define a flag with that name. - IMPORTANT: flags in this list that have arguments MUST use the --flag=value - format. - (default: '') - - - Global flags: - - bq_auth_flags: - --application_default_credential_file: Only for the gcloud wrapper use. - (default: '') - --credential_file: Only for the gcloud wrapper use. - (default: '/Users/ajhamilton/.bigquery.v2.token') - --service_account: Only for the gcloud wrapper use. - (default: '') - --service_account_credential_file: Only for the gcloud wrapper use. - --service_account_private_key_file: Only for the gcloud wrapper use. - (default: '') - --service_account_private_key_password: Only for the gcloud wrapper use. - (default: 'notasecret') - --[no]use_gce_service_account: Only for the gcloud wrapper use. - (default: 'false') - - bq_flags: - --api: API endpoint to talk to. - (default: 'https://www.googleapis.com') - --api_version: API version to use. - (default: 'v2') - --apilog: Log all API requests and responses to the file specified by this - flag. Also accepts "stdout" and "stderr". Specifying the empty string will - direct to stdout. - --bigqueryrc: Path to configuration file. The configuration file specifies new - defaults for any flags, and can be overrridden by specifying the flag on the - command line. If the --bigqueryrc flag is not specified, the BIGQUERYRC - environment variable is used. If that is not specified, the path - "~/.bigqueryrc" is used. - (default: '/Users/ajhamilton/.bigqueryrc') - --ca_certificates_file: Location of CA certificates file. - (default: '') - --dataset_id: Default dataset reference to use for requests (Ignored when not - applicable.). Can be set as "project:dataset" or "dataset". If project is - missing, the value of the project_id flag will be used. - (default: '') - --[no]debug_mode: Show tracebacks on Python exceptions. - (default: 'false') - --[no]disable_ssl_validation: Disables HTTPS certificates validation. This is - off by default. - (default: 'false') - --discovery_file: Filename for JSON document to read for discovery. - (default: '') - --[no]enable_gdrive: When set to true, requests new OAuth token with GDrive - scope. When set to false, requests new OAuth token without GDrive scope. - --[no]fingerprint_job_id: Whether to use a job id that is derived from a - fingerprint of the job configuration. This will prevent the same job from - running multiple times accidentally. - (default: 'false') - --format: : Format for command output. - Options include: - pretty: formatted table output - sparse: simpler table output - prettyjson: easy-to-read JSON format - json: maximally compact JSON - csv: csv format with header - The first three are intended to be human-readable, and the latter three are - for passing to another program. If no format is selected, one will be chosen - based on the command run. - --[no]headless: Whether this bq session is running without user interaction. - This affects behavior that expects user interaction, like whether debug_mode - will break into the debugger and lowers the frequency of informational - printing. - (default: 'false') - --httplib2_debuglevel: Instruct httplib2 to print debugging messages by - setting debuglevel to the given value. - --job_id: A unique job_id to use for the request. If not specified, this - client will generate a job_id. Applies only to commands that launch jobs, - such as cp, extract, load, and query. - --job_property: Additional key-value pairs to include in the properties field - of the job configuration; - repeat this option to specify a list of values - --location: Default geographic location to use when creating datasets or - determining where jobs should run (Ignored when not applicable.) - --max_rows_per_request: Specifies the max number of rows to return per read. - (an integer) - --project_id: Default project to use for requests. - (default: '') - --proxy_address: The name or IP address of the proxy host to use for - connecting to GCP. - (default: '') - --proxy_password: The password to use when authenticating with proxy host. - (default: '') - --proxy_port: The port number to use to connect to the proxy host. - (default: '') - --proxy_username: The user name to use when authenticating with proxy host. - (default: '') - -q,--[no]quiet: If True, ignore status updates while jobs are running. - (default: 'false') - -sync,--[no]synchronous_mode: If True, wait for command completion before - returning, and use the job completion status for error codes. If False, - simply create the job, and use the success of job creation as the error - code. - (default: 'true') - --trace: A tracing token of the form "token:" to include in api - requests. - - google.apputils.app: - -?,--[no]help: show this help - --[no]helpshort: show usage only for this module - --[no]helpxml: like --help, but generates XML output - --[no]run_with_pdb: Set to true for PDB debug mode - (default: 'false') - --[no]run_with_profiling: Set to true for profiling the script. Execution will - be slower, and the output format might change over time. - (default: 'false') - --[no]show_build_data: show build data and exit - --[no]use_cprofile_for_profiling: Use cProfile instead of the profile module - for profiling. This has no effect unless --run_with_profiling is set. - (default: 'true') - - gflags: - --flagfile: Insert flag definitions from the given file into the command line. - (default: '') - --undefok: comma-separated list of flag names that it is okay to specify on - the command line even if the program does not define a flag with that name. - IMPORTANT: flags in this list that have arguments MUST use the --flag=value - format. - (default: '') - - Run 'bq help' to see the list of available commands. + datasetId + ------------------------------ + coast + my_new_dataset_1548207931814 + test_dataset + test_dataset_1544925728787 + test_dataset_1544925753705 + your_dataset_id + your_new_dataset + +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. ```python @@ -599,7 +359,7 @@ The example below demonstrates how to load a local CSV file into a new or existi ``` Upload complete. - Waiting on bqjob_r42e105decd46e2a1_0000016880baeb55_1 ... (0s) Current status: DONE + Waiting on bqjob_ra9f2e0c7f522f31_0000016886cd0676_1 ... (1s) Current status: DONE ## Load data from Google Cloud Storage to a table @@ -611,7 +371,7 @@ The example below demonstrates how to load a local CSV file into a new or existi !bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' ``` - Waiting on bqjob_r52ccf09d3eb8c617_0000016880bb0711_1 ... (2s) Current status: DONE + Waiting on bqjob_r3b5763d92c082dc0_0000016886cd2014_1 ... (0s) Current status: DONE ## Run a query diff --git a/notebooks/rendered/unexecuted/BigQuery Shell Commands.md b/notebooks/rendered/unexecuted/BigQuery Shell Commands.md index f6a0d1d976d..c370e294f7b 100644 --- a/notebooks/rendered/unexecuted/BigQuery Shell Commands.md +++ b/notebooks/rendered/unexecuted/BigQuery Shell Commands.md @@ -16,22 +16,26 @@ To view the available commands for the BigQuery command-line tool, use the `--he A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). -The example below creates a new dataset in the US named "your_new_dataset". +The command below creates a new dataset in the US named "your_new_dataset". ```python !bq --location=US mk --dataset "your_dataset_id" ``` -## Load data from a local file to a table +## List datasets -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. +The command below lists lists all datasets in your current project. ```python -!bq load --help +!bq ls ``` +## Load data from a local file to a table + +The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + ```python !bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv' diff --git a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb b/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb index 84491817746..1bec9143a04 100644 --- a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb @@ -35,7 +35,7 @@ "\n", "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", "\n", - "The example below creates a new dataset in the US named \"your_new_dataset\"." + "The command below creates a new dataset in the US named \"your_new_dataset\"." ] }, { @@ -51,9 +51,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Load data from a local file to a table\n", + "## List datasets\n", "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + "The command below lists lists all datasets in your current project." ] }, { @@ -62,7 +62,16 @@ "metadata": {}, "outputs": [], "source": [ - "!bq load --help" + "!bq ls" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Load data from a local file to a table\n", + "\n", + "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." ] }, { From 7979e22c9be300231b21b584252dc077c6962409 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Mon, 28 Jan 2019 10:20:00 -0800 Subject: [PATCH 06/24] rename rendered markdown files and remove styles --- .../rendered/executed/BigQuery Query Magic.md | 588 ------------------ .../Visualize BigQuery Public Data.md | 514 --------------- ...{BigQuery Basics.md => bigquery-basics.md} | 270 ++++---- .../rendered/executed/bigquery-query-magic.md | 514 +++++++++++++++ ...Commands.md => bigquery-shell-commands.md} | 27 +- ...t Library.md => storage-client-library.md} | 4 +- ...torage Commands.md => storage-commands.md} | 10 +- .../visualize-bigquery-public-data_10_0.png} | Bin .../visualize-bigquery-public-data_16_0.png} | Bin .../visualize-bigquery-public-data_20_0.png} | Bin .../visualize-bigquery-public-data_6_0.png} | Bin .../visualize-bigquery-public-data.md | 466 ++++++++++++++ ...{BigQuery Basics.md => bigquery-basics.md} | 2 +- ...Query Magic.md => bigquery-query-magic.md} | 0 ...Commands.md => bigquery-shell-commands.md} | 0 ...t Library.md => storage-client-library.md} | 0 ...torage Commands.md => storage-commands.md} | 0 ...a.md => visualize-bigquery-public-data.md} | 4 +- 18 files changed, 1127 insertions(+), 1272 deletions(-) delete mode 100644 notebooks/rendered/executed/BigQuery Query Magic.md delete mode 100644 notebooks/rendered/executed/Visualize BigQuery Public Data.md rename notebooks/rendered/executed/{BigQuery Basics.md => bigquery-basics.md} (79%) create mode 100644 notebooks/rendered/executed/bigquery-query-magic.md rename notebooks/rendered/executed/{BigQuery Shell Commands.md => bigquery-shell-commands.md} (92%) rename notebooks/rendered/executed/{Storage Client Library.md => storage-client-library.md} (97%) rename notebooks/rendered/executed/{Storage Commands.md => storage-commands.md} (94%) rename notebooks/rendered/executed/{Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_10_0.png => visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png} (100%) rename notebooks/rendered/executed/{Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_16_0.png => visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png} (100%) rename notebooks/rendered/executed/{Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_20_0.png => visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png} (100%) rename notebooks/rendered/executed/{Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_6_0.png => visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png} (100%) create mode 100644 notebooks/rendered/executed/visualize-bigquery-public-data.md rename notebooks/rendered/unexecuted/{BigQuery Basics.md => bigquery-basics.md} (99%) rename notebooks/rendered/unexecuted/{BigQuery Query Magic.md => bigquery-query-magic.md} (100%) rename notebooks/rendered/unexecuted/{BigQuery Shell Commands.md => bigquery-shell-commands.md} (100%) rename notebooks/rendered/unexecuted/{Storage Client Library.md => storage-client-library.md} (100%) rename notebooks/rendered/unexecuted/{Storage Commands.md => storage-commands.md} (100%) rename notebooks/rendered/unexecuted/{Visualize BigQuery Public Data.md => visualize-bigquery-public-data.md} (98%) diff --git a/notebooks/rendered/executed/BigQuery Query Magic.md b/notebooks/rendered/executed/BigQuery Query Magic.md deleted file mode 100644 index 0543d2e867a..00000000000 --- a/notebooks/rendered/executed/BigQuery Query Magic.md +++ /dev/null @@ -1,588 +0,0 @@ - -# BigQuery Query Magic - -Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. - -## Run a query on a public dataset - -The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. - -The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). - - -```python -%%bigquery -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - -## Display verbose output - -As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion. - - -```python -%%bigquery --verbose -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - - Executing query with job ID: 77a52d0b-6a50-409c-a4dc-cc0cb4f4317a - Query executing: 0.78s - Query complete after 1.30s - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - -## Explicitly specify a project - -By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. - - -```python -project_id = 'your-project-id' -``` - - -```python -%%bigquery --project $project_id -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - -## Assign the query results to a variable - -If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command. - - -```python -%%bigquery df -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - - -```python -df -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - -## Run a parameterized query - -Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. - - -```python -params = {"limit": 10} -``` - - -```python -%%bigquery --params $params -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT @limit -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data.md b/notebooks/rendered/executed/Visualize BigQuery Public Data.md deleted file mode 100644 index da41e68c022..00000000000 --- a/notebooks/rendered/executed/Visualize BigQuery Public Data.md +++ /dev/null @@ -1,514 +0,0 @@ - -# Vizualizing BigQuery Data in a Jupyter Notebook - -[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. - -Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. - -## Using Jupyter Magics to Query BigQuery Data - -The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. - -The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. - - -```python -%%bigquery -SELECT - source_year AS year, - COUNT(is_male) AS birth_count -FROM `bigquery-public-data.samples.natality` -GROUP BY year -ORDER BY year DESC -LIMIT 15 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
-
- - - -The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. - - -```python -%%bigquery total_births -SELECT - source_year AS year, - COUNT(is_male) AS birth_count -FROM `bigquery-public-data.samples.natality` -GROUP BY year -ORDER BY year DESC -LIMIT 15 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
-
- - - -The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. - - -```python -total_births.plot(kind='bar', x='year', y='birth_count'); -``` - - -![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_6_0.png) - - -Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. - - -```python -%%bigquery births_by_weekday -SELECT - wday, - SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, - SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births -FROM `bigquery-public-data.samples.natality` -WHERE wday IS NOT NULL -GROUP BY wday -ORDER BY wday ASC -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wdaymale_birthsfemale_births
0142935754093357
1260958405831111
2367272176412155
3466187296307782
4565830156284434
5665186366223584
6747619504530052
-
- - - -Visualize the query results using a line chart. - - -```python -births_by_weekday.plot(x='wday'); -``` - - -![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_10_0.png) - - -## Using Python to Query BigQuery Data - -Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. - -To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. - - -```python -from google.cloud import bigquery - -client = bigquery.Client() -``` - -Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). - - -```python -sql = """ -SELECT - plurality, - COUNT(1) AS count, - year -FROM - `bigquery-public-data.samples.natality` -WHERE - NOT IS_NAN(plurality) AND plurality > 1 -GROUP BY - plurality, year -ORDER BY - count DESC -""" -df = client.query(sql).to_dataframe() -df.head() -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pluralitycountyear
021392092007
121388662008
221372392006
321332852005
421323442004
-
- - - -To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. - - -```python -pivot_table = df.pivot(index='year', columns='plurality', values='count') -pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); -``` - - -![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_16_0.png) - - -Run the following query to retrieve the count of births by the number of gestation weeks. - - -```python -sql = """ -SELECT - gestation_weeks, - COUNT(1) AS count -FROM - `bigquery-public-data.samples.natality` -WHERE - NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 -GROUP BY - gestation_weeks -ORDER BY - gestation_weeks -""" -df = client.query(sql).to_dataframe() -``` - -Finally, chart the query results in your DataFrame. - - -```python -ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) -ax.set_title('Count of Births by Gestation Weeks') -ax.set_xlabel('Gestation Weeks') -ax.set_ylabel('Count'); -``` - - -![png](Visualize%20BigQuery%20Public%20Data_files/Visualize%20BigQuery%20Public%20Data_20_0.png) - - -### What's Next - -+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. - -+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). diff --git a/notebooks/rendered/executed/BigQuery Basics.md b/notebooks/rendered/executed/bigquery-basics.md similarity index 79% rename from notebooks/rendered/executed/BigQuery Basics.md rename to notebooks/rendered/executed/bigquery-basics.md index 3f518c502b3..9819b9be3c2 100644 --- a/notebooks/rendered/executed/BigQuery Basics.md +++ b/notebooks/rendered/executed/bigquery-basics.md @@ -49,68 +49,56 @@ df
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
name
0Mary
1Ruby
2Annie
3Willie
4Ruth
5Gladys
6Maria
7Frances
8Margaret
9Helen
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
name
0Mary
1Ruby
2Annie
3Willie
4Ruth
5Gladys
6Maria
7Frances
8Margaret
9Helen
@@ -131,7 +119,7 @@ sql = """ SELECT word, word_count FROM `bigquery-public-data.samples.shakespeare` WHERE corpus = @corpus - AND word_count >= @min_word_count + AND word_count >= @min_word_count ORDER BY word_count DESC; """ @@ -154,89 +142,77 @@ query_job.to_dataframe()
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
wordword_count
0the614
1I577
2and490
3to486
4a407
5of367
6my314
7is307
8in291
9you271
10that270
11me263
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
wordword_count
0the614
1I577
2and490
3to486
4a407
5of367
6my314
7is307
8in291
9you271
10that270
11me263
@@ -371,7 +347,7 @@ destination_table = client.get_table(table_ref) print('Loaded {} rows.'.format(destination_table.num_rows)) ``` - Starting job 4c081f09-7351-4d0a-a5bd-90b6ce36371b + Starting job ae46d9d4-5d55-45c5-b812-2c23250049b2 Job finished. Loaded 50 rows. diff --git a/notebooks/rendered/executed/bigquery-query-magic.md b/notebooks/rendered/executed/bigquery-query-magic.md new file mode 100644 index 00000000000..17deb6bc1a8 --- /dev/null +++ b/notebooks/rendered/executed/bigquery-query-magic.md @@ -0,0 +1,514 @@ + +# BigQuery Query Magic + +Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. + +## Run a query on a public dataset + +The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. + +The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). + + +```python +%%bigquery +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Display verbose output + +As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion. + + +```python +%%bigquery --verbose +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + Executing query with job ID: de0ef4a2-c6b0-4622-8404-d248d3c980a3 + Query executing: 0.55s + Query complete after 1.07s + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Explicitly specify a project + +By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. + + +```python +project_id = 'your-project-id' +``` + + +```python +%%bigquery --project $project_id +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Assign the query results to a variable + +If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command. + + +```python +%%bigquery df +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT 10 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + + +```python +df +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
+ + + +## Run a parameterized query + +Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. + + +```python +params = {"limit": 10} +``` + + +```python +%%bigquery --params $params +SELECT name, SUM(number) as count +FROM `bigquery-public-data.usa_names.usa_1910_current` +GROUP BY name +ORDER BY count DESC +LIMIT @limit +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
+
diff --git a/notebooks/rendered/executed/BigQuery Shell Commands.md b/notebooks/rendered/executed/bigquery-shell-commands.md similarity index 92% rename from notebooks/rendered/executed/BigQuery Shell Commands.md rename to notebooks/rendered/executed/bigquery-shell-commands.md index ed81b8504c7..e763a61f83d 100644 --- a/notebooks/rendered/executed/BigQuery Shell Commands.md +++ b/notebooks/rendered/executed/bigquery-shell-commands.md @@ -15,7 +15,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he Python script for interacting with BigQuery. - USAGE: bq [--global_flags] [--command_flags] [args] + USAGE: bq [--global_flags] [--command_flags] [args] Any of the following commands: @@ -70,13 +70,13 @@ To view the available commands for the BigQuery command-line tool, use the `--he bq head -s 5 -n 10 dataset.table help Help for all or selected command: - bq help [] + bq help [] To retrieve help with global flags: bq --help To retrieve help with flags only from the main module: - bq --helpshort [] + bq --helpshort [] init Authenticate and create a default .bigqueryrc file. @@ -97,12 +97,12 @@ To view the available commands for the BigQuery command-line tool, use the `--he load Perform a load operation of source into destination_table. Usage: - load [] + load [] The is the fully-qualified table name of table to create, or append to if the table already exists. - The argument can be a path to a single local file, or a + The argument can be a path to a single local file, or a comma-separated list of URIs. The argument should be either the name of a JSON file or a @@ -157,7 +157,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he bq ls --transfer_log --message_type='messageTypes:INFO,ERROR' projects/p/locations/l/transferConfigs/c/runs/r - + mk Create a dataset, table, view, or transfer configuration with this name. See 'bq help load' for more information on specifying the schema. @@ -211,10 +211,10 @@ To view the available commands for the BigQuery command-line tool, use the `--he partition Copies source tables into partitioned tables. - Usage: bq partition - + Usage: bq partition + - Copies tables of the format to a + Copies tables of the format to a destination partitioned table, with the date suffix of the source tables becoming the partition date of the destination table partitions. @@ -308,11 +308,11 @@ To view the available commands for the BigQuery command-line tool, use the `--he Arguments: job_id: Job ID to wait on. - secs: Number of seconds to wait (must be >= 0). + secs: Number of seconds to wait (must be >= 0). Run 'bq --help' to get help for global flags. - Run 'bq help ' to get help for . + Run 'bq help ' to get help for . ## Create a new dataset @@ -359,7 +359,7 @@ The example below demonstrates how to load a local CSV file into a new or existi ``` Upload complete. - Waiting on bqjob_ra9f2e0c7f522f31_0000016886cd0676_1 ... (1s) Current status: DONE + Waiting on bqjob_r735032bbeffc13dd_0000016895acdf56_1 ... (1s) Current status: DONE ## Load data from Google Cloud Storage to a table @@ -371,7 +371,7 @@ The example below demonstrates how to load a local CSV file into a new or existi !bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' ``` - Waiting on bqjob_r3b5763d92c082dc0_0000016886cd2014_1 ... (0s) Current status: DONE + Waiting on bqjob_r4988ae2c001c168b_0000016895acf9e5_1 ... (1s) Current status: DONE ## Run a query @@ -386,3 +386,4 @@ The following code deletes the dataset created for this tutorial, including all ```python !bq rm -r -f --dataset your_dataset_id ``` +
\ No newline at end of file diff --git a/notebooks/rendered/executed/Storage Client Library.md b/notebooks/rendered/executed/storage-client-library.md similarity index 97% rename from notebooks/rendered/executed/Storage Client Library.md rename to notebooks/rendered/executed/storage-client-library.md index df819ed9f4f..5a7baa4e088 100644 --- a/notebooks/rendered/executed/Storage Client Library.md +++ b/notebooks/rendered/executed/storage-client-library.md @@ -125,9 +125,9 @@ print('\tUpdated: {}'.format(blob.updated)) ``` Select metadata for blob us-states.txt: - ID: your-new-bucket/us-states.txt/1548348088257223 + ID: your-new-bucket/us-states.txt/1548699437748619 Size: 637 bytes - Updated: 2019-01-24 16:41:28.256000+00:00 + Updated: 2019-01-28 18:17:17.748000+00:00 ### Download a blob to a local directory diff --git a/notebooks/rendered/executed/Storage Commands.md b/notebooks/rendered/executed/storage-commands.md similarity index 94% rename from notebooks/rendered/executed/Storage Commands.md rename to notebooks/rendered/executed/storage-commands.md index 7ba4de6ac32..9e32be3d05a 100644 --- a/notebooks/rendered/executed/Storage Commands.md +++ b/notebooks/rendered/executed/storage-commands.md @@ -74,7 +74,7 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help versions Object Versioning and Concurrency Control wildcards Wildcard Names - Use gsutil help for detailed help. + Use gsutil help for detailed help. ## Buckets @@ -155,16 +155,16 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada ``` gs://your-new-bucket/us-states.txt: - Creation time: Thu, 24 Jan 2019 16:40:54 GMT - Update time: Thu, 24 Jan 2019 16:40:54 GMT + Creation time: Mon, 28 Jan 2019 18:17:01 GMT + Update time: Mon, 28 Jan 2019 18:17:01 GMT Storage class: STANDARD Content-Language: en Content-Length: 637 Content-Type: text/plain Hash (crc32c): AmYMRQ== Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CO63hf7thuACEAE= - Generation: 1548348054133742 + ETag: CMnp7faKkeACEAE= + Generation: 1548699421078729 Metageneration: 1 ACL: [ { diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_10_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png similarity index 100% rename from notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_10_0.png rename to notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_16_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png similarity index 100% rename from notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_16_0.png rename to notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_20_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png similarity index 100% rename from notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_20_0.png rename to notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png diff --git a/notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_6_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png similarity index 100% rename from notebooks/rendered/executed/Visualize BigQuery Public Data_files/Visualize BigQuery Public Data_6_0.png rename to notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png diff --git a/notebooks/rendered/executed/visualize-bigquery-public-data.md b/notebooks/rendered/executed/visualize-bigquery-public-data.md new file mode 100644 index 00000000000..39afe255d69 --- /dev/null +++ b/notebooks/rendered/executed/visualize-bigquery-public-data.md @@ -0,0 +1,466 @@ + +# Vizualizing BigQuery Data in a Jupyter Notebook + +[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. + +Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. + +## Using Jupyter Magics to Query BigQuery Data + +The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. + +The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. + + +```python +%%bigquery +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
+
+ + + +The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. + + +```python +%%bigquery total_births +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
+
+ + + +The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. + + +```python +total_births.plot(kind='bar', x='year', y='birth_count'); +``` + + +![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png) + + +Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. + + +```python +%%bigquery births_by_weekday +SELECT + wday, + SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, + SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births +FROM `bigquery-public-data.samples.natality` +WHERE wday IS NOT NULL +GROUP BY wday +ORDER BY wday ASC +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
wdaymale_birthsfemale_births
0142935754093357
1260958405831111
2367272176412155
3466187296307782
4565830156284434
5665186366223584
6747619504530052
+
+ + + +Visualize the query results using a line chart. + + +```python +births_by_weekday.plot(x='wday'); +``` + + +![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png) + + +## Using Python to Query BigQuery Data + +Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. + +To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. + + +```python +from google.cloud import bigquery + +client = bigquery.Client() +``` + +Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). + + +```python +sql = """ +SELECT + plurality, + COUNT(1) AS count, + year +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(plurality) AND plurality > 1 +GROUP BY + plurality, year +ORDER BY + count DESC +""" +df = client.query(sql).to_dataframe() +df.head() +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
pluralitycountyear
021392092007
121388662008
221372392006
321332852005
421323442004
+
+ + + +To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. + + +```python +pivot_table = df.pivot(index='year', columns='plurality', values='count') +pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); +``` + + +![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png) + + +Run the following query to retrieve the count of births by the number of gestation weeks. + + +```python +sql = """ +SELECT + gestation_weeks, + COUNT(1) AS count +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 +GROUP BY + gestation_weeks +ORDER BY + gestation_weeks +""" +df = client.query(sql).to_dataframe() +``` + +Finally, chart the query results in your DataFrame. + + +```python +ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) +ax.set_title('Count of Births by Gestation Weeks') +ax.set_xlabel('Gestation Weeks') +ax.set_ylabel('Count'); +``` + + +![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png) + + +### What's Next + ++ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. + ++ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). diff --git a/notebooks/rendered/unexecuted/BigQuery Basics.md b/notebooks/rendered/unexecuted/bigquery-basics.md similarity index 99% rename from notebooks/rendered/unexecuted/BigQuery Basics.md rename to notebooks/rendered/unexecuted/bigquery-basics.md index 15a69ca7426..8a45e176d9e 100644 --- a/notebooks/rendered/unexecuted/BigQuery Basics.md +++ b/notebooks/rendered/unexecuted/bigquery-basics.md @@ -60,7 +60,7 @@ sql = """ SELECT word, word_count FROM `bigquery-public-data.samples.shakespeare` WHERE corpus = @corpus - AND word_count >= @min_word_count + AND word_count >= @min_word_count ORDER BY word_count DESC; """ diff --git a/notebooks/rendered/unexecuted/BigQuery Query Magic.md b/notebooks/rendered/unexecuted/bigquery-query-magic.md similarity index 100% rename from notebooks/rendered/unexecuted/BigQuery Query Magic.md rename to notebooks/rendered/unexecuted/bigquery-query-magic.md diff --git a/notebooks/rendered/unexecuted/BigQuery Shell Commands.md b/notebooks/rendered/unexecuted/bigquery-shell-commands.md similarity index 100% rename from notebooks/rendered/unexecuted/BigQuery Shell Commands.md rename to notebooks/rendered/unexecuted/bigquery-shell-commands.md diff --git a/notebooks/rendered/unexecuted/Storage Client Library.md b/notebooks/rendered/unexecuted/storage-client-library.md similarity index 100% rename from notebooks/rendered/unexecuted/Storage Client Library.md rename to notebooks/rendered/unexecuted/storage-client-library.md diff --git a/notebooks/rendered/unexecuted/Storage Commands.md b/notebooks/rendered/unexecuted/storage-commands.md similarity index 100% rename from notebooks/rendered/unexecuted/Storage Commands.md rename to notebooks/rendered/unexecuted/storage-commands.md diff --git a/notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md b/notebooks/rendered/unexecuted/visualize-bigquery-public-data.md similarity index 98% rename from notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md rename to notebooks/rendered/unexecuted/visualize-bigquery-public-data.md index 16785c06716..542f0cf7a76 100644 --- a/notebooks/rendered/unexecuted/Visualize BigQuery Public Data.md +++ b/notebooks/rendered/unexecuted/visualize-bigquery-public-data.md @@ -91,7 +91,7 @@ SELECT FROM `bigquery-public-data.samples.natality` WHERE - NOT IS_NAN(plurality) AND plurality > 1 + NOT IS_NAN(plurality) AND plurality > 1 GROUP BY plurality, year ORDER BY @@ -120,7 +120,7 @@ SELECT FROM `bigquery-public-data.samples.natality` WHERE - NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 + NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 GROUP BY gestation_weeks ORDER BY From 422c8c6075e75535554c1e5e3da0e1ec5f0bd606 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Mon, 28 Jan 2019 13:42:24 -0800 Subject: [PATCH 07/24] content fixes per Frank's comments --- .../rendered/executed/bigquery-basics.md | 22 ++++++- .../rendered/executed/bigquery-query-magic.md | 6 +- .../executed/bigquery-shell-commands.md | 6 +- .../executed/storage-client-library.md | 52 ++++++++------- .../rendered/executed/storage-commands.md | 14 ++--- .../rendered/unexecuted/bigquery-basics.md | 17 +++++ .../unexecuted/storage-client-library.md | 45 +++++++------ .../rendered/unexecuted/storage-commands.md | 6 +- .../tutorials/bigquery/BigQuery Basics.ipynb | 30 ++++++++- .../storage/Storage Client Library.ipynb | 63 +++++++++++-------- .../tutorials/storage/Storage Commands.ipynb | 8 +-- 11 files changed, 180 insertions(+), 89 deletions(-) diff --git a/notebooks/rendered/executed/bigquery-basics.md b/notebooks/rendered/executed/bigquery-basics.md index 9819b9be3c2..2e148f41c93 100644 --- a/notebooks/rendered/executed/bigquery-basics.md +++ b/notebooks/rendered/executed/bigquery-basics.md @@ -15,11 +15,31 @@ import pandas To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. +### Client project +The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. + +See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. + + +### Client location Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables. +Run the following to create a client with your default project: + ```python client = bigquery.Client(location="US") +print("Client creating using default project: {}".format(client.project)) +``` + + Client creating using default project: your-project-id + + +Alternatively, you can explicitly specify a project when constructing the client: + + +```python +client = bigquery.Client(location="US", project="your-project-id") ``` ## Run a query on a public dataset @@ -347,7 +367,7 @@ destination_table = client.get_table(table_ref) print('Loaded {} rows.'.format(destination_table.num_rows)) ``` - Starting job ae46d9d4-5d55-45c5-b812-2c23250049b2 + Starting job a27afe96-d36b-458e-b72f-ba47f3d192dc Job finished. Loaded 50 rows. diff --git a/notebooks/rendered/executed/bigquery-query-magic.md b/notebooks/rendered/executed/bigquery-query-magic.md index 17deb6bc1a8..0442f926763 100644 --- a/notebooks/rendered/executed/bigquery-query-magic.md +++ b/notebooks/rendered/executed/bigquery-query-magic.md @@ -103,9 +103,9 @@ ORDER BY count DESC LIMIT 10 ``` - Executing query with job ID: de0ef4a2-c6b0-4622-8404-d248d3c980a3 - Query executing: 0.55s - Query complete after 1.07s + Executing query with job ID: 82f4ffb5-43f8-4e87-b8a4-ed710c4c16ac + Query executing: 0.65s + Query complete after 1.08s diff --git a/notebooks/rendered/executed/bigquery-shell-commands.md b/notebooks/rendered/executed/bigquery-shell-commands.md index e763a61f83d..6090ed8e7e7 100644 --- a/notebooks/rendered/executed/bigquery-shell-commands.md +++ b/notebooks/rendered/executed/bigquery-shell-commands.md @@ -157,7 +157,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he bq ls --transfer_log --message_type='messageTypes:INFO,ERROR' projects/p/locations/l/transferConfigs/c/runs/r - mk Create a dataset, table, view, or transfer configuration with this + name. See 'bq help load' for more information on specifying the schema. @@ -359,7 +359,7 @@ The example below demonstrates how to load a local CSV file into a new or existi ``` Upload complete. - Waiting on bqjob_r735032bbeffc13dd_0000016895acdf56_1 ... (1s) Current status: DONE + Waiting on bqjob_r79803249dee1436f_0000016896639904_1 ... (1s) Current status: DONE ## Load data from Google Cloud Storage to a table @@ -371,7 +371,7 @@ The example below demonstrates how to load a local CSV file into a new or existi !bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' ``` - Waiting on bqjob_r4988ae2c001c168b_0000016895acf9e5_1 ... (1s) Current status: DONE + Waiting on bqjob_r30641d9ed9788ca4_000001689663b441_1 ... (1s) Current status: DONE ## Run a query diff --git a/notebooks/rendered/executed/storage-client-library.md b/notebooks/rendered/executed/storage-client-library.md index 5a7baa4e088..976c0bc07f1 100644 --- a/notebooks/rendered/executed/storage-client-library.md +++ b/notebooks/rendered/executed/storage-client-library.md @@ -1,39 +1,42 @@ # Google Cloud Storage -This page shows how to get started with the Google Cloud Storage Python client library. +This page shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). -## Import the library +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by importing the library: ```python from google.cloud import storage ``` -## Projects +Next, initialize a client object, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. -All data in Cloud Storage belongs inside a project. A project consists of a -set of users, a set of APIs, and billing, authentication, and monitoring -settings for those APIs. You can have one project or multiple projects. +See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. -## Clients -Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client. +Run the following to create a client with your default project: ```python -client = storage.Client(project="your-project-id") +client = storage.Client() +print("Client creating using default project: {}".format(client.project)) ``` -## Buckets + Client creating using default project: your-project-id -Buckets are the basic containers that hold your data. Everything that you -store in Cloud Storage must be contained in a bucket. You can use buckets to -organize your data and control access to your data. -### Create a bucket +Alternatively, you can explicitly specify a project when constructing the client: + + +```python +client = storage.Client(project="your-project-id") +``` -When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), -you specify a globally-unique name. +Finally, create a bucket with a globally unique name. ```python @@ -49,6 +52,8 @@ print('Bucket {} created.'.format(bucket.name)) Bucket your-new-bucket created. +For more information, see [Creating Storage Buckets](https://cloud.google.com/storage/docs/creating-buckets) in the Cloud Storage documentation. + ### List buckets in a project @@ -68,7 +73,7 @@ for item in buckets: your-new-bucket -### Get a bucket +### Get bucket metadata ```python @@ -77,8 +82,13 @@ bucket = client.get_bucket(bucket_name) ## Objects -Objects are the individual pieces of data that you store in Cloud Storage. -There is no limit on the number of objects that you can create in a bucket. +Objects are the individual pieces of data that you store in Cloud Storage. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +Though data in storage buckets is stored similar to a local file system, Google Cloud Storage is a key/value pair object store. A common character to include in object names to emulate directory structure is a slash (/). By using slashes, you can make objects appear as though they're stored in a hierarchical structure. For example, you could name one object `/europe/france/paris.jpg` and another object `/europe/france/cannes.jpg`. When you list these objects, they appear to be in a hierarchical directory structure based on location; however, Cloud Storage sees the objects as independent with no hierarchical relationship whatsoever. + +For more information, including how to rename an object, see the [object naming guidelines](https://cloud.google.com/storage/docs/naming#objectnames). ### Upload a local file to a bucket @@ -125,9 +135,9 @@ print('\tUpdated: {}'.format(blob.updated)) ``` Select metadata for blob us-states.txt: - ID: your-new-bucket/us-states.txt/1548699437748619 + ID: your-new-bucket/us-states.txt/1548711406354410 Size: 637 bytes - Updated: 2019-01-28 18:17:17.748000+00:00 + Updated: 2019-01-28 21:36:46.354000+00:00 ### Download a blob to a local directory diff --git a/notebooks/rendered/executed/storage-commands.md b/notebooks/rendered/executed/storage-commands.md index 9e32be3d05a..df35f17c585 100644 --- a/notebooks/rendered/executed/storage-commands.md +++ b/notebooks/rendered/executed/storage-commands.md @@ -1,9 +1,7 @@ # Storage Commands -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. - -This notebook introduces several `gsutil` commands for interacting with Cloud Storage. +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. ## List available commands @@ -155,16 +153,16 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada ``` gs://your-new-bucket/us-states.txt: - Creation time: Mon, 28 Jan 2019 18:17:01 GMT - Update time: Mon, 28 Jan 2019 18:17:01 GMT + Creation time: Mon, 28 Jan 2019 21:36:30 GMT + Update time: Mon, 28 Jan 2019 21:36:30 GMT Storage class: STANDARD Content-Language: en Content-Length: 637 Content-Type: text/plain Hash (crc32c): AmYMRQ== Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CMnp7faKkeACEAE= - Generation: 1548699421078729 + ETag: CL2ev8K3keACEAE= + Generation: 1548711390859069 Metageneration: 1 ACL: [ { @@ -228,6 +226,8 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada ### Delete a bucket +The following command deletes all objects in the bucket before deleting the bucket itself. + ```python !gsutil rm -r gs://{bucket_name}/ diff --git a/notebooks/rendered/unexecuted/bigquery-basics.md b/notebooks/rendered/unexecuted/bigquery-basics.md index 8a45e176d9e..a645889070f 100644 --- a/notebooks/rendered/unexecuted/bigquery-basics.md +++ b/notebooks/rendered/unexecuted/bigquery-basics.md @@ -15,11 +15,28 @@ import pandas To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. +### Client project +The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. + +See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. + + +### Client location Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables. +Run the following to create a client with your default project: + ```python client = bigquery.Client(location="US") +print("Client creating using default project: {}".format(client.project)) +``` + +Alternatively, you can explicitly specify a project when constructing the client: + + +```python +client = bigquery.Client(location="US", project="your-project-id") ``` ## Run a query on a public dataset diff --git a/notebooks/rendered/unexecuted/storage-client-library.md b/notebooks/rendered/unexecuted/storage-client-library.md index 45fd8f529a2..5a4493d5aec 100644 --- a/notebooks/rendered/unexecuted/storage-client-library.md +++ b/notebooks/rendered/unexecuted/storage-client-library.md @@ -1,39 +1,39 @@ # Google Cloud Storage -This page shows how to get started with the Google Cloud Storage Python client library. +This page shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). -## Import the library +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by importing the library: ```python from google.cloud import storage ``` -## Projects +Next, initialize a client object, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. -All data in Cloud Storage belongs inside a project. A project consists of a -set of users, a set of APIs, and billing, authentication, and monitoring -settings for those APIs. You can have one project or multiple projects. +See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. -## Clients -Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client. +Run the following to create a client with your default project: ```python -client = storage.Client(project="your-project-id") +client = storage.Client() +print("Client creating using default project: {}".format(client.project)) ``` -## Buckets +Alternatively, you can explicitly specify a project when constructing the client: -Buckets are the basic containers that hold your data. Everything that you -store in Cloud Storage must be contained in a bucket. You can use buckets to -organize your data and control access to your data. -### Create a bucket +```python +client = storage.Client(project="your-project-id") +``` -When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), -you specify a globally-unique name. +Finally, create a bucket with a globally unique name. ```python @@ -46,6 +46,8 @@ bucket = client.create_bucket(bucket_name) print('Bucket {} created.'.format(bucket.name)) ``` +For more information, see [Creating Storage Buckets](https://cloud.google.com/storage/docs/creating-buckets) in the Cloud Storage documentation. + ### List buckets in a project @@ -57,7 +59,7 @@ for item in buckets: print("\t" + item.name) ``` -### Get a bucket +### Get bucket metadata ```python @@ -66,8 +68,13 @@ bucket = client.get_bucket(bucket_name) ## Objects -Objects are the individual pieces of data that you store in Cloud Storage. -There is no limit on the number of objects that you can create in a bucket. +Objects are the individual pieces of data that you store in Cloud Storage. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +Though data in storage buckets is stored similar to a local file system, Google Cloud Storage is a key/value pair object store. A common character to include in object names to emulate directory structure is a slash (/). By using slashes, you can make objects appear as though they're stored in a hierarchical structure. For example, you could name one object `/europe/france/paris.jpg` and another object `/europe/france/cannes.jpg`. When you list these objects, they appear to be in a hierarchical directory structure based on location; however, Cloud Storage sees the objects as independent with no hierarchical relationship whatsoever. + +For more information, including how to rename an object, see the [object naming guidelines](https://cloud.google.com/storage/docs/naming#objectnames). ### Upload a local file to a bucket diff --git a/notebooks/rendered/unexecuted/storage-commands.md b/notebooks/rendered/unexecuted/storage-commands.md index b75eaca831b..e2d3025f755 100644 --- a/notebooks/rendered/unexecuted/storage-commands.md +++ b/notebooks/rendered/unexecuted/storage-commands.md @@ -1,9 +1,7 @@ # Storage Commands -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. - -This notebook introduces several `gsutil` commands for interacting with Cloud Storage. +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. ## List available commands @@ -92,6 +90,8 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada ### Delete a bucket +The following command deletes all objects in the bucket before deleting the bucket itself. + ```python !gsutil rm -r gs://{bucket_name}/ diff --git a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb index 8fa8b6fcb55..fe6d5616382 100644 --- a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb @@ -34,7 +34,33 @@ "\n", "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API.\n", "\n", - "Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables." + "### Client project\n", + "The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.\n", + "\n", + "See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials.\n", + "\n", + "\n", + "### Client location\n", + "Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables.\n", + "\n", + "Run the following to create a client with your default project:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client = bigquery.Client(location=\"US\")\n", + "print(\"Client creating using default project: {}\".format(client.project))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, you can explicitly specify a project when constructing the client:" ] }, { @@ -43,7 +69,7 @@ "metadata": {}, "outputs": [], "source": [ - "client = bigquery.Client(location=\"US\")" + "client = bigquery.Client(location=\"US\", project=\"your-project-id\")" ] }, { diff --git a/notebooks/tutorials/storage/Storage Client Library.ipynb b/notebooks/tutorials/storage/Storage Client Library.ipynb index 7ff62cb79bc..5a6734c4e03 100644 --- a/notebooks/tutorials/storage/Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Storage Client Library.ipynb @@ -6,14 +6,18 @@ "source": [ "# Google Cloud Storage\n", "\n", - "This page shows how to get started with the Google Cloud Storage Python client library." + "This page shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Import the library" + "## Create a storage bucket\n", + "\n", + "Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data.\n", + "\n", + "Start by importing the library:" ] }, { @@ -29,49 +33,44 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Projects\n", + "Next, initialize a client object, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.\n", "\n", - "All data in Cloud Storage belongs inside a project. A project consists of a\n", - "set of users, a set of APIs, and billing, authentication, and monitoring\n", - "settings for those APIs. You can have one project or multiple projects." + "See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials.\n", + "\n", + "Run the following to create a client with your default project:" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "## Clients\n", - "Start by initializing a client, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with your credentials. Alternatively, you can explicitly specify a project when constructing the client." + "client = storage.Client()\n", + "print(\"Client creating using default project: {}\".format(client.project))" ] }, { - "cell_type": "code", - "execution_count": null, + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "client = storage.Client(project=\"your-project-id\")" + "Alternatively, you can explicitly specify a project when constructing the client:" ] }, { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "## Buckets\n", - "\n", - "Buckets are the basic containers that hold your data. Everything that you\n", - "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", - "organize your data and control access to your data." + "client = storage.Client(project=\"your-project-id\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Create a bucket\n", - "\n", - "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", - "you specify a globally-unique name." + "Finally, create a bucket with a globally unique name." ] }, { @@ -89,6 +88,13 @@ "print('Bucket {} created.'.format(bucket.name))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For more information, see [Creating Storage Buckets](https://cloud.google.com/storage/docs/creating-buckets) in the Cloud Storage documentation." + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -113,7 +119,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Get a bucket" + "### Get bucket metadata" ] }, { @@ -131,8 +137,13 @@ "source": [ "## Objects\n", "\n", - "Objects are the individual pieces of data that you store in Cloud Storage.\n", - "There is no limit on the number of objects that you can create in a bucket." + "Objects are the individual pieces of data that you store in Cloud Storage. There is no limit on the number of objects that you can create in a bucket.\n", + "\n", + "An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length.\n", + "\n", + "Though data in storage buckets is stored similar to a local file system, Google Cloud Storage is a key/value pair object store. A common character to include in object names to emulate directory structure is a slash (/). By using slashes, you can make objects appear as though they're stored in a hierarchical structure. For example, you could name one object `/europe/france/paris.jpg` and another object `/europe/france/cannes.jpg`. When you list these objects, they appear to be in a hierarchical directory structure based on location; however, Cloud Storage sees the objects as independent with no hierarchical relationship whatsoever.\n", + "\n", + "For more information, including how to rename an object, see the [object naming guidelines](https://cloud.google.com/storage/docs/naming#objectnames)." ] }, { diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage Commands.ipynb index 5e43099e8ad..75ed0301d60 100644 --- a/notebooks/tutorials/storage/Storage Commands.ipynb +++ b/notebooks/tutorials/storage/Storage Commands.ipynb @@ -6,9 +6,7 @@ "source": [ "# Storage Commands\n", "\n", - "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage.\n", - "\n", - "This notebook introduces several `gsutil` commands for interacting with Cloud Storage." + "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`." ] }, { @@ -204,7 +202,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Delete a bucket" + "### Delete a bucket\n", + "\n", + "The following command deletes all objects in the bucket before deleting the bucket itself." ] }, { From 82778a4c91db42c87a259ab0fae5eaf79a65d27c Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Tue, 29 Jan 2019 14:47:28 -0800 Subject: [PATCH 08/24] updated storage notebooks per feedback session with Frank --- .../executed/storage-client-library.md | 69 +++++---- .../rendered/executed/storage-commands.md | 131 +++++++++++++++--- .../unexecuted/storage-client-library.md | 56 +++++--- .../rendered/unexecuted/storage-commands.md | 49 +++++-- .../storage/Storage Client Library.ipynb | 77 +++++----- .../tutorials/storage/Storage Commands.ipynb | 67 ++++++--- 6 files changed, 311 insertions(+), 138 deletions(-) diff --git a/notebooks/rendered/executed/storage-client-library.md b/notebooks/rendered/executed/storage-client-library.md index 976c0bc07f1..7223e8338f4 100644 --- a/notebooks/rendered/executed/storage-client-library.md +++ b/notebooks/rendered/executed/storage-client-library.md @@ -1,7 +1,7 @@ # Google Cloud Storage -This page shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). +This tutorial shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). ## Create a storage bucket @@ -23,21 +23,23 @@ Run the following to create a client with your default project: ```python client = storage.Client() -print("Client creating using default project: {}".format(client.project)) +print("Client created using default project: {}".format(client.project)) ``` - Client creating using default project: your-project-id + Client created using default project: your-project-id Alternatively, you can explicitly specify a project when constructing the client: ```python -client = storage.Client(project="your-project-id") +# client = storage.Client(project='your-project-id') ``` Finally, create a bucket with a globally unique name. +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + ```python # Replace the string below with a unique name for the new bucket @@ -52,9 +54,7 @@ print('Bucket {} created.'.format(bucket.name)) Bucket your-new-bucket created. -For more information, see [Creating Storage Buckets](https://cloud.google.com/storage/docs/creating-buckets) in the Cloud Storage documentation. - -### List buckets in a project +## List buckets in a project ```python @@ -73,24 +73,33 @@ for item in buckets: your-new-bucket -### Get bucket metadata +## Get bucket metadata + +The next cell shows how get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). ```python bucket = client.get_bucket(bucket_name) + +print('Bucket name: {}'.format(bucket.name)) +print('Bucket location: {}'.format(bucket.location)) +print('Bucket storage class: {}'.format(bucket.storage_class)) ``` -## Objects + Bucket name: your-new-bucket + Bucket location: US + Bucket storage class: STANDARD -Objects are the individual pieces of data that you store in Cloud Storage. There is no limit on the number of objects that you can create in a bucket. -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. +## Upload a local file to a bucket -Though data in storage buckets is stored similar to a local file system, Google Cloud Storage is a key/value pair object store. A common character to include in object names to emulate directory structure is a slash (/). By using slashes, you can make objects appear as though they're stored in a hierarchical structure. For example, you could name one object `/europe/france/paris.jpg` and another object `/europe/france/cannes.jpg`. When you list these objects, they appear to be in a hierarchical directory structure based on location; however, Cloud Storage sees the objects as independent with no hierarchical relationship whatsoever. +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. -For more information, including how to rename an object, see the [object naming guidelines](https://cloud.google.com/storage/docs/naming#objectnames). +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. -### Upload a local file to a bucket +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). ```python @@ -106,7 +115,7 @@ print('File uploaded to {}.'.format(bucket.name)) File uploaded to your-new-bucket. -### List blobs in a bucket +## List blobs in a bucket ```python @@ -121,26 +130,27 @@ for item in blobs: us-states.txt -### Get a blob and display metadata +## Get a blob and display metadata + See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. ```python blob = bucket.get_blob(blob_name) -print('Select metadata for blob {}:'.format(blob_name)) -print('\tID: {}'.format(blob.id)) -print('\tSize: {} bytes'.format(blob.size)) -print('\tUpdated: {}'.format(blob.updated)) +print('Name: {}'.format(blob.id)) +print('Size: {} bytes'.format(blob.size)) +print('Content type: {}'.format(blob.content_type)) +print('Public URL: {}'.format(blob.public_url)) ``` - Select metadata for blob us-states.txt: - ID: your-new-bucket/us-states.txt/1548711406354410 - Size: 637 bytes - Updated: 2019-01-28 21:36:46.354000+00:00 + Name: your-new-bucket/us-states.txt/1548801913760895 + Size: 637 bytes + Content type: text/plain + Public URL: https://storage.googleapis.com/your-new-bucket/us-states.txt -### Download a blob to a local directory +## Download a blob to a local directory ```python @@ -170,6 +180,8 @@ print('Blob {} deleted.'.format(blob.name)) ### Delete a bucket +Note that the bucket must be empty before it can be deleted. + ```python bucket = client.get_bucket(bucket_name) @@ -180,3 +192,10 @@ print('Bucket {} deleted.'.format(bucket.name)) Bucket your-new-bucket deleted. + +## Next Steps + +Read more about Google Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/executed/storage-commands.md b/notebooks/rendered/executed/storage-commands.md index df35f17c585..303a5ca49f0 100644 --- a/notebooks/rendered/executed/storage-commands.md +++ b/notebooks/rendered/executed/storage-commands.md @@ -74,16 +74,13 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help Use gsutil help for detailed help. -## Buckets +## Create a storage bucket -Buckets are the basic containers that hold your data. Everything that you -store in Cloud Storage must be contained in a bucket. You can use buckets to -organize your data and control access to your data. +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. -### Create a bucket +Start by defining a globally unique name. -When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), -you specify a globally-unique name. +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). ```python @@ -93,6 +90,8 @@ bucket_name = 'your-new-bucket' NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. +Next, create the new bucket with the `gsutil mb` command: + ```python !gsutil mb gs://{bucket_name}/ @@ -101,7 +100,7 @@ NOTE: In the examples below, the variables are referenced in the command using ` Creating gs://your-new-bucket/... -### List buckets in a project +## List buckets in a project Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. @@ -117,12 +116,94 @@ Replace 'your-project-id' in the cell below with your project ID and run the cel gs://your-new-bucket/ -## Objects +## Get bucket metadata -Objects are the individual pieces of data that you store in Cloud Storage. -There is no limit on the number of objects that you can create in a bucket. +The next cell shows how get information on metadata of your Cloud Storage buckets. -### Upload a local file to a bucket +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +!gsutil ls -L -b gs://{bucket_name}/ +``` + + gs://your-new-bucket/ : + Storage class: STANDARD + Location constraint: US + Versioning enabled: None + Logging configuration: None + Website configuration: None + CORS configuration: None + Lifecycle configuration: None + Requester Pays enabled: None + Labels: None + Default KMS key: None + Time created: Tue, 29 Jan 2019 22:44:49 GMT + Time updated: Tue, 29 Jan 2019 22:44:49 GMT + Metageneration: 1 + ACL: + [ + { + "entity": "project-owners-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "owners" + }, + "role": "OWNER" + }, + { + "entity": "project-editors-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "editors" + }, + "role": "OWNER" + }, + { + "entity": "project-viewers-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "viewers" + }, + "role": "READER" + } + ] + Default ACL: + [ + { + "entity": "project-owners-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "owners" + }, + "role": "OWNER" + }, + { + "entity": "project-editors-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "editors" + }, + "role": "OWNER" + }, + { + "entity": "project-viewers-129776587519", + "projectTeam": { + "projectNumber": "129776587519", + "team": "viewers" + }, + "role": "READER" + } + ] + + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). ```python @@ -134,7 +215,7 @@ There is no limit on the number of objects that you can create in a bucket. Operation completed over 1 objects/637.0 B. -### List blobs in a bucket +## List blobs in a bucket ```python @@ -144,7 +225,8 @@ There is no limit on the number of objects that you can create in a bucket. gs://your-new-bucket/us-states.txt -### Get a blob and display metadata +## Get a blob and display metadata + See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. @@ -153,16 +235,16 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada ``` gs://your-new-bucket/us-states.txt: - Creation time: Mon, 28 Jan 2019 21:36:30 GMT - Update time: Mon, 28 Jan 2019 21:36:30 GMT + Creation time: Tue, 29 Jan 2019 22:44:55 GMT + Update time: Tue, 29 Jan 2019 22:44:55 GMT Storage class: STANDARD Content-Language: en Content-Length: 637 Content-Type: text/plain Hash (crc32c): AmYMRQ== Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CL2ev8K3keACEAE= - Generation: 1548711390859069 + ETag: CJ3Y0taIlOACEAE= + Generation: 1548801895869469 Metageneration: 1 ACL: [ { @@ -190,15 +272,15 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada "role": "READER" }, { - "email": "ajhamilton@google.com", - "entity": "user-ajhamilton@google.com", + "email": "user@example.com", + "entity": "user-user@example.com", "role": "OWNER" } ] TOTAL: 1 objects, 637 bytes (637 B) -### Download a blob to a local directory +## Download a blob to a local directory ```python @@ -235,3 +317,10 @@ The following command deletes all objects in the bucket before deleting the buck Removing gs://your-new-bucket/... + +## Next Steps + +Read more about Google Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/storage-client-library.md b/notebooks/rendered/unexecuted/storage-client-library.md index 5a4493d5aec..86d231f417c 100644 --- a/notebooks/rendered/unexecuted/storage-client-library.md +++ b/notebooks/rendered/unexecuted/storage-client-library.md @@ -1,7 +1,7 @@ # Google Cloud Storage -This page shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). +This tutorial shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). ## Create a storage bucket @@ -23,18 +23,20 @@ Run the following to create a client with your default project: ```python client = storage.Client() -print("Client creating using default project: {}".format(client.project)) +print("Client created using default project: {}".format(client.project)) ``` Alternatively, you can explicitly specify a project when constructing the client: ```python -client = storage.Client(project="your-project-id") +# client = storage.Client(project='your-project-id') ``` Finally, create a bucket with a globally unique name. +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + ```python # Replace the string below with a unique name for the new bucket @@ -46,9 +48,7 @@ bucket = client.create_bucket(bucket_name) print('Bucket {} created.'.format(bucket.name)) ``` -For more information, see [Creating Storage Buckets](https://cloud.google.com/storage/docs/creating-buckets) in the Cloud Storage documentation. - -### List buckets in a project +## List buckets in a project ```python @@ -59,24 +59,28 @@ for item in buckets: print("\t" + item.name) ``` -### Get bucket metadata +## Get bucket metadata + +The next cell shows how get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). ```python bucket = client.get_bucket(bucket_name) + +print('Bucket name: {}'.format(bucket.name)) +print('Bucket location: {}'.format(bucket.location)) +print('Bucket storage class: {}'.format(bucket.storage_class)) ``` -## Objects +## Upload a local file to a bucket -Objects are the individual pieces of data that you store in Cloud Storage. There is no limit on the number of objects that you can create in a bucket. +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. -Though data in storage buckets is stored similar to a local file system, Google Cloud Storage is a key/value pair object store. A common character to include in object names to emulate directory structure is a slash (/). By using slashes, you can make objects appear as though they're stored in a hierarchical structure. For example, you could name one object `/europe/france/paris.jpg` and another object `/europe/france/cannes.jpg`. When you list these objects, they appear to be in a hierarchical directory structure based on location; however, Cloud Storage sees the objects as independent with no hierarchical relationship whatsoever. - -For more information, including how to rename an object, see the [object naming guidelines](https://cloud.google.com/storage/docs/naming#objectnames). - -### Upload a local file to a bucket +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). ```python @@ -89,7 +93,7 @@ blob.upload_from_filename(source_file_name) print('File uploaded to {}.'.format(bucket.name)) ``` -### List blobs in a bucket +## List blobs in a bucket ```python @@ -100,20 +104,21 @@ for item in blobs: print("\t" + item.name) ``` -### Get a blob and display metadata +## Get a blob and display metadata + See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. ```python blob = bucket.get_blob(blob_name) -print('Select metadata for blob {}:'.format(blob_name)) -print('\tID: {}'.format(blob.id)) -print('\tSize: {} bytes'.format(blob.size)) -print('\tUpdated: {}'.format(blob.updated)) +print('Name: {}'.format(blob.id)) +print('Size: {} bytes'.format(blob.size)) +print('Content type: {}'.format(blob.content_type)) +print('Public URL: {}'.format(blob.public_url)) ``` -### Download a blob to a local directory +## Download a blob to a local directory ```python @@ -137,6 +142,8 @@ print('Blob {} deleted.'.format(blob.name)) ### Delete a bucket +Note that the bucket must be empty before it can be deleted. + ```python bucket = client.get_bucket(bucket_name) @@ -144,3 +151,10 @@ bucket.delete() print('Bucket {} deleted.'.format(bucket.name)) ``` + +## Next Steps + +Read more about Google Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/storage-commands.md b/notebooks/rendered/unexecuted/storage-commands.md index e2d3025f755..efa9bbe734b 100644 --- a/notebooks/rendered/unexecuted/storage-commands.md +++ b/notebooks/rendered/unexecuted/storage-commands.md @@ -12,16 +12,13 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help !gsutil help ``` -## Buckets +## Create a storage bucket -Buckets are the basic containers that hold your data. Everything that you -store in Cloud Storage must be contained in a bucket. You can use buckets to -organize your data and control access to your data. +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. -### Create a bucket +Start by defining a globally unique name. -When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets), -you specify a globally-unique name. +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). ```python @@ -31,12 +28,14 @@ bucket_name = 'your-new-bucket' NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. +Next, create the new bucket with the `gsutil mb` command: + ```python !gsutil mb gs://{bucket_name}/ ``` -### List buckets in a project +## List buckets in a project Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. @@ -45,26 +44,39 @@ Replace 'your-project-id' in the cell below with your project ID and run the cel !gsutil ls -p your-project-id ``` -## Objects +## Get bucket metadata + +The next cell shows how get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +!gsutil ls -L -b gs://{bucket_name}/ +``` + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. -Objects are the individual pieces of data that you store in Cloud Storage. -There is no limit on the number of objects that you can create in a bucket. +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. -### Upload a local file to a bucket +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). ```python !gsutil cp resources/us-states.txt gs://{bucket_name}/ ``` -### List blobs in a bucket +## List blobs in a bucket ```python !gsutil ls -r gs://{bucket_name}/** ``` -### Get a blob and display metadata +## Get a blob and display metadata + See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. @@ -72,7 +84,7 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada !gsutil ls -L gs://{bucket_name}/us-states.txt ``` -### Download a blob to a local directory +## Download a blob to a local directory ```python @@ -96,3 +108,10 @@ The following command deletes all objects in the bucket before deleting the buck ```python !gsutil rm -r gs://{bucket_name}/ ``` + +## Next Steps + +Read more about Google Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/tutorials/storage/Storage Client Library.ipynb b/notebooks/tutorials/storage/Storage Client Library.ipynb index 5a6734c4e03..052a76ff95f 100644 --- a/notebooks/tutorials/storage/Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Storage Client Library.ipynb @@ -6,7 +6,7 @@ "source": [ "# Google Cloud Storage\n", "\n", - "This page shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html)." + "This tutorial shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html)." ] }, { @@ -47,7 +47,7 @@ "outputs": [], "source": [ "client = storage.Client()\n", - "print(\"Client creating using default project: {}\".format(client.project))" + "print(\"Client created using default project: {}\".format(client.project))" ] }, { @@ -63,14 +63,16 @@ "metadata": {}, "outputs": [], "source": [ - "client = storage.Client(project=\"your-project-id\")" + "# client = storage.Client(project='your-project-id')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Finally, create a bucket with a globally unique name." + "Finally, create a bucket with a globally unique name.\n", + "\n", + "For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements)." ] }, { @@ -92,14 +94,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "For more information, see [Creating Storage Buckets](https://cloud.google.com/storage/docs/creating-buckets) in the Cloud Storage documentation." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List buckets in a project" + "## List buckets in a project" ] }, { @@ -119,7 +114,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Get bucket metadata" + "## Get bucket metadata\n", + "\n", + "The next cell shows how get information on metadata of your Cloud Storage buckets.\n", + "\n", + "To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes)." ] }, { @@ -128,29 +127,24 @@ "metadata": {}, "outputs": [], "source": [ - "bucket = client.get_bucket(bucket_name)" + "bucket = client.get_bucket(bucket_name)\n", + "\n", + "print('Bucket name: {}'.format(bucket.name))\n", + "print('Bucket location: {}'.format(bucket.location))\n", + "print('Bucket storage class: {}'.format(bucket.storage_class))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Objects\n", + "## Upload a local file to a bucket\n", "\n", - "Objects are the individual pieces of data that you store in Cloud Storage. There is no limit on the number of objects that you can create in a bucket.\n", + "Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as \"blobs\" in the Python client library. There is no limit on the number of objects that you can create in a bucket.\n", "\n", "An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length.\n", "\n", - "Though data in storage buckets is stored similar to a local file system, Google Cloud Storage is a key/value pair object store. A common character to include in object names to emulate directory structure is a slash (/). By using slashes, you can make objects appear as though they're stored in a hierarchical structure. For example, you could name one object `/europe/france/paris.jpg` and another object `/europe/france/cannes.jpg`. When you list these objects, they appear to be in a hierarchical directory structure based on location; however, Cloud Storage sees the objects as independent with no hierarchical relationship whatsoever.\n", - "\n", - "For more information, including how to rename an object, see the [object naming guidelines](https://cloud.google.com/storage/docs/naming#objectnames)." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Upload a local file to a bucket" + "For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames)." ] }, { @@ -174,7 +168,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### List blobs in a bucket" + "## List blobs in a bucket" ] }, { @@ -196,7 +190,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Get a blob and display metadata\n", + "## Get a blob and display metadata\n", + "\n", "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." ] }, @@ -208,17 +203,17 @@ "source": [ "blob = bucket.get_blob(blob_name)\n", "\n", - "print('Select metadata for blob {}:'.format(blob_name))\n", - "print('\\tID: {}'.format(blob.id))\n", - "print('\\tSize: {} bytes'.format(blob.size))\n", - "print('\\tUpdated: {}'.format(blob.updated))" + "print('Name: {}'.format(blob.id))\n", + "print('Size: {} bytes'.format(blob.size))\n", + "print('Content type: {}'.format(blob.content_type))\n", + "print('Public URL: {}'.format(blob.public_url))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Download a blob to a local directory" + "## Download a blob to a local directory" ] }, { @@ -265,7 +260,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Delete a bucket" + "### Delete a bucket\n", + "\n", + "Note that the bucket must be empty before it can be deleted." ] }, { @@ -279,6 +276,18 @@ "\n", "print('Bucket {} deleted.'.format(bucket.name))" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Read more about Google Cloud Storage in the documentation:\n", + "+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms)\n", + "+ [How-To Guides](https://cloud.google.com/storage/docs/how-to)\n", + "+ [Pricing](https://cloud.google.com/storage/pricing)" + ] } ], "metadata": { diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage Commands.ipynb index 75ed0301d60..57ef304db30 100644 --- a/notebooks/tutorials/storage/Storage Commands.ipynb +++ b/notebooks/tutorials/storage/Storage Commands.ipynb @@ -33,21 +33,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Buckets\n", + "## Create a storage bucket\n", "\n", - "Buckets are the basic containers that hold your data. Everything that you\n", - "store in Cloud Storage must be contained in a bucket. You can use buckets to\n", - "organize your data and control access to your data." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Create a bucket\n", + "Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data.\n", + "\n", + "Start by defining a globally unique name.\n", "\n", - "When you [create a bucket](https://cloud.google.com/storage/docs/creating-buckets),\n", - "you specify a globally-unique name." + "For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements)." ] }, { @@ -64,7 +56,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables." + "NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables.\n", + "\n", + "Next, create the new bucket with the `gsutil mb` command:" ] }, { @@ -80,7 +74,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### List buckets in a project\n", + "## List buckets in a project\n", "\n", "Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project." ] @@ -98,17 +92,33 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Objects\n", + "## Get bucket metadata\n", + "\n", + "The next cell shows how get information on metadata of your Cloud Storage buckets.\n", "\n", - "Objects are the individual pieces of data that you store in Cloud Storage.\n", - "There is no limit on the number of objects that you can create in a bucket." + "To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil ls -L -b gs://{bucket_name}/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Upload a local file to a bucket" + "## Upload a local file to a bucket\n", + "\n", + "Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as \"blobs\" in the Python client library. There is no limit on the number of objects that you can create in a bucket.\n", + "\n", + "An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length.\n", + "\n", + "For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames)." ] }, { @@ -124,7 +134,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### List blobs in a bucket" + "## List blobs in a bucket" ] }, { @@ -142,7 +152,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Get a blob and display metadata\n", + "## Get a blob and display metadata\n", + "\n", "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." ] }, @@ -159,7 +170,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Download a blob to a local directory" + "## Download a blob to a local directory" ] }, { @@ -215,6 +226,18 @@ "source": [ "!gsutil rm -r gs://{bucket_name}/" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "Read more about Google Cloud Storage in the documentation:\n", + "+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms)\n", + "+ [How-To Guides](https://cloud.google.com/storage/docs/how-to)\n", + "+ [Pricing](https://cloud.google.com/storage/pricing)" + ] } ], "metadata": { From 35ecad50bbcb11f680f33258da1febd08c2fbba1 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Wed, 30 Jan 2019 15:31:49 -0800 Subject: [PATCH 09/24] update storage notebooks per nstock's comments --- .../executed/cloud-storage-client-library.md | 197 +++++++++++ .../rendered/executed/storage-commands.md | 316 +++++++++--------- .../cloud-storage-client-library.md | 160 +++++++++ .../rendered/unexecuted/storage-commands.md | 16 +- ...ynb => Cloud Storage Client Library.ipynb} | 10 +- .../tutorials/storage/Storage Commands.ipynb | 20 +- 6 files changed, 547 insertions(+), 172 deletions(-) create mode 100644 notebooks/rendered/executed/cloud-storage-client-library.md create mode 100644 notebooks/rendered/unexecuted/cloud-storage-client-library.md rename notebooks/tutorials/storage/{Storage Client Library.ipynb => Cloud Storage Client Library.ipynb} (93%) diff --git a/notebooks/rendered/executed/cloud-storage-client-library.md b/notebooks/rendered/executed/cloud-storage-client-library.md new file mode 100644 index 00000000000..fc58e903ed8 --- /dev/null +++ b/notebooks/rendered/executed/cloud-storage-client-library.md @@ -0,0 +1,197 @@ + +# Cloud Storage Client Library + +This tutorial shows how to get started with the [Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). + +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by importing the library: + + +```python +from google.cloud import storage +``` + +Next, initialize a client object, which is used to interact with the Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. + +See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. + +Run the following to create a client with your default project: + + +```python +client = storage.Client() +print("Client created using default project: {}".format(client.project)) +``` + + Client created using default project: your-project-id + + +Alternatively, you can explicitly specify a project when constructing the client: + + +```python +# client = storage.Client(project='your-project-id') +``` + +Finally, create a bucket with a globally unique name. + +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'your-new-bucket' + +# Creates the new bucket +bucket = client.create_bucket(bucket_name) + +print('Bucket {} created.'.format(bucket.name)) +``` + + Bucket your-new-bucket created. + + +## List buckets in a project + + +```python +buckets = client.list_buckets() + +print("Buckets in {}:".format(client.project)) +for item in buckets: + print("\t" + item.name) +``` + + Buckets in your-project-id: + your-new-bucket + + +## Get bucket metadata + +The next cell shows how to get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +bucket = client.get_bucket(bucket_name) + +print('Bucket name: {}'.format(bucket.name)) +print('Bucket location: {}'.format(bucket.location)) +print('Bucket storage class: {}'.format(bucket.storage_class)) +``` + + Bucket name: your-new-bucket + Bucket location: US + Bucket storage class: STANDARD + + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). + + +```python +blob_name = 'us-states.txt' +blob = bucket.blob(blob_name) + +source_file_name = 'resources/us-states.txt' +blob.upload_from_filename(source_file_name) + +print('File uploaded to {}.'.format(bucket.name)) +``` + + File uploaded to your-new-bucket. + + +## List blobs in a bucket + + +```python +blobs = bucket.list_blobs() + +print("Blobs in {}:".format(bucket.name)) +for item in blobs: + print("\t" + item.name) +``` + + Blobs in your-new-bucket: + us-states.txt + + +## Get a blob and display metadata + +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +blob = bucket.get_blob(blob_name) + +print('Name: {}'.format(blob.id)) +print('Size: {} bytes'.format(blob.size)) +print('Content type: {}'.format(blob.content_type)) +print('Public URL: {}'.format(blob.public_url)) +``` + + Name: your-new-bucket/us-states.txt/1548890628692952 + Size: 637 bytes + Content type: text/plain + Public URL: https://storage.googleapis.com/your-new-bucket/us-states.txt + + +## Download a blob to a local directory + + +```python +output_file_name = 'resources/downloaded-us-states.txt' +blob.download_to_filename(output_file_name) + +print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) +``` + + Downloaded blob us-states.txt to resources/downloaded-us-states.txt. + + +## Cleaning up + +### Delete a blob + + +```python +blob = client.get_bucket(bucket_name).get_blob(blob_name) +blob.delete() + +print('Blob {} deleted.'.format(blob.name)) +``` + + Blob us-states.txt deleted. + + +### Delete a bucket + +Note that the bucket must be empty before it can be deleted. + + +```python +bucket = client.get_bucket(bucket_name) +bucket.delete() + +print('Bucket {} deleted.'.format(bucket.name)) +``` + + Bucket your-new-bucket deleted. + + +## Next Steps + +Read more about Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/executed/storage-commands.md b/notebooks/rendered/executed/storage-commands.md index 303a5ca49f0..51bd91e6477 100644 --- a/notebooks/rendered/executed/storage-commands.md +++ b/notebooks/rendered/executed/storage-commands.md @@ -1,17 +1,17 @@ - -# Storage Commands - -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. - -## List available commands - -The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: - - -```python -!gsutil help -``` - + +# Storage Commands + +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. + +## List available commands + +The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: + + +```python +!gsutil help +``` + Usage: gsutil [-D] [-DD] [-h header]... [-m] [-o] [-q] [command [opts...] args...] Available commands: acl Get, set, or change bucket and/or object ACLs @@ -49,7 +49,7 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help version Print version info about gsutil versioning Enable or suspend versioning for one or more buckets web Set a main page and/or error page for one or more buckets - + Additional help topics: acls Working With Access Control Lists anon Accessing Public Data Without Credentials @@ -71,62 +71,64 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help throttling Throttling gsutil versions Object Versioning and Concurrency Control wildcards Wildcard Names - - Use gsutil help for detailed help. - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by defining a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' -``` - -NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. - -Next, create the new bucket with the `gsutil mb` command: - - -```python -!gsutil mb gs://{bucket_name}/ -``` - + + Use gsutil help for detailed help. + +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by defining a globally unique name. + +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'your-new-bucket' +``` + +NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. + +Next, create the new bucket with the `gsutil mb` command: + + +```python +!gsutil mb gs://{bucket_name}/ +``` + Creating gs://your-new-bucket/... - - -## List buckets in a project - -Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. - - -```python -!gsutil ls -p your-project-id -``` - - gs://your-project-id/ - gs://my-new-bucket-1548180688764/ - gs://my-new-bucket-1548208228513/ - gs://test-storage-bucket-1548209987490/ + + +## List buckets in a project + +Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. + + +```python +# Replace the string below with your project ID +project_id = 'your-project-id' +``` + + +```python +!gsutil ls -p $project_id +``` + gs://your-new-bucket/ - - -## Get bucket metadata - -The next cell shows how get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -!gsutil ls -L -b gs://{bucket_name}/ -``` - + + +## Get bucket metadata + +The next cell shows how to get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +!gsutil ls -L -b gs://{bucket_name}/ +``` + gs://your-new-bucket/ : Storage class: STANDARD Location constraint: US @@ -138,10 +140,10 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c Requester Pays enabled: None Labels: None Default KMS key: None - Time created: Tue, 29 Jan 2019 22:44:49 GMT - Time updated: Tue, 29 Jan 2019 22:44:49 GMT + Time created: Wed, 30 Jan 2019 23:23:59 GMT + Time updated: Wed, 30 Jan 2019 23:23:59 GMT Metageneration: 1 - ACL: + ACL: [ { "entity": "project-owners-129776587519", @@ -168,7 +170,7 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c "role": "READER" } ] - Default ACL: + Default ACL: [ { "entity": "project-owners-129776587519", @@ -195,56 +197,56 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c "role": "READER" } ] - - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -!gsutil cp resources/us-states.txt gs://{bucket_name}/ -``` - + + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). + + +```python +!gsutil cp resources/us-states.txt gs://{bucket_name}/ +``` + Copying file://resources/us-states.txt [Content-Type=text/plain]... - - Operation completed over 1 objects/637.0 B. - - -## List blobs in a bucket - - -```python -!gsutil ls -r gs://{bucket_name}/** -``` - + + Operation completed over 1 objects/637.0 B. + + +## List blobs in a bucket + + +```python +!gsutil ls -r gs://{bucket_name}/** +``` + gs://your-new-bucket/us-states.txt - - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -!gsutil ls -L gs://{bucket_name}/us-states.txt -``` - + + +## Get a blob and display metadata + +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +!gsutil ls -L gs://{bucket_name}/us-states.txt +``` + gs://your-new-bucket/us-states.txt: - Creation time: Tue, 29 Jan 2019 22:44:55 GMT - Update time: Tue, 29 Jan 2019 22:44:55 GMT + Creation time: Wed, 30 Jan 2019 23:24:06 GMT + Update time: Wed, 30 Jan 2019 23:24:06 GMT Storage class: STANDARD Content-Language: en Content-Length: 637 Content-Type: text/plain Hash (crc32c): AmYMRQ== Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CJ3Y0taIlOACEAE= - Generation: 1548801895869469 + ETag: CLCthKbTluACEAE= + Generation: 1548890646058672 Metageneration: 1 ACL: [ { @@ -278,49 +280,49 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada } ] TOTAL: 1 objects, 637 bytes (637 B) - - -## Download a blob to a local directory - - -```python -!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt -``` - + + +## Download a blob to a local directory + + +```python +!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt +``` + Copying gs://your-new-bucket/us-states.txt... - - Operation completed over 1 objects/637.0 B. - - -## Cleaning up - -### Delete a blob - - -```python -!gsutil rm gs://{bucket_name}/us-states.txt -``` - + + Operation completed over 1 objects/637.0 B. + + +## Cleaning up + +### Delete a blob + + +```python +!gsutil rm gs://{bucket_name}/us-states.txt +``` + Removing gs://your-new-bucket/us-states.txt... - - Operation completed over 1 objects. - - -### Delete a bucket - -The following command deletes all objects in the bucket before deleting the bucket itself. - - -```python -!gsutil rm -r gs://{bucket_name}/ -``` - + + Operation completed over 1 objects. + + +### Delete a bucket + +The following command deletes all objects in the bucket before deleting the bucket itself. + + +```python +!gsutil rm -r gs://{bucket_name}/ +``` + Removing gs://your-new-bucket/... - - -## Next Steps - -Read more about Google Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) + + +## Next Steps + +Read more about Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/cloud-storage-client-library.md b/notebooks/rendered/unexecuted/cloud-storage-client-library.md new file mode 100644 index 00000000000..1b0dc9e1aeb --- /dev/null +++ b/notebooks/rendered/unexecuted/cloud-storage-client-library.md @@ -0,0 +1,160 @@ + +# Cloud Storage Client Library + +This tutorial shows how to get started with the [Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). + +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by importing the library: + + +```python +from google.cloud import storage +``` + +Next, initialize a client object, which is used to interact with the Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. + +See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. + +Run the following to create a client with your default project: + + +```python +client = storage.Client() +print("Client created using default project: {}".format(client.project)) +``` + +Alternatively, you can explicitly specify a project when constructing the client: + + +```python +# client = storage.Client(project='your-project-id') +``` + +Finally, create a bucket with a globally unique name. + +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'your-new-bucket' + +# Creates the new bucket +bucket = client.create_bucket(bucket_name) + +print('Bucket {} created.'.format(bucket.name)) +``` + +## List buckets in a project + + +```python +buckets = client.list_buckets() + +print("Buckets in {}:".format(client.project)) +for item in buckets: + print("\t" + item.name) +``` + +## Get bucket metadata + +The next cell shows how to get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +bucket = client.get_bucket(bucket_name) + +print('Bucket name: {}'.format(bucket.name)) +print('Bucket location: {}'.format(bucket.location)) +print('Bucket storage class: {}'.format(bucket.storage_class)) +``` + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). + + +```python +blob_name = 'us-states.txt' +blob = bucket.blob(blob_name) + +source_file_name = 'resources/us-states.txt' +blob.upload_from_filename(source_file_name) + +print('File uploaded to {}.'.format(bucket.name)) +``` + +## List blobs in a bucket + + +```python +blobs = bucket.list_blobs() + +print("Blobs in {}:".format(bucket.name)) +for item in blobs: + print("\t" + item.name) +``` + +## Get a blob and display metadata + +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +blob = bucket.get_blob(blob_name) + +print('Name: {}'.format(blob.id)) +print('Size: {} bytes'.format(blob.size)) +print('Content type: {}'.format(blob.content_type)) +print('Public URL: {}'.format(blob.public_url)) +``` + +## Download a blob to a local directory + + +```python +output_file_name = 'resources/downloaded-us-states.txt' +blob.download_to_filename(output_file_name) + +print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) +``` + +## Cleaning up + +### Delete a blob + + +```python +blob = client.get_bucket(bucket_name).get_blob(blob_name) +blob.delete() + +print('Blob {} deleted.'.format(blob.name)) +``` + +### Delete a bucket + +Note that the bucket must be empty before it can be deleted. + + +```python +bucket = client.get_bucket(bucket_name) +bucket.delete() + +print('Bucket {} deleted.'.format(bucket.name)) +``` + +## Next Steps + +Read more about Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/storage-commands.md b/notebooks/rendered/unexecuted/storage-commands.md index efa9bbe734b..25c7119e2b5 100644 --- a/notebooks/rendered/unexecuted/storage-commands.md +++ b/notebooks/rendered/unexecuted/storage-commands.md @@ -1,7 +1,7 @@ # Storage Commands -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. ## List available commands @@ -26,7 +26,7 @@ For more information about naming buckets, see [Bucket name requirements](https: bucket_name = 'your-new-bucket' ``` -NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables. +NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. Next, create the new bucket with the `gsutil mb` command: @@ -41,12 +41,18 @@ Replace 'your-project-id' in the cell below with your project ID and run the cel ```python -!gsutil ls -p your-project-id +# Replace the string below with your project ID +project_id = 'your-project-id' +``` + + +```python +!gsutil ls -p $project_id ``` ## Get bucket metadata -The next cell shows how get information on metadata of your Cloud Storage buckets. +The next cell shows how to get information on metadata of your Cloud Storage buckets. To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). @@ -111,7 +117,7 @@ The following command deletes all objects in the bucket before deleting the buck ## Next Steps -Read more about Google Cloud Storage in the documentation: +Read more about Cloud Storage in the documentation: + [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) + [How-To Guides](https://cloud.google.com/storage/docs/how-to) + [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/tutorials/storage/Storage Client Library.ipynb b/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb similarity index 93% rename from notebooks/tutorials/storage/Storage Client Library.ipynb rename to notebooks/tutorials/storage/Cloud Storage Client Library.ipynb index 052a76ff95f..9ff37a749f5 100644 --- a/notebooks/tutorials/storage/Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb @@ -4,9 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Google Cloud Storage\n", + "# Cloud Storage Client Library\n", "\n", - "This tutorial shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html)." + "This tutorial shows how to get started with the [Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html)." ] }, { @@ -33,7 +33,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Next, initialize a client object, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.\n", + "Next, initialize a client object, which is used to interact with the Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.\n", "\n", "See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials.\n", "\n", @@ -116,7 +116,7 @@ "source": [ "## Get bucket metadata\n", "\n", - "The next cell shows how get information on metadata of your Cloud Storage buckets.\n", + "The next cell shows how to get information on metadata of your Cloud Storage buckets.\n", "\n", "To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes)." ] @@ -283,7 +283,7 @@ "source": [ "## Next Steps\n", "\n", - "Read more about Google Cloud Storage in the documentation:\n", + "Read more about Cloud Storage in the documentation:\n", "+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms)\n", "+ [How-To Guides](https://cloud.google.com/storage/docs/how-to)\n", "+ [Pricing](https://cloud.google.com/storage/pricing)" diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage Commands.ipynb index 57ef304db30..e5a0255291a 100644 --- a/notebooks/tutorials/storage/Storage Commands.ipynb +++ b/notebooks/tutorials/storage/Storage Commands.ipynb @@ -6,7 +6,7 @@ "source": [ "# Storage Commands\n", "\n", - "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Google Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`." + "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`." ] }, { @@ -56,7 +56,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "NOTE: In the examples below, the variables are referenced in the command using `$` and `{}`. You may replace the interpolated variables with literal values if they are constant instead of creating and using variables.\n", + "NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters.\n", "\n", "Next, create the new bucket with the `gsutil mb` command:" ] @@ -85,7 +85,17 @@ "metadata": {}, "outputs": [], "source": [ - "!gsutil ls -p your-project-id" + "# Replace the string below with your project ID\n", + "project_id = 'your-project-id'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!gsutil ls -p $project_id" ] }, { @@ -94,7 +104,7 @@ "source": [ "## Get bucket metadata\n", "\n", - "The next cell shows how get information on metadata of your Cloud Storage buckets.\n", + "The next cell shows how to get information on metadata of your Cloud Storage buckets.\n", "\n", "To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes)." ] @@ -233,7 +243,7 @@ "source": [ "## Next Steps\n", "\n", - "Read more about Google Cloud Storage in the documentation:\n", + "Read more about Cloud Storage in the documentation:\n", "+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms)\n", "+ [How-To Guides](https://cloud.google.com/storage/docs/how-to)\n", "+ [Pricing](https://cloud.google.com/storage/pricing)" From e9d112005a57c6b62c1efa92b6e3bb5c751ca065 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Wed, 30 Jan 2019 16:27:48 -0800 Subject: [PATCH 10/24] add BQML tutorial from codelab --- .../getting-started-with-bigquery-ml.md | 374 ++++++++++++++++++ .../getting-started-with-bigquery-ml.md | 183 +++++++++ .../Getting Started with BigQuery ML.ipynb | 297 ++++++++++++++ 3 files changed, 854 insertions(+) create mode 100644 notebooks/rendered/executed/getting-started-with-bigquery-ml.md create mode 100644 notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md create mode 100644 notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb diff --git a/notebooks/rendered/executed/getting-started-with-bigquery-ml.md b/notebooks/rendered/executed/getting-started-with-bigquery-ml.md new file mode 100644 index 00000000000..104223c195f --- /dev/null +++ b/notebooks/rendered/executed/getting-started-with-bigquery-ml.md @@ -0,0 +1,374 @@ + +# Getting Started with BigQuery ML + +BigQuery ML (BQML) enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratise machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement. + +In this tutorial, you'll use the [sample Analytics 360 dataset](https://support.google.com/analytics/answer/3437719) to create a model that predicts whether a visitor will make a transaction. + +## Create a dataset + + +```python +from google.cloud import bigquery + +client = bigquery.Client(location="US") +dataset = client.create_dataset("bqml_tutorial") +``` + +## Create a Model + +### Logistic regression for Analytics 360 +Now, let's move on to our task. Here is how you would create a model to predict whether a visitor will make a transaction. + + +```python +%%bigquery +CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` +OPTIONS(model_type='logistic_reg') AS +SELECT + IF(totals.transactions IS NULL, 0, 1) AS label, + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(geoNetwork.country, "") AS country, + IFNULL(totals.pageviews, 0) AS pageviews +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20160801' AND '20170631' +LIMIT 100000; +``` + + + + +
+ + + + + + + + + +
+
+ + + +Here, we use the visitor's device's operating system, whether said device is a mobile device, the visitor's country and the number of page views as the criteria for whether a transaction has been made. + +In this case, "bqml_tutorial" is the name of the dataset and "sample_model" is the name of our model. The model type specified is binary logistic regression. In this case, `label` is what we're trying to fit to. Note that if you're only interested in 1 column, this is an alternative way to setting `input_label_cols`. We're also limiting our training data to those collected from 1 August 2016 to 31 June 2017. We're doing this to save the last month of data for "prediction". Furthermore, we're limiting to 100,000 data points to save us some time. Feel free to remove the last line if you're not in a rush. + +Running the CREATE MODEL command creates a Query Job that will run asynchronously so you can, for example, close or refresh the browser. + +When the job is complete, you will see an empty DataFrame returned below the cell (it may be rendered as a small box or line, depending upon your settings). This is expected because there are no query results returned from creating a model. + +## Evaluate the Model + + +```python +%%bigquery +SELECT + * +FROM + ml.EVALUATE(MODEL `bqml_tutorial.sample_model`, ( +SELECT + IF(totals.transactions IS NULL, 0, 1) AS label, + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(geoNetwork.country, "") AS country, + IFNULL(totals.pageviews, 0) AS pageviews +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')); +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
precisionrecallaccuracyf1_scorelog_lossroc_auc
00.4545450.1117320.9852360.1793720.0472020.9837
+
+ + + +If used with a linear regression model, the above query returns the following columns: `mean_absolute_error`, `mean_squared_error`, `mean_squared_log_error`, `median_absolute_error`, `r2_score`, `explained_variance`. If used with a logistic regression model, the above query returns the following columns: `precision`, `recall`, `accuracy`, `f1_score`, `log_loss`, `roc_auc`. Please consult the machine learning glossary or run a Google search to understand how each of these metrics are calculated and what they mean. + +Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this: + +| | precision | recall | accuracy | f1_score | log_loss | roc_auc | +|---|---|---|---|---|---|---| +| 1 | 0.437838 | 0.075419 | 0.985249 | 0.128674 | 0.047682 | 0.982956 | + +## Use the Model + +### Predict purchases per country + +Here we try to predict the number of transactions made by visitors of each country, sort the results and select the top 10 countries by purchases. + + +```python +%%bigquery +SELECT + country, + SUM(predicted_label) as total_predicted_purchases +FROM + ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( +SELECT + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(totals.pageviews, 0) AS pageviews, + IFNULL(geoNetwork.country, "") AS country +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) +GROUP BY country +ORDER BY total_predicted_purchases DESC +LIMIT 10; +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
countrytotal_predicted_purchases
0United States221
1Taiwan11
2Canada8
3India3
4United Kingdom2
5Singapore2
6Japan2
7Turkey2
8Thailand1
9Guyana1
+
+ + + +Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this: + +| | country | total_predicted_purchases | +|---|---|---|---| +| 0 | United States | 467 | +| 1 | Canada | 8 | +| 2 | Taiwan | 6 | +| 3 | India | 5 | +| 4 | United Kingdom | 3 | +| 5 | Turkey | 3 | +| 6 | Japan | 2 | +| 7 | Germany | 2 | +| 8 | Hong Kong | 2 | +| 9 | Singapore | 2 | + +### Predict purchases per user + +Here is another example. This time we try to predict the number of transactions each visitor makes, sort the results and select the top 10 visitors by transactions. + + +```python +%%bigquery +SELECT + fullVisitorId, + SUM(predicted_label) as total_predicted_purchases +FROM + ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( +SELECT + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(totals.pageviews, 0) AS pageviews, + IFNULL(geoNetwork.country, "") AS country, + fullVisitorId +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) +GROUP BY fullVisitorId +ORDER BY total_predicted_purchases DESC +LIMIT 10; +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
fullVisitorIdtotal_predicted_purchases
094178574712951310454
183889310329550527463
212809936612043474502
350739197610516301912
417120667030994876522
58069922490326866502
603763940560921891132
774203005015230124602
880646251500335083962
91122883309288959422
+
+ + + +You should see a table similar to this: + +| | country | total_predicted_purchases | +|---|---|---|---| +| 0 | 9417857471295131045 | 3 | +| 1 | 8388931032955052746 | 2 | +| 2 | 7420300501523012460 | 2 | +| 3 | 806992249032686650 | 2 | +| 4 | 0376394056092189113 | 2 | +| 5 | 2969418676126258798 | 2 | +| 6 | 489038402765684003 | 2 | +| 7 | 057693500927581077 | 2 | +| 8 | 112288330928895942 | 2 | +| 9 | 1280993661204347450 | 2 | + +## Congratulations! + +You completed the tutorial. Looking for a challenge? Try making a linear regression model with BQML. + +What we've covered: ++ Create a binary logistic regression model ++ Evaluate the model ++ Use model to make predictions + +## Cleaning up + +To delete the resources created by this tutorial, execute the following code to delete the dataset and its contents: + + +```python +client.delete_dataset(dataset, delete_contents=True) +``` + +## Next Steps + +For more information about BQML, please refer to the [documentation](https://cloud.google.com/bigquery/docs/bigqueryml-intro). diff --git a/notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md b/notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md new file mode 100644 index 00000000000..e800abf5444 --- /dev/null +++ b/notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md @@ -0,0 +1,183 @@ + +# Getting Started with BigQuery ML + +BigQuery ML (BQML) enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratise machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement. + +In this tutorial, you'll use the [sample Analytics 360 dataset](https://support.google.com/analytics/answer/3437719) to create a model that predicts whether a visitor will make a transaction. + +## Create a dataset + + +```python +from google.cloud import bigquery + +client = bigquery.Client(location="US") +dataset = client.create_dataset("bqml_tutorial") +``` + +## Create a Model + +### Logistic regression for Analytics 360 +Now, let's move on to our task. Here is how you would create a model to predict whether a visitor will make a transaction. + + +```python +%%bigquery +CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` +OPTIONS(model_type='logistic_reg') AS +SELECT + IF(totals.transactions IS NULL, 0, 1) AS label, + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(geoNetwork.country, "") AS country, + IFNULL(totals.pageviews, 0) AS pageviews +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20160801' AND '20170631' +LIMIT 100000; +``` + +Here, we use the visitor's device's operating system, whether said device is a mobile device, the visitor's country and the number of page views as the criteria for whether a transaction has been made. + +In this case, "bqml_tutorial" is the name of the dataset and "sample_model" is the name of our model. The model type specified is binary logistic regression. In this case, `label` is what we're trying to fit to. Note that if you're only interested in 1 column, this is an alternative way to setting `input_label_cols`. We're also limiting our training data to those collected from 1 August 2016 to 31 June 2017. We're doing this to save the last month of data for "prediction". Furthermore, we're limiting to 100,000 data points to save us some time. Feel free to remove the last line if you're not in a rush. + +Running the CREATE MODEL command creates a Query Job that will run asynchronously so you can, for example, close or refresh the browser. + +When the job is complete, you will see an empty DataFrame returned below the cell (it may be rendered as a small box or line, depending upon your settings). This is expected because there are no query results returned from creating a model. + +## Evaluate the Model + + +```python +%%bigquery +SELECT + * +FROM + ml.EVALUATE(MODEL `bqml_tutorial.sample_model`, ( +SELECT + IF(totals.transactions IS NULL, 0, 1) AS label, + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(geoNetwork.country, "") AS country, + IFNULL(totals.pageviews, 0) AS pageviews +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')); +``` + +If used with a linear regression model, the above query returns the following columns: `mean_absolute_error`, `mean_squared_error`, `mean_squared_log_error`, `median_absolute_error`, `r2_score`, `explained_variance`. If used with a logistic regression model, the above query returns the following columns: `precision`, `recall`, `accuracy`, `f1_score`, `log_loss`, `roc_auc`. Please consult the machine learning glossary or run a Google search to understand how each of these metrics are calculated and what they mean. + +Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this: + +| | precision | recall | accuracy | f1_score | log_loss | roc_auc | +|---|---|---|---|---|---|---| +| 1 | 0.437838 | 0.075419 | 0.985249 | 0.128674 | 0.047682 | 0.982956 | + +## Use the Model + +### Predict purchases per country + +Here we try to predict the number of transactions made by visitors of each country, sort the results and select the top 10 countries by purchases. + + +```python +%%bigquery +SELECT + country, + SUM(predicted_label) as total_predicted_purchases +FROM + ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( +SELECT + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(totals.pageviews, 0) AS pageviews, + IFNULL(geoNetwork.country, "") AS country +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) +GROUP BY country +ORDER BY total_predicted_purchases DESC +LIMIT 10; +``` + +Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this: + +| | country | total_predicted_purchases | +|---|---|---|---| +| 0 | United States | 467 | +| 1 | Canada | 8 | +| 2 | Taiwan | 6 | +| 3 | India | 5 | +| 4 | United Kingdom | 3 | +| 5 | Turkey | 3 | +| 6 | Japan | 2 | +| 7 | Germany | 2 | +| 8 | Hong Kong | 2 | +| 9 | Singapore | 2 | + +### Predict purchases per user + +Here is another example. This time we try to predict the number of transactions each visitor makes, sort the results and select the top 10 visitors by transactions. + + +```python +%%bigquery +SELECT + fullVisitorId, + SUM(predicted_label) as total_predicted_purchases +FROM + ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( +SELECT + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(totals.pageviews, 0) AS pageviews, + IFNULL(geoNetwork.country, "") AS country, + fullVisitorId +FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` +WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) +GROUP BY fullVisitorId +ORDER BY total_predicted_purchases DESC +LIMIT 10; +``` + +You should see a table similar to this: + +| | country | total_predicted_purchases | +|---|---|---|---| +| 0 | 9417857471295131045 | 3 | +| 1 | 8388931032955052746 | 2 | +| 2 | 7420300501523012460 | 2 | +| 3 | 806992249032686650 | 2 | +| 4 | 0376394056092189113 | 2 | +| 5 | 2969418676126258798 | 2 | +| 6 | 489038402765684003 | 2 | +| 7 | 057693500927581077 | 2 | +| 8 | 112288330928895942 | 2 | +| 9 | 1280993661204347450 | 2 | + +## Congratulations! + +You completed the tutorial. Looking for a challenge? Try making a linear regression model with BQML. + +What we've covered: ++ Create a binary logistic regression model ++ Evaluate the model ++ Use model to make predictions + +## Cleaning up + +To delete the resources created by this tutorial, execute the following code to delete the dataset and its contents: + + +```python +client.delete_dataset(dataset, delete_contents=True) +``` + +## Next Steps + +For more information about BQML, please refer to the [documentation](https://cloud.google.com/bigquery/docs/bigqueryml-intro). diff --git a/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb b/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb new file mode 100644 index 00000000000..7f7b4325b47 --- /dev/null +++ b/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb @@ -0,0 +1,297 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting Started with BigQuery ML\n", + "\n", + "BigQuery ML (BQML) enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratise machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement.\n", + "\n", + "In this tutorial, you'll use the [sample Analytics 360 dataset](https://support.google.com/analytics/answer/3437719) to create a model that predicts whether a visitor will make a transaction." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a dataset" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from google.cloud import bigquery\n", + "\n", + "client = bigquery.Client(location=\"US\")\n", + "dataset = client.create_dataset(\"bqml_tutorial\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a Model\n", + "\n", + "### Logistic regression for Analytics 360\n", + "Now, let's move on to our task. Here is how you would create a model to predict whether a visitor will make a transaction." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery\n", + "CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` \n", + "OPTIONS(model_type='logistic_reg') AS\n", + "SELECT\n", + " IF(totals.transactions IS NULL, 0, 1) AS label,\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(geoNetwork.country, \"\") AS country,\n", + " IFNULL(totals.pageviews, 0) AS pageviews\n", + "FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + "WHERE\n", + " _TABLE_SUFFIX BETWEEN '20160801' AND '20170631'\n", + "LIMIT 100000;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, we use the visitor's device's operating system, whether said device is a mobile device, the visitor's country and the number of page views as the criteria for whether a transaction has been made.\n", + "\n", + "In this case, \"bqml_tutorial\" is the name of the dataset and \"sample_model\" is the name of our model. The model type specified is binary logistic regression. In this case, `label` is what we're trying to fit to. Note that if you're only interested in 1 column, this is an alternative way to setting `input_label_cols`. We're also limiting our training data to those collected from 1 August 2016 to 31 June 2017. We're doing this to save the last month of data for \"prediction\". Furthermore, we're limiting to 100,000 data points to save us some time. Feel free to remove the last line if you're not in a rush.\n", + "\n", + "Running the CREATE MODEL command creates a Query Job that will run asynchronously so you can, for example, close or refresh the browser.\n", + "\n", + "When the job is complete, you will see an empty DataFrame returned below the cell (it may be rendered as a small box or line, depending upon your settings). This is expected because there are no query results returned from creating a model." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Evaluate the Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery\n", + "SELECT\n", + " *\n", + "FROM\n", + " ml.EVALUATE(MODEL `bqml_tutorial.sample_model`, (\n", + "SELECT\n", + " IF(totals.transactions IS NULL, 0, 1) AS label,\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(geoNetwork.country, \"\") AS country,\n", + " IFNULL(totals.pageviews, 0) AS pageviews\n", + "FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + "WHERE\n", + " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If used with a linear regression model, the above query returns the following columns: `mean_absolute_error`, `mean_squared_error`, `mean_squared_log_error`, `median_absolute_error`, `r2_score`, `explained_variance`. If used with a logistic regression model, the above query returns the following columns: `precision`, `recall`, `accuracy`, `f1_score`, `log_loss`, `roc_auc`. Please consult the machine learning glossary or run a Google search to understand how each of these metrics are calculated and what they mean.\n", + "\n", + "Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this:\n", + "\n", + "| | precision | recall | accuracy | f1_score | log_loss | roc_auc |\n", + "|---|---|---|---|---|---|---|\n", + "| 1 | 0.437838 | 0.075419 | 0.985249 | 0.128674 | 0.047682 | 0.982956 |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Use the Model\n", + "\n", + "### Predict purchases per country\n", + "\n", + "Here we try to predict the number of transactions made by visitors of each country, sort the results and select the top 10 countries by purchases." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery\n", + "SELECT\n", + " country,\n", + " SUM(predicted_label) as total_predicted_purchases\n", + "FROM\n", + " ml.PREDICT(MODEL `bqml_tutorial.sample_model`, (\n", + "SELECT\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(totals.pageviews, 0) AS pageviews,\n", + " IFNULL(geoNetwork.country, \"\") AS country\n", + "FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + "WHERE\n", + " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))\n", + "GROUP BY country\n", + "ORDER BY total_predicted_purchases DESC\n", + "LIMIT 10;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this:\n", + "\n", + "| | country | total_predicted_purchases |\n", + "|---|---|---|---|\n", + "| 0 | United States | 467 |\n", + "| 1 | Canada | 8 |\n", + "| 2 | Taiwan | 6 |\n", + "| 3 | India | 5 |\n", + "| 4 | United Kingdom | 3 |\n", + "| 5 | Turkey | 3 |\n", + "| 6 | Japan | 2 |\n", + "| 7 | Germany | 2 |\n", + "| 8 | Hong Kong | 2 |\n", + "| 9 | Singapore | 2 |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Predict purchases per user\n", + "\n", + "Here is another example. This time we try to predict the number of transactions each visitor makes, sort the results and select the top 10 visitors by transactions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery\n", + "SELECT\n", + " fullVisitorId,\n", + " SUM(predicted_label) as total_predicted_purchases\n", + "FROM\n", + " ml.PREDICT(MODEL `bqml_tutorial.sample_model`, (\n", + "SELECT\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(totals.pageviews, 0) AS pageviews,\n", + " IFNULL(geoNetwork.country, \"\") AS country,\n", + " fullVisitorId\n", + "FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + "WHERE\n", + " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))\n", + "GROUP BY fullVisitorId\n", + "ORDER BY total_predicted_purchases DESC\n", + "LIMIT 10;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You should see a table similar to this:\n", + "\n", + "| | country | total_predicted_purchases |\n", + "|---|---|---|---|\n", + "| 0 | 9417857471295131045 | 3 |\n", + "| 1 | 8388931032955052746 | 2 |\n", + "| 2 | 7420300501523012460 | 2 |\n", + "| 3 | 806992249032686650 | 2 |\n", + "| 4 | 0376394056092189113 | 2 |\n", + "| 5 | 2969418676126258798 | 2 |\n", + "| 6 | 489038402765684003 | 2 |\n", + "| 7 | 057693500927581077 | 2 |\n", + "| 8 | 112288330928895942 | 2 |\n", + "| 9 | 1280993661204347450 | 2 |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Congratulations!\n", + "\n", + "You completed the tutorial. Looking for a challenge? Try making a linear regression model with BQML.\n", + "\n", + "What we've covered:\n", + "+ Create a binary logistic regression model\n", + "+ Evaluate the model\n", + "+ Use model to make predictions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cleaning up\n", + "\n", + "To delete the resources created by this tutorial, execute the following code to delete the dataset and its contents:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "client.delete_dataset(dataset, delete_contents=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Next Steps\n", + "\n", + "For more information about BQML, please refer to the [documentation](https://cloud.google.com/bigquery/docs/bigqueryml-intro)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Local google-cloud-bigquery development", + "language": "python", + "name": "venv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 87cc6b4195f4b9f701a602a95efc45fcbd0950ed Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Tue, 5 Feb 2019 16:36:16 -0800 Subject: [PATCH 11/24] add alixhami as notebooks codeowner --- .github/CODEOWNERS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5e9a8238a86..90b740e9aa3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -9,3 +9,6 @@ bigquery/transfer/* @tswast # Tim Swast is the primary maintainer of the Composer samples. composer/* @tswast + +# Alix Hamilton is the primary maintainer of the Jupyter notebook samples +notebooks/* @alixhami From 1a4edba8fbb526dbd3ca3f98f6a0c66ae3eedbb1 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Tue, 5 Feb 2019 20:09:39 -0800 Subject: [PATCH 12/24] update tables from markdown to html to solve rendering issue --- .../Getting Started with BigQuery ML.ipynb | 78 ++++++++++++------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb b/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb index 7f7b4325b47..ab543925bea 100644 --- a/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb +++ b/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb @@ -113,9 +113,27 @@ "\n", "Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this:\n", "\n", - "| | precision | recall | accuracy | f1_score | log_loss | roc_auc |\n", - "|---|---|---|---|---|---|---|\n", - "| 1 | 0.437838 | 0.075419 | 0.985249 | 0.128674 | 0.047682 | 0.982956 |" + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
precisionrecallaccuracyf1_scorelog_lossroc_auc
10.4378380.0754190.9852490.1286740.0476820.982956
" ] }, { @@ -161,18 +179,19 @@ "source": [ "Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this:\n", "\n", - "| | country | total_predicted_purchases |\n", - "|---|---|---|---|\n", - "| 0 | United States | 467 |\n", - "| 1 | Canada | 8 |\n", - "| 2 | Taiwan | 6 |\n", - "| 3 | India | 5 |\n", - "| 4 | United Kingdom | 3 |\n", - "| 5 | Turkey | 3 |\n", - "| 6 | Japan | 2 |\n", - "| 7 | Germany | 2 |\n", - "| 8 | Hong Kong | 2 |\n", - "| 9 | Singapore | 2 |" + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrytotal_predicted_purchases
0UnitedStates467
1Canada8
2Taiwan6
3India5
4UnitedKingdom3
5Turkey3
6Japan2
7Germany2
8HongKong2
9Singapore2
" ] }, { @@ -217,18 +236,19 @@ "source": [ "You should see a table similar to this:\n", "\n", - "| | country | total_predicted_purchases |\n", - "|---|---|---|---|\n", - "| 0 | 9417857471295131045 | 3 |\n", - "| 1 | 8388931032955052746 | 2 |\n", - "| 2 | 7420300501523012460 | 2 |\n", - "| 3 | 806992249032686650 | 2 |\n", - "| 4 | 0376394056092189113 | 2 |\n", - "| 5 | 2969418676126258798 | 2 |\n", - "| 6 | 489038402765684003 | 2 |\n", - "| 7 | 057693500927581077 | 2 |\n", - "| 8 | 112288330928895942 | 2 |\n", - "| 9 | 1280993661204347450 | 2 |" + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countrytotal_predicted_purchases
094178574712951310453
183889310329550527462
274203005015230124602
38069922490326866502
403763940560921891132
529694186761262587982
64890384027656840032
70576935009275810772
81122883309288959422
912809936612043474502
" ] }, { @@ -275,9 +295,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { From efccfa6cd9b5af9be15c93b42e23ea29cdafdf82 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Tue, 5 Feb 2019 20:10:55 -0800 Subject: [PATCH 13/24] update to use dataset_id variable and interpolation --- .../bigquery/BigQuery Shell Commands.ipynb | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb b/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb index 1bec9143a04..3116d69963e 100644 --- a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb @@ -35,7 +35,7 @@ "\n", "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", "\n", - "The command below creates a new dataset in the US named \"your_new_dataset\"." + "First, define a name for your new dataset:" ] }, { @@ -44,7 +44,25 @@ "metadata": {}, "outputs": [], "source": [ - "!bq --location=US mk --dataset \"your_dataset_id\"" + "dataset_id = \"your_new_dataset\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The command below creates a new dataset in the US using the ID defined above.\n", + "\n", + "NOTE: In the examples below, the `dataset_id` variable is referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!bq --location=US mk --dataset $dataset_id" ] }, { @@ -80,7 +98,7 @@ "metadata": {}, "outputs": [], "source": [ - "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv'" + "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_local_file 'resources/us-states.csv'" ] }, { @@ -98,7 +116,7 @@ "metadata": {}, "outputs": [], "source": [ - "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" + "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" ] }, { @@ -125,15 +143,15 @@ "metadata": {}, "outputs": [], "source": [ - "!bq rm -r -f --dataset your_dataset_id" + "!bq rm -r -f --dataset $dataset_id" ] } ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { From 154635ea356a6d04baff97182146fd679e9d6a42 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Tue, 5 Feb 2019 20:11:45 -0800 Subject: [PATCH 14/24] updates to python3 kernel from virtualenv --- notebooks/tutorials/bigquery/BigQuery Basics.ipynb | 6 +++--- notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb | 4 ++-- .../tutorials/bigquery/Visualize BigQuery Public Data.ipynb | 4 ++-- .../tutorials/storage/Cloud Storage Client Library.ipynb | 4 ++-- notebooks/tutorials/storage/Storage Commands.ipynb | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb index fe6d5616382..a55744301b0 100644 --- a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb @@ -69,7 +69,7 @@ "metadata": {}, "outputs": [], "source": [ - "client = bigquery.Client(location=\"US\", project=\"your-project-id\")" + "# client = bigquery.Client(location=\"US\", project=\"your-project-id\")" ] }, { @@ -339,9 +339,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb index 3a167d41734..a6a2dc701f0 100644 --- a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb @@ -158,9 +158,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb b/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb index 606871bad30..1df73278925 100644 --- a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb +++ b/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb @@ -249,9 +249,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb b/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb index 9ff37a749f5..ce5eeec9809 100644 --- a/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb @@ -292,9 +292,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage Commands.ipynb index e5a0255291a..8c98b08ba72 100644 --- a/notebooks/tutorials/storage/Storage Commands.ipynb +++ b/notebooks/tutorials/storage/Storage Commands.ipynb @@ -252,9 +252,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Local google-cloud-bigquery development", + "display_name": "Python 3", "language": "python", - "name": "venv" + "name": "python3" }, "language_info": { "codemirror_mode": { From 386bef837b22dce6627cf37cd6072295d2ab4c99 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Tue, 5 Feb 2019 21:11:55 -0800 Subject: [PATCH 15/24] remove unexecuted rendered notebooks --- .../{executed => }/bigquery-basics.md | 4 +- .../{executed => }/bigquery-query-magic.md | 6 +- .../{executed => }/bigquery-shell-commands.md | 37 +- .../cloud-storage-client-library.md | 2 +- .../executed/storage-client-library.md | 201 ----------- .../visualize-bigquery-public-data_10_0.png | Bin 15605 -> 0 bytes .../visualize-bigquery-public-data_20_0.png | Bin 12721 -> 0 bytes .../visualize-bigquery-public-data_6_0.png | Bin 7378 -> 0 bytes .../getting-started-with-bigquery-ml.md | 126 ++++--- .../{executed => }/storage-commands.md | 318 +++++++++--------- .../rendered/unexecuted/bigquery-basics.md | 232 ------------- .../unexecuted/bigquery-query-magic.md | 91 ----- .../unexecuted/bigquery-shell-commands.md | 64 ---- .../cloud-storage-client-library.md | 160 --------- .../getting-started-with-bigquery-ml.md | 183 ---------- .../unexecuted/storage-client-library.md | 160 --------- .../rendered/unexecuted/storage-commands.md | 123 ------- .../visualize-bigquery-public-data.md | 146 -------- .../visualize-bigquery-public-data_10_0.png | Bin 0 -> 17935 bytes .../visualize-bigquery-public-data_16_0.png | Bin .../visualize-bigquery-public-data_20_0.png | Bin 0 -> 12577 bytes .../visualize-bigquery-public-data_6_0.png | Bin 0 -> 7326 bytes .../visualize-bigquery-public-data.md | 0 23 files changed, 258 insertions(+), 1595 deletions(-) rename notebooks/rendered/{executed => }/bigquery-basics.md (98%) rename notebooks/rendered/{executed => }/bigquery-query-magic.md (98%) rename notebooks/rendered/{executed => }/bigquery-shell-commands.md (91%) rename notebooks/rendered/{executed => }/cloud-storage-client-library.md (98%) delete mode 100644 notebooks/rendered/executed/storage-client-library.md delete mode 100644 notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png delete mode 100644 notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png delete mode 100644 notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png rename notebooks/rendered/{executed => }/getting-started-with-bigquery-ml.md (81%) rename notebooks/rendered/{executed => }/storage-commands.md (92%) delete mode 100644 notebooks/rendered/unexecuted/bigquery-basics.md delete mode 100644 notebooks/rendered/unexecuted/bigquery-query-magic.md delete mode 100644 notebooks/rendered/unexecuted/bigquery-shell-commands.md delete mode 100644 notebooks/rendered/unexecuted/cloud-storage-client-library.md delete mode 100644 notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md delete mode 100644 notebooks/rendered/unexecuted/storage-client-library.md delete mode 100644 notebooks/rendered/unexecuted/storage-commands.md delete mode 100644 notebooks/rendered/unexecuted/visualize-bigquery-public-data.md create mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png rename notebooks/rendered/{executed => }/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png (100%) create mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png create mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png rename notebooks/rendered/{executed => }/visualize-bigquery-public-data.md (100%) diff --git a/notebooks/rendered/executed/bigquery-basics.md b/notebooks/rendered/bigquery-basics.md similarity index 98% rename from notebooks/rendered/executed/bigquery-basics.md rename to notebooks/rendered/bigquery-basics.md index 2e148f41c93..38a04a69eb4 100644 --- a/notebooks/rendered/executed/bigquery-basics.md +++ b/notebooks/rendered/bigquery-basics.md @@ -39,7 +39,7 @@ Alternatively, you can explicitly specify a project when constructing the client ```python -client = bigquery.Client(location="US", project="your-project-id") +# client = bigquery.Client(location="US", project="your-project-id") ``` ## Run a query on a public dataset @@ -367,7 +367,7 @@ destination_table = client.get_table(table_ref) print('Loaded {} rows.'.format(destination_table.num_rows)) ``` - Starting job a27afe96-d36b-458e-b72f-ba47f3d192dc + Starting job 1c54e163-d785-4551-b4b7-7170ba07e00a Job finished. Loaded 50 rows. diff --git a/notebooks/rendered/executed/bigquery-query-magic.md b/notebooks/rendered/bigquery-query-magic.md similarity index 98% rename from notebooks/rendered/executed/bigquery-query-magic.md rename to notebooks/rendered/bigquery-query-magic.md index 0442f926763..8e800003602 100644 --- a/notebooks/rendered/executed/bigquery-query-magic.md +++ b/notebooks/rendered/bigquery-query-magic.md @@ -103,9 +103,9 @@ ORDER BY count DESC LIMIT 10 ``` - Executing query with job ID: 82f4ffb5-43f8-4e87-b8a4-ed710c4c16ac - Query executing: 0.65s - Query complete after 1.08s + Executing query with job ID: 0e3ca180-c6e9-4298-bbc4-b68e7e6fdebd + Query executing: 0.52s + Query complete after 0.83s diff --git a/notebooks/rendered/executed/bigquery-shell-commands.md b/notebooks/rendered/bigquery-shell-commands.md similarity index 91% rename from notebooks/rendered/executed/bigquery-shell-commands.md rename to notebooks/rendered/bigquery-shell-commands.md index 6090ed8e7e7..1b9d7ada952 100644 --- a/notebooks/rendered/executed/bigquery-shell-commands.md +++ b/notebooks/rendered/bigquery-shell-commands.md @@ -157,7 +157,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he bq ls --transfer_log --message_type='messageTypes:INFO,ERROR' projects/p/locations/l/transferConfigs/c/runs/r - + mk Create a dataset, table, view, or transfer configuration with this name. See 'bq help load' for more information on specifying the schema. @@ -235,7 +235,7 @@ To view the available commands for the BigQuery command-line tool, use the `--he echo 'select count(*) from publicdata:samples.shakespeare' | bq query Usage: - query [] + rm Delete the dataset, table, or transfer config described by identifier. @@ -319,14 +319,23 @@ To view the available commands for the BigQuery command-line tool, use the `--he A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). -The command below creates a new dataset in the US named "your_new_dataset". +First, define a name for your new dataset: + + +```python +dataset_id = "your_new_dataset" +``` + +The command below creates a new dataset in the US using the ID defined above. + +NOTE: In the examples below, the `dataset_id` variable is referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. ```python -!bq --location=US mk --dataset "your_dataset_id" +!bq --location=US mk --dataset $dataset_id ``` - Dataset 'your-project-id:your_dataset_id' successfully created. + Dataset 'your-project-id:your_new_dataset' successfully created. ## List datasets @@ -340,12 +349,6 @@ The command below lists lists all datasets in your current project. datasetId ------------------------------ - coast - my_new_dataset_1548207931814 - test_dataset - test_dataset_1544925728787 - test_dataset_1544925753705 - your_dataset_id your_new_dataset @@ -355,11 +358,11 @@ The example below demonstrates how to load a local CSV file into a new or existi ```python -!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv' +!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_local_file 'resources/us-states.csv' ``` Upload complete. - Waiting on bqjob_r79803249dee1436f_0000016896639904_1 ... (1s) Current status: DONE + Waiting on bqjob_r6e3244e44cef905c_00000168c0b8a070_1 ... (2s) Current status: DONE ## Load data from Google Cloud Storage to a table @@ -368,10 +371,10 @@ The example below demonstrates how to load a local CSV file into a new or existi ```python -!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' ``` - Waiting on bqjob_r30641d9ed9788ca4_000001689663b441_1 ... (1s) Current status: DONE + Waiting on bqjob_r262c33706835e862_00000168c0b8bf2b_1 ... (1s) Current status: DONE ## Run a query @@ -384,6 +387,6 @@ The following code deletes the dataset created for this tutorial, including all ```python -!bq rm -r -f --dataset your_dataset_id +!bq rm -r -f --dataset $dataset_id ``` - \ No newline at end of file + \ No newline at end of file diff --git a/notebooks/rendered/executed/cloud-storage-client-library.md b/notebooks/rendered/cloud-storage-client-library.md similarity index 98% rename from notebooks/rendered/executed/cloud-storage-client-library.md rename to notebooks/rendered/cloud-storage-client-library.md index fc58e903ed8..c9f9cd61015 100644 --- a/notebooks/rendered/executed/cloud-storage-client-library.md +++ b/notebooks/rendered/cloud-storage-client-library.md @@ -140,7 +140,7 @@ print('Content type: {}'.format(blob.content_type)) print('Public URL: {}'.format(blob.public_url)) ``` - Name: your-new-bucket/us-states.txt/1548890628692952 + Name: your-new-bucket/us-states.txt/1549421467685211 Size: 637 bytes Content type: text/plain Public URL: https://storage.googleapis.com/your-new-bucket/us-states.txt diff --git a/notebooks/rendered/executed/storage-client-library.md b/notebooks/rendered/executed/storage-client-library.md deleted file mode 100644 index 7223e8338f4..00000000000 --- a/notebooks/rendered/executed/storage-client-library.md +++ /dev/null @@ -1,201 +0,0 @@ - -# Google Cloud Storage - -This tutorial shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by importing the library: - - -```python -from google.cloud import storage -``` - -Next, initialize a client object, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. - -Run the following to create a client with your default project: - - -```python -client = storage.Client() -print("Client created using default project: {}".format(client.project)) -``` - - Client created using default project: your-project-id - - -Alternatively, you can explicitly specify a project when constructing the client: - - -```python -# client = storage.Client(project='your-project-id') -``` - -Finally, create a bucket with a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' - -# Creates the new bucket -bucket = client.create_bucket(bucket_name) - -print('Bucket {} created.'.format(bucket.name)) -``` - - Bucket your-new-bucket created. - - -## List buckets in a project - - -```python -buckets = client.list_buckets() - -print("Buckets in {}:".format(client.project)) -for item in buckets: - print("\t" + item.name) -``` - - Buckets in your-project-id: - your-project-id - my-new-bucket-1548180688764 - my-new-bucket-1548208228513 - test-storage-bucket-1548209987490 - your-new-bucket - - -## Get bucket metadata - -The next cell shows how get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -bucket = client.get_bucket(bucket_name) - -print('Bucket name: {}'.format(bucket.name)) -print('Bucket location: {}'.format(bucket.location)) -print('Bucket storage class: {}'.format(bucket.storage_class)) -``` - - Bucket name: your-new-bucket - Bucket location: US - Bucket storage class: STANDARD - - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -blob_name = 'us-states.txt' -blob = bucket.blob(blob_name) - -source_file_name = 'resources/us-states.txt' -blob.upload_from_filename(source_file_name) - -print('File uploaded to {}.'.format(bucket.name)) -``` - - File uploaded to your-new-bucket. - - -## List blobs in a bucket - - -```python -blobs = bucket.list_blobs() - -print("Blobs in {}:".format(bucket.name)) -for item in blobs: - print("\t" + item.name) -``` - - Blobs in your-new-bucket: - us-states.txt - - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -blob = bucket.get_blob(blob_name) - -print('Name: {}'.format(blob.id)) -print('Size: {} bytes'.format(blob.size)) -print('Content type: {}'.format(blob.content_type)) -print('Public URL: {}'.format(blob.public_url)) -``` - - Name: your-new-bucket/us-states.txt/1548801913760895 - Size: 637 bytes - Content type: text/plain - Public URL: https://storage.googleapis.com/your-new-bucket/us-states.txt - - -## Download a blob to a local directory - - -```python -output_file_name = 'resources/downloaded-us-states.txt' -blob.download_to_filename(output_file_name) - -print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) -``` - - Downloaded blob us-states.txt to resources/downloaded-us-states.txt. - - -## Cleaning up - -### Delete a blob - - -```python -blob = client.get_bucket(bucket_name).get_blob(blob_name) -blob.delete() - -print('Blob {} deleted.'.format(blob.name)) -``` - - Blob us-states.txt deleted. - - -### Delete a bucket - -Note that the bucket must be empty before it can be deleted. - - -```python -bucket = client.get_bucket(bucket_name) -bucket.delete() - -print('Bucket {} deleted.'.format(bucket.name)) -``` - - Bucket your-new-bucket deleted. - - -## Next Steps - -Read more about Google Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png deleted file mode 100644 index f844443cd7cbb8c0051a2f7adb068d85c2edd6e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15605 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 LijdORMuGniR-C7w diff --git a/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png deleted file mode 100644 index 1686a466e05c55a1a5d2b78ea7dba27ab58593d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12721 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 Mz;9~4jym#x01<_zn*aa+ diff --git a/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png b/notebooks/rendered/executed/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png deleted file mode 100644 index 120d3e2e5082dcd44533e0dd37f57bfbd900d44c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7378 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 M(jHm%v+pne4 0 -0.454545 -0.111732 -0.985236 -0.179372 -0.047202 -0.9837 +0.461832 +0.112663 +0.985289 +0.181138 +0.046062 +0.98184 @@ -122,9 +122,27 @@ If used with a linear regression model, the above query returns the following co Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this: -| | precision | recall | accuracy | f1_score | log_loss | roc_auc | -|---|---|---|---|---|---|---| -| 1 | 0.437838 | 0.075419 | 0.985249 | 0.128674 | 0.047682 | 0.982956 | + + + + + + + + + + + + + + + + + + + + +
precisionrecallaccuracyf1_scorelog_lossroc_auc
10.4378380.0754190.9852490.1286740.0476820.982956
## Use the Model @@ -171,17 +189,17 @@ LIMIT 10; 0 United States -221 +228 1 -Taiwan -11 +Canada +7 2 -Canada -8 +Taiwan +6 3 @@ -190,32 +208,32 @@ LIMIT 10; 4 -United Kingdom +Turkey 2 5 -Singapore +Japan 2 6 -Japan -2 +United Kingdom +1 7 -Turkey -2 +Vietnam +1 8 -Thailand +El Salvador 1 9 -Guyana +Serbia 1 @@ -226,18 +244,19 @@ LIMIT 10; Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this: -| | country | total_predicted_purchases | -|---|---|---|---| -| 0 | United States | 467 | -| 1 | Canada | 8 | -| 2 | Taiwan | 6 | -| 3 | India | 5 | -| 4 | United Kingdom | 3 | -| 5 | Turkey | 3 | -| 6 | Japan | 2 | -| 7 | Germany | 2 | -| 8 | Hong Kong | 2 | -| 9 | Singapore | 2 | + + + + + + + + + + + + +
countrytotal_predicted_purchases
0UnitedStates467
1Canada8
2Taiwan6
3India5
4UnitedKingdom3
5Turkey3
6Japan2
7Germany2
8HongKong2
9Singapore2
### Predict purchases per user @@ -287,8 +306,8 @@ LIMIT 10; 1 -8388931032955052746 -3 +2969418676126258798 +2 2 @@ -297,27 +316,27 @@ LIMIT 10; 3 -5073919761051630191 +0376394056092189113 2 4 -1712066703099487652 +806992249032686650 2 5 -806992249032686650 +1712066703099487652 2 6 -0376394056092189113 +057693500927581077 2 7 -7420300501523012460 +8388931032955052746 2 @@ -338,18 +357,19 @@ LIMIT 10; You should see a table similar to this: -| | country | total_predicted_purchases | -|---|---|---|---| -| 0 | 9417857471295131045 | 3 | -| 1 | 8388931032955052746 | 2 | -| 2 | 7420300501523012460 | 2 | -| 3 | 806992249032686650 | 2 | -| 4 | 0376394056092189113 | 2 | -| 5 | 2969418676126258798 | 2 | -| 6 | 489038402765684003 | 2 | -| 7 | 057693500927581077 | 2 | -| 8 | 112288330928895942 | 2 | -| 9 | 1280993661204347450 | 2 | + + + + + + + + + + + + +
countrytotal_predicted_purchases
094178574712951310453
183889310329550527462
274203005015230124602
38069922490326866502
403763940560921891132
529694186761262587982
64890384027656840032
70576935009275810772
81122883309288959422
912809936612043474502
## Congratulations! diff --git a/notebooks/rendered/executed/storage-commands.md b/notebooks/rendered/storage-commands.md similarity index 92% rename from notebooks/rendered/executed/storage-commands.md rename to notebooks/rendered/storage-commands.md index 51bd91e6477..91f3e2c8bf9 100644 --- a/notebooks/rendered/executed/storage-commands.md +++ b/notebooks/rendered/storage-commands.md @@ -1,17 +1,17 @@ - -# Storage Commands - -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. - -## List available commands - -The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: - - -```python -!gsutil help -``` - + +# Storage Commands + +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. + +## List available commands + +The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: + + +```python +!gsutil help +``` + Usage: gsutil [-D] [-DD] [-h header]... [-m] [-o] [-q] [command [opts...] args...] Available commands: acl Get, set, or change bucket and/or object ACLs @@ -49,7 +49,7 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help version Print version info about gsutil versioning Enable or suspend versioning for one or more buckets web Set a main page and/or error page for one or more buckets - + Additional help topics: acls Working With Access Control Lists anon Accessing Public Data Without Credentials @@ -71,64 +71,64 @@ The `gsutil` command can be used to perform a wide array of tasks. Run the `help throttling Throttling gsutil versions Object Versioning and Concurrency Control wildcards Wildcard Names - - Use gsutil help for detailed help. - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by defining a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' -``` - -NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. - -Next, create the new bucket with the `gsutil mb` command: - - -```python -!gsutil mb gs://{bucket_name}/ -``` - + + Use gsutil help for detailed help. + +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by defining a globally unique name. + +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = 'your-new-bucket' +``` + +NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. + +Next, create the new bucket with the `gsutil mb` command: + + +```python +!gsutil mb gs://{bucket_name}/ +``` + Creating gs://your-new-bucket/... - - -## List buckets in a project - -Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. - - -```python -# Replace the string below with your project ID -project_id = 'your-project-id' -``` - - -```python -!gsutil ls -p $project_id -``` - + + +## List buckets in a project + +Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. + + +```python +# Replace the string below with your project ID +project_id = 'your-project-id' +``` + + +```python +!gsutil ls -p $project_id +``` + gs://your-new-bucket/ - - -## Get bucket metadata - -The next cell shows how to get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -!gsutil ls -L -b gs://{bucket_name}/ -``` - + + +## Get bucket metadata + +The next cell shows how to get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +!gsutil ls -L -b gs://{bucket_name}/ +``` + gs://your-new-bucket/ : Storage class: STANDARD Location constraint: US @@ -140,10 +140,10 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c Requester Pays enabled: None Labels: None Default KMS key: None - Time created: Wed, 30 Jan 2019 23:23:59 GMT - Time updated: Wed, 30 Jan 2019 23:23:59 GMT + Time created: Wed, 06 Feb 2019 02:51:19 GMT + Time updated: Wed, 06 Feb 2019 02:51:19 GMT Metageneration: 1 - ACL: + ACL: [ { "entity": "project-owners-129776587519", @@ -170,7 +170,7 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c "role": "READER" } ] - Default ACL: + Default ACL: [ { "entity": "project-owners-129776587519", @@ -197,56 +197,56 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c "role": "READER" } ] - - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -!gsutil cp resources/us-states.txt gs://{bucket_name}/ -``` - + + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). + + +```python +!gsutil cp resources/us-states.txt gs://{bucket_name}/ +``` + Copying file://resources/us-states.txt [Content-Type=text/plain]... - - Operation completed over 1 objects/637.0 B. - - -## List blobs in a bucket - - -```python -!gsutil ls -r gs://{bucket_name}/** -``` - + + Operation completed over 1 objects/637.0 B. + + +## List blobs in a bucket + + +```python +!gsutil ls -r gs://{bucket_name}/** +``` + gs://your-new-bucket/us-states.txt - - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -!gsutil ls -L gs://{bucket_name}/us-states.txt -``` - + + +## Get a blob and display metadata + +See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +!gsutil ls -L gs://{bucket_name}/us-states.txt +``` + gs://your-new-bucket/us-states.txt: - Creation time: Wed, 30 Jan 2019 23:24:06 GMT - Update time: Wed, 30 Jan 2019 23:24:06 GMT + Creation time: Wed, 06 Feb 2019 02:51:25 GMT + Update time: Wed, 06 Feb 2019 02:51:25 GMT Storage class: STANDARD Content-Language: en Content-Length: 637 Content-Type: text/plain Hash (crc32c): AmYMRQ== Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CLCthKbTluACEAE= - Generation: 1548890646058672 + ETag: CKeP/OmMpuACEAE= + Generation: 1549421485426599 Metageneration: 1 ACL: [ { @@ -280,49 +280,49 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada } ] TOTAL: 1 objects, 637 bytes (637 B) - - -## Download a blob to a local directory - - -```python -!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt -``` - + + +## Download a blob to a local directory + + +```python +!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt +``` + Copying gs://your-new-bucket/us-states.txt... - - Operation completed over 1 objects/637.0 B. - - -## Cleaning up - -### Delete a blob - - -```python -!gsutil rm gs://{bucket_name}/us-states.txt -``` - + + Operation completed over 1 objects/637.0 B. + + +## Cleaning up + +### Delete a blob + + +```python +!gsutil rm gs://{bucket_name}/us-states.txt +``` + Removing gs://your-new-bucket/us-states.txt... - - Operation completed over 1 objects. - - -### Delete a bucket - -The following command deletes all objects in the bucket before deleting the bucket itself. - - -```python -!gsutil rm -r gs://{bucket_name}/ -``` - + + Operation completed over 1 objects. + + +### Delete a bucket + +The following command deletes all objects in the bucket before deleting the bucket itself. + + +```python +!gsutil rm -r gs://{bucket_name}/ +``` + Removing gs://your-new-bucket/... - - -## Next Steps - -Read more about Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) + + +## Next Steps + +Read more about Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/bigquery-basics.md b/notebooks/rendered/unexecuted/bigquery-basics.md deleted file mode 100644 index a645889070f..00000000000 --- a/notebooks/rendered/unexecuted/bigquery-basics.md +++ /dev/null @@ -1,232 +0,0 @@ - -# BigQuery Basics - -[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library. - -## Import the libraries used in this tutorial - - -```python -from google.cloud import bigquery -import pandas -``` - -## Initialize a client - -To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. - -### Client project -The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. - - -### Client location -Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables. - -Run the following to create a client with your default project: - - -```python -client = bigquery.Client(location="US") -print("Client creating using default project: {}".format(client.project)) -``` - -Alternatively, you can explicitly specify a project when constructing the client: - - -```python -client = bigquery.Client(location="US", project="your-project-id") -``` - -## Run a query on a public dataset - -The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. - -Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). - - -```python -query = """ - SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current` - WHERE state = "TX" - LIMIT 10 -""" -query_job = client.query( - query, - # Location must match that of the dataset(s) referenced in the query. - location="US", -) # API request - starts the query - -df = query_job.to_dataframe() -df -``` - -## Run a parameterized query - -BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query. - -To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value. - -For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation. - - -```python -# Define the query -sql = """ - SELECT word, word_count - FROM `bigquery-public-data.samples.shakespeare` - WHERE corpus = @corpus - AND word_count >= @min_word_count - ORDER BY word_count DESC; -""" - -# Define the parameter values in a query job configuration -job_config = bigquery.QueryJobConfig( - query_parameters=[ - bigquery.ScalarQueryParameter("corpus", "STRING", "romeoandjuliet"), - bigquery.ScalarQueryParameter("min_word_count", "INT64", 250), - ] -) - -# Start the query job -query_job = client.query(sql, location="US", job_config=job_config) - -# Return the results as a pandas DataFrame -query_job.to_dataframe() -``` - -## Create a new dataset - -A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). - - -```python -# Define a name for the new dataset. -dataset_id = 'your_new_dataset' - -# The project defaults to the Client's project if not specified. -dataset = client.create_dataset(dataset_id) # API request -``` - -## Write query results to a destination table - -For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. - - -```python -sql = """ - SELECT corpus - FROM `bigquery-public-data.samples.shakespeare` - GROUP BY corpus; -""" -table_ref = dataset.table("your_new_table_id") -job_config = bigquery.QueryJobConfig( - destination=table_ref -) - -# Start the query, passing in the extra configuration. -query_job = client.query(sql, location="US", job_config=job_config) - -query_job.result() # Waits for the query to finish -print("Query results loaded to table {}".format(table_ref.path)) -``` - -## Load data from a pandas DataFrame to a new table - - -```python -records = [ - {"title": "The Meaning of Life", "release_year": 1983}, - {"title": "Monty Python and the Holy Grail", "release_year": 1975}, - {"title": "Life of Brian", "release_year": 1979}, - {"title": "And Now for Something Completely Different", "release_year": 1971}, -] - -# Optionally set explicit indices. -# If indices are not specified, a column will be created for the default -# indices created by pandas. -index = ["Q24980", "Q25043", "Q24953", "Q16403"] -df = pandas.DataFrame(records, index=pandas.Index(index, name="wikidata_id")) - -table_ref = dataset.table("monty_python") -job = client.load_table_from_dataframe(df, table_ref, location="US") - -job.result() # Waits for table load to complete. -print("Loaded dataframe to {}".format(table_ref.path)) -``` - -## Load data from a local file to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. - - -```python -source_filename = 'resources/us-states.csv' - -table_ref = dataset.table('us_states_from_local_file') -job_config = bigquery.LoadJobConfig( - source_format=bigquery.SourceFormat.CSV, - skip_leading_rows=1, - autodetect=True -) - -with open(source_filename, 'rb') as source_file: - job = client.load_table_from_file( - source_file, - table_ref, - location='US', # Must match the destination dataset location. - job_config=job_config) # API request - -job.result() # Waits for table load to complete. - -print('Loaded {} rows into {}:{}.'.format( - job.output_rows, dataset_id, table_ref.path)) -``` - -## Load data from Google Cloud Storage to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. - - -```python -# Configure the load job -job_config = bigquery.LoadJobConfig( - schema=[ - bigquery.SchemaField('name', 'STRING'), - bigquery.SchemaField('post_abbr', 'STRING') - ], - skip_leading_rows=1, - # The source format defaults to CSV, so the line below is optional. - source_format=bigquery.SourceFormat.CSV -) -uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' -destination_table_ref = dataset.table('us_states_from_gcs') - -# Start the load job -load_job = client.load_table_from_uri( - uri, destination_table_ref, job_config=job_config) -print('Starting job {}'.format(load_job.job_id)) - -load_job.result() # Waits for table load to complete. -print('Job finished.') - -# Retreive the destination table -destination_table = client.get_table(table_ref) -print('Loaded {} rows.'.format(destination_table.num_rows)) -``` - -## Cleaning Up - -The following code deletes the dataset created for this tutorial, including all tables in the dataset. - - -```python -# Retrieve the dataset from the API -dataset = client.get_dataset(client.dataset(dataset_id)) - -# Delete the dataset and its contents -client.delete_dataset(dataset, delete_contents=True) - -print('Deleted dataset: {}'.format(dataset.path)) -``` diff --git a/notebooks/rendered/unexecuted/bigquery-query-magic.md b/notebooks/rendered/unexecuted/bigquery-query-magic.md deleted file mode 100644 index 31080347455..00000000000 --- a/notebooks/rendered/unexecuted/bigquery-query-magic.md +++ /dev/null @@ -1,91 +0,0 @@ - -# BigQuery Query Magic - -Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. - -## Run a query on a public dataset - -The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. - -The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). - - -```python -%%bigquery -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - -## Display verbose output - -As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion. - - -```python -%%bigquery --verbose -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - -## Explicitly specify a project - -By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. - - -```python -project_id = 'your-project-id' -``` - - -```python -%%bigquery --project $project_id -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - -## Assign the query results to a variable - -If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command. - - -```python -%%bigquery df -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT 10 -``` - - -```python -df -``` - -## Run a parameterized query - -Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. - - -```python -params = {"limit": 10} -``` - - -```python -%%bigquery --params $params -SELECT name, SUM(number) as count -FROM `bigquery-public-data.usa_names.usa_1910_current` -GROUP BY name -ORDER BY count DESC -LIMIT @limit -``` diff --git a/notebooks/rendered/unexecuted/bigquery-shell-commands.md b/notebooks/rendered/unexecuted/bigquery-shell-commands.md deleted file mode 100644 index c370e294f7b..00000000000 --- a/notebooks/rendered/unexecuted/bigquery-shell-commands.md +++ /dev/null @@ -1,64 +0,0 @@ - -# BigQuery command-line tool - -The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`. - -## View available commands - -To view the available commands for the BigQuery command-line tool, use the `--help` flag. - - -```python -!bq help -``` - -## Create a new dataset - -A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). - -The command below creates a new dataset in the US named "your_new_dataset". - - -```python -!bq --location=US mk --dataset "your_dataset_id" -``` - -## List datasets - -The command below lists lists all datasets in your current project. - - -```python -!bq ls -``` - -## Load data from a local file to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. - - -```python -!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_local_file 'resources/us-states.csv' -``` - -## Load data from Google Cloud Storage to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. - - -```python -!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV your_dataset_id.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' -``` - -## Run a query - -The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose. - -## Cleaning Up - -The following code deletes the dataset created for this tutorial, including all tables in the dataset. - - -```python -!bq rm -r -f --dataset your_dataset_id -``` diff --git a/notebooks/rendered/unexecuted/cloud-storage-client-library.md b/notebooks/rendered/unexecuted/cloud-storage-client-library.md deleted file mode 100644 index 1b0dc9e1aeb..00000000000 --- a/notebooks/rendered/unexecuted/cloud-storage-client-library.md +++ /dev/null @@ -1,160 +0,0 @@ - -# Cloud Storage Client Library - -This tutorial shows how to get started with the [Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by importing the library: - - -```python -from google.cloud import storage -``` - -Next, initialize a client object, which is used to interact with the Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. - -Run the following to create a client with your default project: - - -```python -client = storage.Client() -print("Client created using default project: {}".format(client.project)) -``` - -Alternatively, you can explicitly specify a project when constructing the client: - - -```python -# client = storage.Client(project='your-project-id') -``` - -Finally, create a bucket with a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' - -# Creates the new bucket -bucket = client.create_bucket(bucket_name) - -print('Bucket {} created.'.format(bucket.name)) -``` - -## List buckets in a project - - -```python -buckets = client.list_buckets() - -print("Buckets in {}:".format(client.project)) -for item in buckets: - print("\t" + item.name) -``` - -## Get bucket metadata - -The next cell shows how to get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -bucket = client.get_bucket(bucket_name) - -print('Bucket name: {}'.format(bucket.name)) -print('Bucket location: {}'.format(bucket.location)) -print('Bucket storage class: {}'.format(bucket.storage_class)) -``` - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -blob_name = 'us-states.txt' -blob = bucket.blob(blob_name) - -source_file_name = 'resources/us-states.txt' -blob.upload_from_filename(source_file_name) - -print('File uploaded to {}.'.format(bucket.name)) -``` - -## List blobs in a bucket - - -```python -blobs = bucket.list_blobs() - -print("Blobs in {}:".format(bucket.name)) -for item in blobs: - print("\t" + item.name) -``` - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -blob = bucket.get_blob(blob_name) - -print('Name: {}'.format(blob.id)) -print('Size: {} bytes'.format(blob.size)) -print('Content type: {}'.format(blob.content_type)) -print('Public URL: {}'.format(blob.public_url)) -``` - -## Download a blob to a local directory - - -```python -output_file_name = 'resources/downloaded-us-states.txt' -blob.download_to_filename(output_file_name) - -print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) -``` - -## Cleaning up - -### Delete a blob - - -```python -blob = client.get_bucket(bucket_name).get_blob(blob_name) -blob.delete() - -print('Blob {} deleted.'.format(blob.name)) -``` - -### Delete a bucket - -Note that the bucket must be empty before it can be deleted. - - -```python -bucket = client.get_bucket(bucket_name) -bucket.delete() - -print('Bucket {} deleted.'.format(bucket.name)) -``` - -## Next Steps - -Read more about Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md b/notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md deleted file mode 100644 index e800abf5444..00000000000 --- a/notebooks/rendered/unexecuted/getting-started-with-bigquery-ml.md +++ /dev/null @@ -1,183 +0,0 @@ - -# Getting Started with BigQuery ML - -BigQuery ML (BQML) enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratise machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement. - -In this tutorial, you'll use the [sample Analytics 360 dataset](https://support.google.com/analytics/answer/3437719) to create a model that predicts whether a visitor will make a transaction. - -## Create a dataset - - -```python -from google.cloud import bigquery - -client = bigquery.Client(location="US") -dataset = client.create_dataset("bqml_tutorial") -``` - -## Create a Model - -### Logistic regression for Analytics 360 -Now, let's move on to our task. Here is how you would create a model to predict whether a visitor will make a transaction. - - -```python -%%bigquery -CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` -OPTIONS(model_type='logistic_reg') AS -SELECT - IF(totals.transactions IS NULL, 0, 1) AS label, - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(geoNetwork.country, "") AS country, - IFNULL(totals.pageviews, 0) AS pageviews -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20160801' AND '20170631' -LIMIT 100000; -``` - -Here, we use the visitor's device's operating system, whether said device is a mobile device, the visitor's country and the number of page views as the criteria for whether a transaction has been made. - -In this case, "bqml_tutorial" is the name of the dataset and "sample_model" is the name of our model. The model type specified is binary logistic regression. In this case, `label` is what we're trying to fit to. Note that if you're only interested in 1 column, this is an alternative way to setting `input_label_cols`. We're also limiting our training data to those collected from 1 August 2016 to 31 June 2017. We're doing this to save the last month of data for "prediction". Furthermore, we're limiting to 100,000 data points to save us some time. Feel free to remove the last line if you're not in a rush. - -Running the CREATE MODEL command creates a Query Job that will run asynchronously so you can, for example, close or refresh the browser. - -When the job is complete, you will see an empty DataFrame returned below the cell (it may be rendered as a small box or line, depending upon your settings). This is expected because there are no query results returned from creating a model. - -## Evaluate the Model - - -```python -%%bigquery -SELECT - * -FROM - ml.EVALUATE(MODEL `bqml_tutorial.sample_model`, ( -SELECT - IF(totals.transactions IS NULL, 0, 1) AS label, - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(geoNetwork.country, "") AS country, - IFNULL(totals.pageviews, 0) AS pageviews -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')); -``` - -If used with a linear regression model, the above query returns the following columns: `mean_absolute_error`, `mean_squared_error`, `mean_squared_log_error`, `median_absolute_error`, `r2_score`, `explained_variance`. If used with a logistic regression model, the above query returns the following columns: `precision`, `recall`, `accuracy`, `f1_score`, `log_loss`, `roc_auc`. Please consult the machine learning glossary or run a Google search to understand how each of these metrics are calculated and what they mean. - -Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this: - -| | precision | recall | accuracy | f1_score | log_loss | roc_auc | -|---|---|---|---|---|---|---| -| 1 | 0.437838 | 0.075419 | 0.985249 | 0.128674 | 0.047682 | 0.982956 | - -## Use the Model - -### Predict purchases per country - -Here we try to predict the number of transactions made by visitors of each country, sort the results and select the top 10 countries by purchases. - - -```python -%%bigquery -SELECT - country, - SUM(predicted_label) as total_predicted_purchases -FROM - ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( -SELECT - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(totals.pageviews, 0) AS pageviews, - IFNULL(geoNetwork.country, "") AS country -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) -GROUP BY country -ORDER BY total_predicted_purchases DESC -LIMIT 10; -``` - -Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this: - -| | country | total_predicted_purchases | -|---|---|---|---| -| 0 | United States | 467 | -| 1 | Canada | 8 | -| 2 | Taiwan | 6 | -| 3 | India | 5 | -| 4 | United Kingdom | 3 | -| 5 | Turkey | 3 | -| 6 | Japan | 2 | -| 7 | Germany | 2 | -| 8 | Hong Kong | 2 | -| 9 | Singapore | 2 | - -### Predict purchases per user - -Here is another example. This time we try to predict the number of transactions each visitor makes, sort the results and select the top 10 visitors by transactions. - - -```python -%%bigquery -SELECT - fullVisitorId, - SUM(predicted_label) as total_predicted_purchases -FROM - ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( -SELECT - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(totals.pageviews, 0) AS pageviews, - IFNULL(geoNetwork.country, "") AS country, - fullVisitorId -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) -GROUP BY fullVisitorId -ORDER BY total_predicted_purchases DESC -LIMIT 10; -``` - -You should see a table similar to this: - -| | country | total_predicted_purchases | -|---|---|---|---| -| 0 | 9417857471295131045 | 3 | -| 1 | 8388931032955052746 | 2 | -| 2 | 7420300501523012460 | 2 | -| 3 | 806992249032686650 | 2 | -| 4 | 0376394056092189113 | 2 | -| 5 | 2969418676126258798 | 2 | -| 6 | 489038402765684003 | 2 | -| 7 | 057693500927581077 | 2 | -| 8 | 112288330928895942 | 2 | -| 9 | 1280993661204347450 | 2 | - -## Congratulations! - -You completed the tutorial. Looking for a challenge? Try making a linear regression model with BQML. - -What we've covered: -+ Create a binary logistic regression model -+ Evaluate the model -+ Use model to make predictions - -## Cleaning up - -To delete the resources created by this tutorial, execute the following code to delete the dataset and its contents: - - -```python -client.delete_dataset(dataset, delete_contents=True) -``` - -## Next Steps - -For more information about BQML, please refer to the [documentation](https://cloud.google.com/bigquery/docs/bigqueryml-intro). diff --git a/notebooks/rendered/unexecuted/storage-client-library.md b/notebooks/rendered/unexecuted/storage-client-library.md deleted file mode 100644 index 86d231f417c..00000000000 --- a/notebooks/rendered/unexecuted/storage-client-library.md +++ /dev/null @@ -1,160 +0,0 @@ - -# Google Cloud Storage - -This tutorial shows how to get started with the [Google Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by importing the library: - - -```python -from google.cloud import storage -``` - -Next, initialize a client object, which is used to interact with the Google Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. - -Run the following to create a client with your default project: - - -```python -client = storage.Client() -print("Client created using default project: {}".format(client.project)) -``` - -Alternatively, you can explicitly specify a project when constructing the client: - - -```python -# client = storage.Client(project='your-project-id') -``` - -Finally, create a bucket with a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' - -# Creates the new bucket -bucket = client.create_bucket(bucket_name) - -print('Bucket {} created.'.format(bucket.name)) -``` - -## List buckets in a project - - -```python -buckets = client.list_buckets() - -print("Buckets in {}:".format(client.project)) -for item in buckets: - print("\t" + item.name) -``` - -## Get bucket metadata - -The next cell shows how get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -bucket = client.get_bucket(bucket_name) - -print('Bucket name: {}'.format(bucket.name)) -print('Bucket location: {}'.format(bucket.location)) -print('Bucket storage class: {}'.format(bucket.storage_class)) -``` - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -blob_name = 'us-states.txt' -blob = bucket.blob(blob_name) - -source_file_name = 'resources/us-states.txt' -blob.upload_from_filename(source_file_name) - -print('File uploaded to {}.'.format(bucket.name)) -``` - -## List blobs in a bucket - - -```python -blobs = bucket.list_blobs() - -print("Blobs in {}:".format(bucket.name)) -for item in blobs: - print("\t" + item.name) -``` - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -blob = bucket.get_blob(blob_name) - -print('Name: {}'.format(blob.id)) -print('Size: {} bytes'.format(blob.size)) -print('Content type: {}'.format(blob.content_type)) -print('Public URL: {}'.format(blob.public_url)) -``` - -## Download a blob to a local directory - - -```python -output_file_name = 'resources/downloaded-us-states.txt' -blob.download_to_filename(output_file_name) - -print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) -``` - -## Cleaning up - -### Delete a blob - - -```python -blob = client.get_bucket(bucket_name).get_blob(blob_name) -blob.delete() - -print('Blob {} deleted.'.format(blob.name)) -``` - -### Delete a bucket - -Note that the bucket must be empty before it can be deleted. - - -```python -bucket = client.get_bucket(bucket_name) -bucket.delete() - -print('Bucket {} deleted.'.format(bucket.name)) -``` - -## Next Steps - -Read more about Google Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/storage-commands.md b/notebooks/rendered/unexecuted/storage-commands.md deleted file mode 100644 index 25c7119e2b5..00000000000 --- a/notebooks/rendered/unexecuted/storage-commands.md +++ /dev/null @@ -1,123 +0,0 @@ - -# Storage Commands - -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. - -## List available commands - -The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: - - -```python -!gsutil help -``` - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by defining a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' -``` - -NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. - -Next, create the new bucket with the `gsutil mb` command: - - -```python -!gsutil mb gs://{bucket_name}/ -``` - -## List buckets in a project - -Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. - - -```python -# Replace the string below with your project ID -project_id = 'your-project-id' -``` - - -```python -!gsutil ls -p $project_id -``` - -## Get bucket metadata - -The next cell shows how to get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -!gsutil ls -L -b gs://{bucket_name}/ -``` - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -!gsutil cp resources/us-states.txt gs://{bucket_name}/ -``` - -## List blobs in a bucket - - -```python -!gsutil ls -r gs://{bucket_name}/** -``` - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -!gsutil ls -L gs://{bucket_name}/us-states.txt -``` - -## Download a blob to a local directory - - -```python -!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt -``` - -## Cleaning up - -### Delete a blob - - -```python -!gsutil rm gs://{bucket_name}/us-states.txt -``` - -### Delete a bucket - -The following command deletes all objects in the bucket before deleting the bucket itself. - - -```python -!gsutil rm -r gs://{bucket_name}/ -``` - -## Next Steps - -Read more about Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/unexecuted/visualize-bigquery-public-data.md b/notebooks/rendered/unexecuted/visualize-bigquery-public-data.md deleted file mode 100644 index 542f0cf7a76..00000000000 --- a/notebooks/rendered/unexecuted/visualize-bigquery-public-data.md +++ /dev/null @@ -1,146 +0,0 @@ - -# Vizualizing BigQuery Data in a Jupyter Notebook - -[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. - -Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. - -## Using Jupyter Magics to Query BigQuery Data - -The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. - -The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. - - -```python -%%bigquery -SELECT - source_year AS year, - COUNT(is_male) AS birth_count -FROM `bigquery-public-data.samples.natality` -GROUP BY year -ORDER BY year DESC -LIMIT 15 -``` - -The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. - - -```python -%%bigquery total_births -SELECT - source_year AS year, - COUNT(is_male) AS birth_count -FROM `bigquery-public-data.samples.natality` -GROUP BY year -ORDER BY year DESC -LIMIT 15 -``` - -The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. - - -```python -total_births.plot(kind='bar', x='year', y='birth_count'); -``` - -Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. - - -```python -%%bigquery births_by_weekday -SELECT - wday, - SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, - SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births -FROM `bigquery-public-data.samples.natality` -WHERE wday IS NOT NULL -GROUP BY wday -ORDER BY wday ASC -``` - -Visualize the query results using a line chart. - - -```python -births_by_weekday.plot(x='wday'); -``` - -## Using Python to Query BigQuery Data - -Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. - -To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. - - -```python -from google.cloud import bigquery - -client = bigquery.Client() -``` - -Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). - - -```python -sql = """ -SELECT - plurality, - COUNT(1) AS count, - year -FROM - `bigquery-public-data.samples.natality` -WHERE - NOT IS_NAN(plurality) AND plurality > 1 -GROUP BY - plurality, year -ORDER BY - count DESC -""" -df = client.query(sql).to_dataframe() -df.head() -``` - -To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. - - -```python -pivot_table = df.pivot(index='year', columns='plurality', values='count') -pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); -``` - -Run the following query to retrieve the count of births by the number of gestation weeks. - - -```python -sql = """ -SELECT - gestation_weeks, - COUNT(1) AS count -FROM - `bigquery-public-data.samples.natality` -WHERE - NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 -GROUP BY - gestation_weeks -ORDER BY - gestation_weeks -""" -df = client.query(sql).to_dataframe() -``` - -Finally, chart the query results in your DataFrame. - - -```python -ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) -ax.set_title('Count of Births by Gestation Weeks') -ax.set_xlabel('Gestation Weeks') -ax.set_ylabel('Count'); -``` - -### What's Next - -+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. - -+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). diff --git a/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png b/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png new file mode 100644 index 0000000000000000000000000000000000000000..0bed3d1ad6539a9c5ed68b9b11a6492ed7bf684b GIT binary patch literal 17935 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 literal 0 HcmV?d00001 diff --git a/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png b/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png new file mode 100644 index 0000000000000000000000000000000000000000..b70b433e9adf852f6404b63ed2aa40467b9d1a50 GIT binary patch literal 7326 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 J)oHI^{sWfAD^36a literal 0 HcmV?d00001 diff --git a/notebooks/rendered/executed/visualize-bigquery-public-data.md b/notebooks/rendered/visualize-bigquery-public-data.md similarity index 100% rename from notebooks/rendered/executed/visualize-bigquery-public-data.md rename to notebooks/rendered/visualize-bigquery-public-data.md From 0287d5fdb739d1b643902e7209472867ef6efe01 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 10:31:30 -0800 Subject: [PATCH 16/24] update bqml tutorial to getting started for data scientists --- .../getting-started-with-bigquery-ml.md | 456 ++++++------------ .../Getting Started with BigQuery ML.ipynb | 350 ++++++++------ 2 files changed, 364 insertions(+), 442 deletions(-) diff --git a/notebooks/rendered/getting-started-with-bigquery-ml.md b/notebooks/rendered/getting-started-with-bigquery-ml.md index 2c890dbec6c..9acbc5caad2 100644 --- a/notebooks/rendered/getting-started-with-bigquery-ml.md +++ b/notebooks/rendered/getting-started-with-bigquery-ml.md @@ -1,29 +1,54 @@ -# Getting Started with BigQuery ML +# Getting started with BigQuery ML -BigQuery ML (BQML) enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratise machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement. +BigQuery ML enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratize machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement. -In this tutorial, you'll use the [sample Analytics 360 dataset](https://support.google.com/analytics/answer/3437719) to create a model that predicts whether a visitor will make a transaction. +In this tutorial, you use the sample [Google Analytics sample dataset for BigQuery](https://support.google.com/analytics/answer/7586738?hl=en&ref_topic=3416089) to create a model that predicts whether a website visitor will make a transaction. For information on the schema of the Analytics dataset, see [BigQuery export schema](https://support.google.com/analytics/answer/3437719) in the Google Analytics Help Center. -## Create a dataset + +## Objectives +In this tutorial, you use: + ++ BigQuery ML to create a binary logistic regression model using the `CREATE MODEL` statement ++ The `ML.EVALUATE` function to evaluate the ML model ++ The `ML.PREDICT` function to make predictions using the ML model + +## Create your dataset + +Enter the following code to import the BigQuery Python client library and initialize a client. The BigQuery client is used to send and receive messages from the BigQuery API. ```python from google.cloud import bigquery client = bigquery.Client(location="US") +``` + +Next, you create a BigQuery dataset to store your ML model. Run the following to create your dataset: + + +```python dataset = client.create_dataset("bqml_tutorial") ``` -## Create a Model +## Create your model + +Next, you create a logistic regression model using the Google Analytics sample +dataset for BigQuery. The model is used to predict whether a +website visitor will make a transaction. The standard SQL query uses a +`CREATE MODEL` statement to create and train the model. Standard SQL is the +default query syntax for the BigQuery python client library. + +The BigQuery python client library provides a cell magic, +`%%bigquery`, which runs a SQL query and returns the results as a Pandas +`DataFrame`. -### Logistic regression for Analytics 360 -Now, let's move on to our task. Here is how you would create a model to predict whether a visitor will make a transaction. +To run the `CREATE MODEL` query to create and train your model: ```python %%bigquery -CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` +CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` OPTIONS(model_type='logistic_reg') AS SELECT IF(totals.transactions IS NULL, 0, 1) AS label, @@ -34,37 +59,34 @@ SELECT FROM `bigquery-public-data.google_analytics_sample.ga_sessions_*` WHERE - _TABLE_SUFFIX BETWEEN '20160801' AND '20170631' -LIMIT 100000; + _TABLE_SUFFIX BETWEEN '20160801' AND '20170630' ``` +The query takes several minutes to complete. After the first iteration is +complete, your model (`sample_model`) appears in the navigation panel of the +BigQuery web UI. Because the query uses a `CREATE MODEL` statement to create a +table, you do not see query results. The output is an empty `DataFrame`. +## Get training statistics +To see the results of the model training, you can use the +[`ML.TRAINING_INFO`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train) +function, or you can view the statistics in the BigQuery web UI. This functionality +is not currently available in the BigQuery Classic web UI. +In this tutorial, you use the `ML.TRAINING_INFO` function. -
- - - - - - - - - -
-
- - +A machine learning algorithm builds a model by examining many examples and +attempting to find a model that minimizes loss. This process is called empirical +risk minimization. -Here, we use the visitor's device's operating system, whether said device is a mobile device, the visitor's country and the number of page views as the criteria for whether a transaction has been made. +Loss is the penalty for a bad prediction — a number indicating +how bad the model's prediction was on a single example. If the model's +prediction is perfect, the loss is zero; otherwise, the loss is greater. The +goal of training a model is to find a set of weights that have low +loss, on average, across all examples. -In this case, "bqml_tutorial" is the name of the dataset and "sample_model" is the name of our model. The model type specified is binary logistic regression. In this case, `label` is what we're trying to fit to. Note that if you're only interested in 1 column, this is an alternative way to setting `input_label_cols`. We're also limiting our training data to those collected from 1 August 2016 to 31 June 2017. We're doing this to save the last month of data for "prediction". Furthermore, we're limiting to 100,000 data points to save us some time. Feel free to remove the last line if you're not in a rush. - -Running the CREATE MODEL command creates a Query Job that will run asynchronously so you can, for example, close or refresh the browser. - -When the job is complete, you will see an empty DataFrame returned below the cell (it may be rendered as a small box or line, depending upon your settings). This is expected because there are no query results returned from creating a model. - -## Evaluate the Model +To see the model training statistics that were generated when you ran the +`CREATE MODEL` query: ```python @@ -72,83 +94,77 @@ When the job is complete, you will see an empty DataFrame returned below the cel SELECT * FROM - ml.EVALUATE(MODEL `bqml_tutorial.sample_model`, ( -SELECT - IF(totals.transactions IS NULL, 0, 1) AS label, - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(geoNetwork.country, "") AS country, - IFNULL(totals.pageviews, 0) AS pageviews -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')); + ML.TRAINING_INFO(MODEL `bqml_tutorial.sample_model`) ``` +Note: Typically, it is not a best practice to use a `SELECT *` query. Because the model output is a small table, this query does not process a large amount of data. As a result, the cost is minimal. + +When the query is complete, the results appear below the query. The results should look like the following: +![image.png](attachment:image.png) +The `loss` column represents the loss metric calculated after the given iteration +on the training dataset. Since you performed a logistic regression, this column +is the [log loss](https://en.wikipedia.org/wiki/Cross_entropy#Cross-entropy_error_function_and_logistic_regression). +The `eval_loss` column is the same loss metric calculated on +the holdout dataset (data that is held back from training to validate the model). +For more details on the `ML.TRAINING_INFO` function, see the +[BigQuery ML syntax reference](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train). -
+## Evaluate your model - - - - - - - - - - - - - - - - - - - - - - - -
precisionrecallaccuracyf1_scorelog_lossroc_auc
00.4618320.1126630.9852890.1811380.0460620.98184
-
+After creating your model, you evaluate the performance of the classifier using +the [`ML.EVALUATE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-evaluate) +function. You can also use the [`ML.ROC_CURVE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-roc) +function for logistic regression specific metrics. +A classifier is one of a set of enumerated target values for a label. For +example, in this tutorial you are using a binary classification model that +detects transactions. The two classes are the values in the `label` column: +`0` (no transactions) and not `1` (transaction made). +To run the `ML.EVALUATE` query that evaluates the model: -If used with a linear regression model, the above query returns the following columns: `mean_absolute_error`, `mean_squared_error`, `mean_squared_log_error`, `median_absolute_error`, `r2_score`, `explained_variance`. If used with a logistic regression model, the above query returns the following columns: `precision`, `recall`, `accuracy`, `f1_score`, `log_loss`, `roc_auc`. Please consult the machine learning glossary or run a Google search to understand how each of these metrics are calculated and what they mean. -Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this: +```python +%%bigquery +SELECT + * +FROM ML.EVALUATE(MODEL `bqml_tutorial.sample_model`, ( + SELECT + IF(totals.transactions IS NULL, 0, 1) AS label, + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(geoNetwork.country, "") AS country, + IFNULL(totals.pageviews, 0) AS pageviews + FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` + WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) +``` + +When the query is complete, the results appear below the query. The +results should look like the following: +![image.png](attachment:image.png) + +Because you performed a logistic regression, the results include the following +columns: ++ [`precision`](https://developers.google.com/machine-learning/glossary/#precision) ++ [`recall`](https://developers.google.com/machine-learning/glossary/#recall) ++ [`accuracy`](https://developers.google.com/machine-learning/glossary/#accuracy) ++ [`f1_score`](https://en.wikipedia.org/wiki/F1_score) ++ [`log_loss`](https://developers.google.com/machine-learning/glossary/#Log_Loss) ++ [`roc_auc`](https://developers.google.com/machine-learning/glossary/#AUC) - - - - - - - - - - - - - - - - - - - -
precisionrecallaccuracyf1_scorelog_lossroc_auc
10.4378380.0754190.9852490.1286740.0476820.982956
-## Use the Model +## Use your model to predict outcomes -### Predict purchases per country +Now that you have evaluated your model, the next step is to use it to predict +outcomes. You use your model to predict the number of transactions made by +website visitors from each country. And you use it to predict purchases per user. -Here we try to predict the number of transactions made by visitors of each country, sort the results and select the top 10 countries by purchases. +To run the query that uses the model to predict the number of transactions: ```python @@ -156,111 +172,33 @@ Here we try to predict the number of transactions made by visitors of each count SELECT country, SUM(predicted_label) as total_predicted_purchases -FROM - ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( -SELECT - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(totals.pageviews, 0) AS pageviews, - IFNULL(geoNetwork.country, "") AS country -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) -GROUP BY country -ORDER BY total_predicted_purchases DESC -LIMIT 10; +FROM ML.PREDICT(MODEL `bqml_tutorial.sample_model`, ( + SELECT + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(totals.pageviews, 0) AS pageviews, + IFNULL(geoNetwork.country, "") AS country + FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` + WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) + GROUP BY country + ORDER BY total_predicted_purchases DESC + LIMIT 10 ``` +When the query is complete, the results appear below the query. The +results should look like the following. Because model training is not +deterministic, your results may differ. +![image.png](attachment:image.png) +In the next example, you try to predict the number of transactions each website +visitor will make. This query is identical to the previous query except for the +`GROUP BY` clause. Here the `GROUP BY` clause — `GROUP BY fullVisitorId` +— is used to group the results by visitor ID. -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
countrytotal_predicted_purchases
0United States228
1Canada7
2Taiwan6
3India3
4Turkey2
5Japan2
6United Kingdom1
7Vietnam1
8El Salvador1
9Serbia1
-
- - - -Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this: - - - - - - - - - - - - - -
countrytotal_predicted_purchases
0UnitedStates467
1Canada8
2Taiwan6
3India5
4UnitedKingdom3
5Turkey3
6Japan2
7Germany2
8HongKong2
9Singapore2
- -### Predict purchases per user - -Here is another example. This time we try to predict the number of transactions each visitor makes, sort the results and select the top 10 visitors by transactions. +To run the query that predicts purchases per user: ```python @@ -268,117 +206,25 @@ Here is another example. This time we try to predict the number of transactions SELECT fullVisitorId, SUM(predicted_label) as total_predicted_purchases -FROM - ml.PREDICT(MODEL `bqml_tutorial.sample_model`, ( -SELECT - IFNULL(device.operatingSystem, "") AS os, - device.isMobile AS is_mobile, - IFNULL(totals.pageviews, 0) AS pageviews, - IFNULL(geoNetwork.country, "") AS country, - fullVisitorId -FROM - `bigquery-public-data.google_analytics_sample.ga_sessions_*` -WHERE - _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) -GROUP BY fullVisitorId -ORDER BY total_predicted_purchases DESC -LIMIT 10; +FROM ML.PREDICT(MODEL `bqml_tutorial.sample_model`, ( + SELECT + IFNULL(device.operatingSystem, "") AS os, + device.isMobile AS is_mobile, + IFNULL(totals.pageviews, 0) AS pageviews, + IFNULL(geoNetwork.country, "") AS country, + fullVisitorId + FROM + `bigquery-public-data.google_analytics_sample.ga_sessions_*` + WHERE + _TABLE_SUFFIX BETWEEN '20170701' AND '20170801')) + GROUP BY fullVisitorId + ORDER BY total_predicted_purchases DESC + LIMIT 10 ``` - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
fullVisitorIdtotal_predicted_purchases
094178574712951310454
129694186761262587982
212809936612043474502
303763940560921891132
48069922490326866502
517120667030994876522
60576935009275810772
783889310329550527462
880646251500335083962
91122883309288959422
-
- - - -You should see a table similar to this: - - - - - - - - - - - - - -
countrytotal_predicted_purchases
094178574712951310453
183889310329550527462
274203005015230124602
38069922490326866502
403763940560921891132
529694186761262587982
64890384027656840032
70576935009275810772
81122883309288959422
912809936612043474502
- -## Congratulations! - -You completed the tutorial. Looking for a challenge? Try making a linear regression model with BQML. - -What we've covered: -+ Create a binary logistic regression model -+ Evaluate the model -+ Use model to make predictions +When the query is complete, the results appear below the query. The +results should look like the following: +![image.png](attachment:image.png) ## Cleaning up @@ -388,7 +234,3 @@ To delete the resources created by this tutorial, execute the following code to ```python client.delete_dataset(dataset, delete_contents=True) ``` - -## Next Steps - -For more information about BQML, please refer to the [documentation](https://cloud.google.com/bigquery/docs/bigqueryml-intro). diff --git a/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb b/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb index ab543925bea..7d535e942f0 100644 --- a/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb +++ b/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb @@ -4,18 +4,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Getting Started with BigQuery ML\n", + "# Getting started with BigQuery ML\n", "\n", - "BigQuery ML (BQML) enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratise machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement.\n", + "BigQuery ML enables users to create and execute machine learning models in BigQuery using SQL queries. The goal is to democratize machine learning by enabling SQL practitioners to build models using their existing tools and to increase development speed by eliminating the need for data movement.\n", "\n", - "In this tutorial, you'll use the [sample Analytics 360 dataset](https://support.google.com/analytics/answer/3437719) to create a model that predicts whether a visitor will make a transaction." + "In this tutorial, you use the sample [Google Analytics sample dataset for BigQuery](https://support.google.com/analytics/answer/7586738?hl=en&ref_topic=3416089) to create a model that predicts whether a website visitor will make a transaction. For information on the schema of the Analytics dataset, see [BigQuery export schema](https://support.google.com/analytics/answer/3437719) in the Google Analytics Help Center.\n", + "\n", + "\n", + "## Objectives\n", + "In this tutorial, you use:\n", + "\n", + "+ BigQuery ML to create a binary logistic regression model using the `CREATE MODEL` statement\n", + "+ The `ML.EVALUATE` function to evaluate the ML model\n", + "+ The `ML.PREDICT` function to make predictions using the ML model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Create a dataset" + "## Create your dataset\n", + "\n", + "Enter the following code to import the BigQuery Python client library and initialize a client. The BigQuery client is used to send and receive messages from the BigQuery API." ] }, { @@ -26,7 +36,22 @@ "source": [ "from google.cloud import bigquery\n", "\n", - "client = bigquery.Client(location=\"US\")\n", + "client = bigquery.Client(location=\"US\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, you create a BigQuery dataset to store your ML model. Run the following to create your dataset:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "dataset = client.create_dataset(\"bqml_tutorial\")" ] }, @@ -34,10 +59,19 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Create a Model\n", + "## Create your model\n", "\n", - "### Logistic regression for Analytics 360\n", - "Now, let's move on to our task. Here is how you would create a model to predict whether a visitor will make a transaction." + "Next, you create a logistic regression model using the Google Analytics sample\n", + "dataset for BigQuery. The model is used to predict whether a\n", + "website visitor will make a transaction. The standard SQL query uses a\n", + "`CREATE MODEL` statement to create and train the model. Standard SQL is the\n", + "default query syntax for the BigQuery python client library.\n", + "\n", + "The BigQuery python client library provides a cell magic,\n", + "`%%bigquery`, which runs a SQL query and returns the results as a Pandas\n", + "`DataFrame`.\n", + "\n", + "To run the `CREATE MODEL` query to create and train your model:" ] }, { @@ -47,7 +81,7 @@ "outputs": [], "source": [ "%%bigquery\n", - "CREATE OR REPLACE MODEL `bqml_tutorial.sample_model` \n", + "CREATE OR REPLACE MODEL `bqml_tutorial.sample_model`\n", "OPTIONS(model_type='logistic_reg') AS\n", "SELECT\n", " IF(totals.transactions IS NULL, 0, 1) AS label,\n", @@ -58,28 +92,43 @@ "FROM\n", " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", "WHERE\n", - " _TABLE_SUFFIX BETWEEN '20160801' AND '20170631'\n", - "LIMIT 100000;" + " _TABLE_SUFFIX BETWEEN '20160801' AND '20170630'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Here, we use the visitor's device's operating system, whether said device is a mobile device, the visitor's country and the number of page views as the criteria for whether a transaction has been made.\n", - "\n", - "In this case, \"bqml_tutorial\" is the name of the dataset and \"sample_model\" is the name of our model. The model type specified is binary logistic regression. In this case, `label` is what we're trying to fit to. Note that if you're only interested in 1 column, this is an alternative way to setting `input_label_cols`. We're also limiting our training data to those collected from 1 August 2016 to 31 June 2017. We're doing this to save the last month of data for \"prediction\". Furthermore, we're limiting to 100,000 data points to save us some time. Feel free to remove the last line if you're not in a rush.\n", - "\n", - "Running the CREATE MODEL command creates a Query Job that will run asynchronously so you can, for example, close or refresh the browser.\n", - "\n", - "When the job is complete, you will see an empty DataFrame returned below the cell (it may be rendered as a small box or line, depending upon your settings). This is expected because there are no query results returned from creating a model." + "The query takes several minutes to complete. After the first iteration is\n", + "complete, your model (`sample_model`) appears in the navigation panel of the\n", + "BigQuery web UI. Because the query uses a `CREATE MODEL` statement to create a\n", + "table, you do not see query results. The output is an empty `DataFrame`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Evaluate the Model" + "## Get training statistics\n", + "\n", + "To see the results of the model training, you can use the\n", + "[`ML.TRAINING_INFO`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train)\n", + "function, or you can view the statistics in the BigQuery web UI. This functionality\n", + "is not currently available in the BigQuery Classic web UI.\n", + "In this tutorial, you use the `ML.TRAINING_INFO` function.\n", + "\n", + "A machine learning algorithm builds a model by examining many examples and\n", + "attempting to find a model that minimizes loss. This process is called empirical\n", + "risk minimization.\n", + "\n", + "Loss is the penalty for a bad prediction — a number indicating\n", + "how bad the model's prediction was on a single example. If the model's\n", + "prediction is perfect, the loss is zero; otherwise, the loss is greater. The\n", + "goal of training a model is to find a set of weights that have low\n", + "loss, on average, across all examples.\n", + "\n", + "To see the model training statistics that were generated when you ran the\n", + "`CREATE MODEL` query:" ] }, { @@ -92,59 +141,60 @@ "SELECT\n", " *\n", "FROM\n", - " ml.EVALUATE(MODEL `bqml_tutorial.sample_model`, (\n", - "SELECT\n", - " IF(totals.transactions IS NULL, 0, 1) AS label,\n", - " IFNULL(device.operatingSystem, \"\") AS os,\n", - " device.isMobile AS is_mobile,\n", - " IFNULL(geoNetwork.country, \"\") AS country,\n", - " IFNULL(totals.pageviews, 0) AS pageviews\n", - "FROM\n", - " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", - "WHERE\n", - " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'));" + " ML.TRAINING_INFO(MODEL `bqml_tutorial.sample_model`)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "If used with a linear regression model, the above query returns the following columns: `mean_absolute_error`, `mean_squared_error`, `mean_squared_log_error`, `median_absolute_error`, `r2_score`, `explained_variance`. If used with a logistic regression model, the above query returns the following columns: `precision`, `recall`, `accuracy`, `f1_score`, `log_loss`, `roc_auc`. Please consult the machine learning glossary or run a Google search to understand how each of these metrics are calculated and what they mean.\n", - "\n", - "Concretely, you'll recognize the `SELECT` and `FROM` portions of the query are identical to that used during training. The `WHERE` portion reflects the change in time frame and the `FROM` portion shows that we're calling `ml.EVALUATE`. You should see a table similar to this:\n", - "\n", + "Note: Typically, it is not a best practice to use a `SELECT *` query. Because the model output is a small table, this query does not process a large amount of data. As a result, the cost is minimal." + ] + }, + { + "attachments": { + "image.png": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAncAAAFqCAYAAAB4any6AAAgAElEQVR4Aey9PXTiSNb//+3/2XOkPr8ATQQToY3QRmgi2AieyGxkNoInMhuZJ4KNzGZkZiOzkdnITGQmgo3MRmgiMxFMBBOZiUxHVkdWR/d/SkIgYcC8mG5sX3x80Eu93PrcW1VXVaXiAxER+MMEmAATYAJMgAkwASbwJgj8f2+iFFwIJsAEmAATYAJMgAkwAZsAO3dsCEyACTABJsAEmAATeEME2Ll7Q8rkojABJsAEmAATYAJMgJ07tgEmwASYABNgAkyACbwhAuzcvSFlclGYABNgAkyACTABJsDOHdsAE2ACTIAJMAEmwATeEAF27t6QMrkoTIAJMAEmwASYABNg545tgAkwASbABJgAE2ACb4jAH3Ypy4cPH3aJznGZABNgAkyACTABJsAEFhDY5TcmdnLuhCy7ZL6gLCsvCWfya+a3Uhi++SwB1teziFYGYH4r8Sy9ydyWolnrBvNbC9PBBWK9HZxKdhJI6HOXD0/L7kKP4zIBJsAEmAATYAJM4MAIsHN3YAphcZgAE2ACTIAJMAEmsAsBdu52ocdxmQATYAJMgAkwASZwYATYuTswhbA4TIAJMAEmwASYABPYhQA7d7vQ47hMgAkwASbABJgAEzgwAuzcHZhCWBwmwASYABNgAkyACexCgJ27XehxXCbABJgAE2ACTIAJHBgBdu7WUkgflXgIsqKjaFhrxZgFMmEUdShyCMlKf3b5XR+9RiavUeavbWQtZOUP+PBBRqpufu3MDzK/YUWH2K/qg1pE91kJXyk/Iw9VlFGOozp8tpBfOcAubfdXFnWP2W1mh3sUZGXS3MauxLPhzbfj3I3rSCkfoOTaGyJYI7g5RHf4CV8+DzEcbtppmRj2h/j85RP6/RE2dQ3XkO4VBlnCZJ863IBSt6gt6KiWyLxBuhyUCTCBfREYoRqXnzrRO7Xd+5KV011M4C20sUvscHGB93p151+o2Kt0GyQ+bjdgfAbkDeKsHVTJot4NwRgpiKdCa0dzAqrIN7pQuybUZHI/8m0o0bcPvpjJXnW4dqG7aLR+AxCbi7FY5rlAfMoEmMC3IDBsoNH/Asw3zzu13d+iIO85zzfQxi6zw2+hVtrh4/z62A4JbBh1cX4P1LvMUDQAEven/1KCLu9FBk3KSCCET6nzeEfNwhFFAhIFT27s3B/vbuji9JhikTAFJYmkQJCiR6d0efvgkW6SBiQ6uppc75xSGCDp6Ipum2d0HA1TQMQPRuno7IbuprHv6TIh2XIFJnkSudciVLi5pcuTBEWCEklSgMKJE7rsefN+oN7VKR1FgxQQ5fCWERIdXz9Oc3p64OYTpfOBk04iHCApUqBbIrotRJz0oufUm0bu0VnEySd65l5101lH3mlCdtqzM++Rmx7IYfKcDkXce+qcn1AiEiRJkigQjNDR6SV51TQ4jxIgUeLynh5uLygTE2FjdGErQ5T/jDKJKEWCASeNcIyOz5p05yK8v6FCIkiSjzEoeNqx83+qRyHXI901zygTi0zsJzyxH9v4JoV2y/tS/LwsD+l4QT0R4j3c0uXpEUWF7UkBCkZilDlr0sDlLsI8Dui6cDwJI/QrOJ7Q+c2kJj1334NhcTvhBnikga2vSX0NhCl6XKDrniPMYzNDQaF/SdQZN45Q/xUd2fXPsS+iNeyJiBybFO2PU+c8KS44fCX8rk4pEXF0GUmc0tVVgSI2sxhduMxuTihgX3PbYae4ndOg3S5IiUtyaohbNxa3UcIumucndBSLUDgwaSOjR1S46pFrPg+dczoOO23srH2UKNMUIZYwFe3JhdOeiHZbtCeJkwtyzc2RdhI3eELXt9d0ehShoJAhEKZY5pw63iq+QJvzadwMmnR2FHXaCZHf6RUNHkW7lqHYpG6EYxm68DZqL2T3y+zwoXdFhaPojG0sQ2fNuynbzex8Sdv7BvrK3e1QWMPqtmfehFa3Y/Ohn56L32rd+rNr5ptmvDi/AV0eC+OcOD6isY5GKRo7oabtI7mVO0JHR+GpcxQuCPeGiO4uKCGBJNGZREXHP2kkAkd0NfXQ3DSeOnfCmZAg2R1WNBKYpC9RwvEoljgFboMG28mAFKZoLEph13kLn9LNpOW6vz52OptAlDJn51Q4ikycjyDFTs6oOZVxEU03H4miRwknHeGQxs5JtMGbO3fPy+uVYrG+RAhXLte5e06H99Q8CTvllsIUSyQoOtGTKMukX552pIHYEcVce5COyPHHH+jmNEwQDnQkSlHhjE+cuEihYzdmjzcFignn0b4udCrCRenoXDi58zI7Jb27mujH7siELUzsUIrQ6Y3rpM/iCsd0lb7X4+cNdUjHC+rJY4cK0VnHa5d/wiiQuLTtUDR6t4VJ3ZSCFJnWQ1HfRA/63H0/g+V2RzTTV4AisYT9sCDCI3BEl6IuPXboNCh0KFHU4909XB07uhXtgt2pP29PQqplnapfYvfs8Pk93JzYD7U2M7vtE+wCE0duF+ducRtFjz06E/YTcOwiOq2fQco4DTzdnjsPx7ZME/uJRmNU6Cxz7jztyXy9DWfoeuq0zfQh2X1EhGKediNwfD1xUF39Lfp20whQMChRIBz1tDGgYDhMkpA5Jpy+SdsRPpm0/y9n94vs8LF3QYlJOxmMJCgRi0zaxDBlmi6Ezex8Yds7ce5ec1+5ux2u0fbMmc+qdmwu6MLTN+DciXI90NXR/OiYW163comKE6ZE4ZKanQ7dTodriB4fRCPwSA8PD3R/d0XHtsG7HYtIx01jkXMHipzekNOND+gi5sghRvSc6jHr2J+O3ImGMeF0KqIUNycTByxMju85K1f41HFA6LFJGVu+INkDSm4xF37P8hYVK3J8Rlc3Her07m1nZhvnbrW8fiGWG+dMrhmTWVln1ybp9c4oajsEUSrcTrzehxs6CQudBiZP6J6OFKBANEPn1zfU6fRmDfDjAwlVP4rvh3u6PYs6HbZ3VOW24HReYsTPHYWwxVggs3AEbBlA4cyVMwL42KOLhOPkS1HHifY6hi/Dz8/5cM6e1pO7y4TDWIrR2WRE4r554oz0wO2gZ2xn9eaR7nu3k1HV5+77CSy1u6m+xMOXq9x7ujp29OU88D1SZ+JozvT3QNeTMKJDd112WsOeFnWqfmm9ZwfOz/OAg/AJ2f2/mA05mcwAeOvMxiN3jkM930YJOo8PD/Qo/h4e6OF+QBfuTEimOR1hGpzHntZlG+1TpjRtTwKUuHBGAB9Fu2879aBwQYzUi48bFyRFzyYPkcLhmpQ3kCF7cHASevGXJ43pg+jdtJ8AInTacSzq4fp44lxFyJk0eSG7X/iQ8UDXGcfuA8duX0U0uHA4ugMAdpk2sfNFbe/UuXu9faXgsJMdrtX2+C1oaTvmD7b07O28ULHGnHb4tI52NY90Mom46qzOM7s15NMalA8f8d133+H7P/4N//nsJGaa67z+EEYql4JiR9GgxyeLPkwT67x6IcVzSKtOfoqehC6JYxNjO7IFayKCrCjOej1ZgWyLbmE9+Zy0ES2i0aogl0oiqYe2Xvu3Wt5JXi/8Nep2Yb+EJ1kY1vLI5XLIFesY2flYGA2do2m2UgKVVgOlbArJpO4sw7FGaJVzSKoyPn78Dt999z3+/M9f8UVEWlNX0/Tdg2Ebxu/iJIxUPgfbpGQd+XwSQo1fxP2xG9j5/hb8/BJ8zTML3XbXZizKXYw7tSSULiIdFXJ8gtEWb5CHoMedSvDlv3no8SxK9T6gxR2mz95fs0zDNrq2vmSYRsWxo1wJ7bHTFoyHQ4whI5nLImLrr4WWMDyzjYZY0IsgUrm0U9f3YU9PinFg/NBHV6xrAxDNl5AWTZ2sIl1M27yeiL/phUVt1NhANZ+CJn/Ex+++w3ff/wl//9mRwTLNrV5Qm7YngRSKed1uC2U1h2I6aEv8u9GGf18DCVo2B902Exl6UrfrNywTa3URdqoS9HR6koYKXZ/0E+EUckmnXih6HNqk/Tft9v+5erEpYG/4PgzbpgF53EZJtKm5HCqGZfP4MuxjKPqeTe18Uds7zfYV95W72uFabc8U1IscvCPnToIWdyrylJzZQD79f/jx59+B6Akurm9wc3OBY6eOT4OtPJBCCDl10w7mdBPicB3HEBBO26SaL3gbJIR4XLMbkt9aNbT6Q3TrNRifAATiSMVnua2UUQTXktCfC7TG/dXyrpHAFkHMkek4YV9+w39//BE/2v8/QagN+AJrvoUN6dAnDrObXb+aRvaf/8GvZghHZ1do3tzguhB1Gmk30KbfU6dQgTpVIiCHQo4D8MUUfqPv8y34+QT4qiee8rtM7PxDUBW7F4M56aDj5RauTxMISl/w6Zef8M+//RmqnkXd7mGA5+6vVSzThONrf8av/3Ht6Ef89IuoUKLKTuqsnkNOOJ9f+mi1hjAnL2shnEY+5dS5vdjTk0IcGL+pMyMhFPIYfEhFyFHnkxLMX7BcxvM3FrZRI9SyKfzjp1/wu5JA4bKJm5sbnCXWzGxBHuLStD1RFCieJlRxK/G0Xs8S8JZXPFx7os0CPXOkeJg5D+gAlElbIeJOL84SehG7nyU3O7LcAQTY9c1pU3/Ej//5FfbYxkRPG9v5grZ3mumr7StfwA7XbXumsHY/eEfO3QJY3bbjKCGCfL2OYjaFVGoy0rMg+LJL21T0aVoLKvT0HgC93ED1KAj89m/89Yc/4c9/+wm/B6I4rdWQ87Sv3jgLj1cJaY1nrqg1wmhutMmX3jPy+sK+0ImiKo4TFjzBzSOJpQS+/37lObd1BKM1dEaQUhU0KjmkUynENY9Xvo2sonOw45k+ZtZ47IzaSgqU+Sy+Ab9tivYycTzld5nYCY8xMp3RF2U6Iq0hWzMwGt3iqnCEsAR8+e0nFEsth6X8zP11BJ7qK4KzW78NCZuyjPzkQUtDNheDhC/ot1uotwy7wwunc3Cep/ZkT0/KcGD85JkzZI49jYRwhhx1PimBeMid+XNjjMcrHnrn2yizi3ZXJCwhVqqjmk8jlUpCn69TC3JddWnangi5PeKYbsOnqJN6vSqVl7n3rJv6Ena/SFShS5ujhNjFna89tdtXq4W0/PJ2Pq/iRaItvfZM27m3vvIl7HDttmdp6Te+8WacO1fv1mjkTNdNnzJXMJlammiAnFo+btXRnjzIr4j59W4NW6h3PyFwdGaPNnVuB7gf91HLzg1NbSGREpo4TaMujL4ov5j2rKE9mZbeIsmdoizToRqPQxMpf2qjWh/OHFGYGBrGZHp2ddZu2qKnsTVt9dGoO1OGvpiy7DyVfxljOHJsYun0t5ZCMixi/45WtQ47uNVHrWY4jqS4v4kD7hPkLZzISKYnU9TdGqqGM4w5btfQ+lWUL4hkSjjmFobdrs1PDsWRq7ZRz9tgYY1HEI8eq++vyWqqr9/QqDZ8djPut9H1+CuqcOSEg9mvo94VFSKCbC4+HbFZ257WFG1xsAPjBx1xe93IF/TrVbRtXiaMWsNZNuEthNuZfRmi3XaWTZjdKmrGUi/QG9s5nrbPnlHVUQP1BWlM9WGOMJosafE6bt7E1WTKmf783Ea11rfbA2tUR7XlNPxht73xRvomxy9k9wtl15GKB+yZj36t4ls+Yo1Ff+DU1SnX59rNhXl85Yv76itfwg43aHteitobce4U6JPpyy8//x80sS5NSaLy3G7pegq2feN3/CulQ9c1aNk2EHz2eeql+D+bjmWO7afLz//9J7LZLNKpODRVhZbMojq/oOvZ1PwBtFTSaeS+/IJ//CCe5BT86e9dyN+k/Ct0qJdQOY1Awif89/90hFRHV6oSwp9SVXQdH8xfON+ZOp3ettd06XHoahzlUQhPZuDVOHTR5uF3/PsvYqRCRijX8jiUnoTlJMqVDIQb8uk/f8MfFRmy8gP+/vNnQIogV8k7Tqknyns7DGXLKMaEl/Qr/vk/30GWZXz/l39D7CQYSJRRTovhAxNGKYk/KgpUPW7rKluz59yhxpPQnr2/JlU5iVLl2NbX7z/9L7SQBl3XoYUUfP9DDjVve6GmkUtKwOff8KsQJZpDbjpAvIE9rSnasmAHxQ8hZItpu858+e3f+Isq27+8k2qIlYpzHz2NlO2ff8Z//++PkBUZoT//EyPlSY2bi+g5lcXSE9EWf8Ev5aS9rEbV8+gvSEPVJzMun/+D/w0JuRSk63Nrcd2ktTwqOdGefMbPf//BruOKWGstfLvgMSrlQ9mP9Ll64RZom28F2UoZiYAYIf83/kcNQdPFcpYQlO//jHxDsPt6dr5NCebj7K2vfAk73KTtmS/YludvxLkDtHwNlUzU9svEs2FI058fvleyqDXOcBQJQPo8wsgKIVs3YFRTsPv3LaG+XDQLI1OGOlnQ8uXzZ3wW/59+x28//4S/p/NozK3p2ihvvYxG/RSJSBCSaENDcZxettEux3dbi7aRELPAy3WoIFUzYFye4igaAsa/4tfhCFZIx3EuO1mkPEtn0ZFerqN2EnPWdIkXMOJltPsN5MTKee9HSaNSLyAhbEKs51NEA7d8lDSUrcO4OcdJIoKg3cMFEUmc4KJtoJbacf7IK9drPZbjqLS7uCocIxp2alUgHMPx2TW6bdf5VezF5glVhjn8Bb/0R4AaQ+asiXYlLhYmPXN/fThqtgWjc4GTRBSKNcKvv4qXKEJIZHLwD4aHkM657YCEWC7rc9TXtqf1RVsc8sD4Kek62pcniIVF/ZARSubRMFrIz9cjOYlK6xInsTAConGRVSQL1zBaOdjv0iwu7dxV1V4uc5oII4BPGI0saLkGuu0SxPOC75Mso352hIh4MLU7AOGoLKt/TnvSttuTsOOYBiNIZM5x020gezCj7S9n9z5W7olWRLvbxFkmgYhiYfTrrxiaMrREBvmU0+Z9NTt3Zdr6e5995cvY4fptz9YQfBE/iPdofVc2OBG/mbhD9A1ycoJ+7fw2FvCFI1jdIvQ//wu/RU7QbNWQ1pznY3NYQy7+f/jP5zAKt+LnTl444xdK7r3p64WwTZNhflMUGx0wt41wPQnM/J4geRUX3rPeXntfucjAdtXnmxm5WwTntV8z+317XVBAzNdPHDtRJkWRnWlCScX/+1G3p7rEdJfvX0mitmRW4rVzYfmZwKskYDWQFVP383VVlqHmjVdZJBZ6hFpSbE+1QK96ZW5LFaa1LwLcVz4lyyN3T5kczpV+BXr8H/j1SwCRoxSSqgJrPETX+Bm/fZYQKbTRLWtL9ruTEVK338/uJSDs+uTxEjK85jSY33baO1xuFsYj8XrIgo8itod5snJtQcD9Xzpcfvsv+zY52C/9LFKqLLZIWjY1vE1Oq+O8a7298r5ykWZ31Sc7d4uoHtC1cbuCYqUOoz/CJ7FOPygWviaRyhVRyupf7ZX9bZDsapzb5PmW4jC/7bTJ3Lbj5sZifi6J1/X93vX2mvvKRZa2qz7ZuVtEla+9CIFdjfNFhHjFiTC/7ZTH3Lbj5sZifi6J1/XNentd+npO2l31yWvuniPM95kAE2ACTIAJMAEm8IoIsHP3ipTFojIBJsAEmAATYAJM4DkC7Nw9R4jvMwEmwASYABNgAkzgFRHYec3dKyori8oEmAATYAJMgAkwgVdBYJd9hP+wawl3yXzTvHddYLhpfhx+NwKsL+a3G4HtYrPdbcfNjcX8XBKv65v19rr09Zy0Qp+7fHhadhd6HJcJMAEmwASYABNgAgdGgJ27A1MIi8MEmAATYAJMgAkwgV0IsHO3Cz2OywSYABNgAkyACTCBAyPAzt2BKYTFYQJMgAkwASbABJjALgTYuduFHsdlAkyACTABJsAEmMCBEWDn7sAUwuIwASbABJgAE2ACTGAXAuzc7UKP4zIBJsAEmAATYAJM4MAI7M+5G7VRSsehKjJkJQQ9VURjaO2v+GYXtVxykp+KeLYCY7y/7DjlHQmwvnYDuAW/fkmD2DvJ/6+jMvSIMjZQzaegqwpkWUZISyJf78P0BHEPzW4VKVVGKG+4l2bfZgNpeT6vD5CzLTitwBi1pDwniye8XkF/lhqAEVp5HYqcRG2Xev3quQGwhmhVckjpKhTZbV/zqPe9WjLRb5SQjWsI2WFUxNMVtEc+qLudjOpIKR+g5NqedNbLdy1btFO1MKxnockysq3n+g8LRlGDLMdR9dq0R7p3e7iF3Y+7dRTdPlxWoCazqHKn+mpMaOdNjBeW1DSQT6Xx79++TG5/wq///Rf+NzWG3G0gHVoYa4eLI9SzKZTMLKqtKnR5hHa5iHQaMLol6DukzFH3QYD1tRvV7fiZYxPB40s0SjrkqQAyVNU9GaKSzqKuFlGqlaGrMkyjgnw+hZzcRyvrVlzR4eaQLvaBEDxpuekAME2YiKFwU0VW8VxXtEn4ENI1A7rXH7GDmWiVsqiHNEzFGhuoZLOojpXFeXmSX334FrgBo3oRpbaKfKmGsqZCsUZoV/LIi/a134JQk9nKI10aI1WsoFHTELL6qJdEm2jC6FYQnxnAamRL745Qy5cxVAK+EOvm+7wtimRHaBWzyLdMKGvIaxkl5FuWMEn++AhsYffjOnLpMpAtodqKQ1NMdGtFFNNZoGugqPky4JNDJEA7fAAsjH1/mSAJIAQSdNF7pMf7a8qEQSJ89Ly3MM46F5flR7cFikgxuhh4UnloUiYYpEzzwXORD78mAdbXbrRflt8jXR8HKHq2uv49PjzQo0/sR7o5CZJ0dEX3k+uPNycUDiborHNPzUyAwqcdXwz7pHdG0cAxNf2JPQ03f+XukhKBCBVu3YgDuogFKJK5okHvnGJSgi5dQebjTs7fJbeHKzqSApSZAn+kh/mm7+6CYlKYCrdLwD3HzxPt7vKIgrFzujwNU+DkxnNnnXzXscVHuj2LUCB6Ss27DhXCkqdsnuzcw4cOnUbClLk8p8R8X+CGeePfL2v3RA8Pbh10wd1SISJR7Nzb0br3+PulCSzV55oZ7WFa1oTR7kKM2UnJPHK6DDmURTEdtn3bYcvAS4+YD40uRloaKe/ThJJEOm7BaPkndw7RwX5vMrG+dtP4dvxMMZgGRfUOoz2VQ1bmR8dkKIoCWNZkOhWQUxUY3TYqSZHW7LovNTFyJ4fWGnHxxuvXauhqeeSnQ0sa8o0+uo0cNFnktv3nLXODKfSgQJkOcQm9zbFSQgjBEkF3+4xqyJVNFGtFaE80sk6+69iijHipjX63hrT6nN5NGKU82noV1dR8oXcr6luIvZ3dw2NLLoUQRPNh7mxAbnr8vU8Ce3DuRhiNnOlYVVXhVjVV1yAB+DLs4yWXfQg4o+EQUD3TODYxBaoWgjkavnh++1TIe0ib9bWblrfjN+lQlU0nrUbo90cI6fpsmhQhqOrqeTJLOHeKMq3/a5XYaqNaHyGVz8L7nCZ72pG10lkS6G1yszDut1DMlTFMllBMLim8cMP7BvrQkfTCXR58yZ0harkyrGINRX21DbgJPM13TVtUVDxjZnYWppiObeuoVtM8JetC93xvZ/eeBNxDswtjqECP72RAbmr8vWcCe3DuLIztdTQS5JDr2sFe+GuXxXIq9suVy4JlWpDFixtzidojDqb55NlyLhifflUCrK/dcG/Lz8TYtGCUdKghMcITghZPo9jor6wfZruMSj+OYj6+kdjCubNGdWQ1FSFFQUjVkcpVV77kNG5U0ZLTyE/X9m2U5TOB3xg3q4Ws/cLKR3z/Qw5tpYRWI+9ziv1AhqiVG0C2uNOa52E1j7JVRM23btOfk/9sUb7b2aI/3cmZ2UYp34Zere1UroVpv4mL29r9fOEtdMsVtNUciqn5nnY+LJ8fAoH9vFBxCCVjGZgAE/AQiKPcaiFlKgiJhy5zjGGrinIuib54Is8/fRq3hjVkc21olc0XUCvZGtqhEeSQmJq1YA67qFfKSCWHaHVreDp71ke9akDNdnFYfceBcpNTqPYHKFsWxqMuWrUKkrqBmtFCbvomiqt+E0Y+i/I4i1YrtdloqpuE+B5Wka9YKBnrvqS2LN/NmXrFmB2baBeLaMer6KdnAwmz+3z0UgTGjRyydRllo/wCL+O8lFSczioCe3DuFNgDdr9/geUM4dn5m9ZkoYcsb7wOZ1UBxLt6Yp2QGL0TOXifKUx7kdH8GqLVqfHdfRNgfe1GeHt+ip5Capq5Bj2ehAoNyWod3XwFvrG5UQO5VAnjbGuh4zdNZtmBrCKZ8ngZmo54UsFYzaHWriDle4UWsNpV1IZxlFr7erf9rXET29Ro9jSkputIppP21Hm5YiBX887NmuhWUki3VFSNGuxlkst0tvL6ENV8BVaxjdlzgCWWYk7XY3rbXmB1vhvZ4hK5zHYReSOOajftcVidfmbS2yyJ+Z4ub2/3LqVxO49Uvo9k3UBpzal4Ny5/fzsCe5iWVaFpzuvxo9Fouj/WqD+0X7KAqq+1jmITJJquioV3c2vrTIyGY4j1OpuuMtokbw67OQHW1+bMvDFekp+ua8B4PK2ndj7jFnKpPIapBtrVpKfj9EqxxbGiQQuJ7Ob3PxmjUW3BSheR9fiDW+SwMsrb4+YtrgZdkzEejz3T7Bb61TTSVQXldgO5p4Oz3gRWHw9bqHc/4Zd//ICP070SP+IvP37C55/+io8fxD50bhLb5bvQFt0kF3wb9QZ+//1H/PV7z/6If/w7fv7yC/7xpw+Q9cqLv7y3QIyDv7SL3ZtGEelsG1qtjfrL72F28Oxes4B7cO5kxFNxCPfui1FDXWxcPG6h2vrd5hRJJlesC9kOpSrSHLb8G3SaBlpdIJmK+0bztsuBY70kAdbXbjTX5Wf6OvpFeVroGn1A02d1ctxGPpVDN15Hu5Z62QejcRf9sQJNeHjez7COqqEgm99hytCb3pLjN8fNV84+jKGFkKpO2jsLw1oaqQpQarfWfvnBl6T3RM2h0e2h1/P+3+LyOIDA0QVue11U7AHDbfNdYIve/BccJyvdOXl66N0UEJWiOG327McOmSUAACAASURBVDes9/issECiw7y0rd2bXTHC3kKoaqCxz6euw8T26qXaw7QsEMqWka8a+OevP+Pvf/qIv7uYgkcoFX2TP+6d3b71IkqpOvLZIkLVvL2JcatcREvJweC1GLux3Uds1tduVNfh1y0i/ucalIs+umLH0WEdxbqFeFKHJn59whqjW6+gXBcjLjnnTVjTQCmdRQNZVLMKhoZ/26KQnoS21tImC0a1iK6SQtx+oQIwhwaq5TK6ehld36I6EbaGoZ5HI+mf2NsN0oLYb4LbGI18EV0ti3RSs3+Rxxr30aqUUB0nUZ20r6N6FqliH3q5Bk2sqfT+iIisIh53ncAFnBZdkkPQ9DmnXOxVHRL702iI6850+lr5rmOLi2SYu6ao+tMN6kcaFHShaTrEoDR/AGxh91a/inS6DDNZRVkdwTC8e1wo0JL6yz74saJensCa++EtDLZyk737Dp1nYhQOSCRJQYokTumqN7+r5sJkl15cmd9Dj65OExQR+QWCFD0+o+bd0qT4xlcgwPraDfJO/AYXlAgG6fhqsuPvpD5GggF7g3EpEKbo0SlddDw7AovNwMXm4wv/A+Tbq9Yu2iM1MxIFF2xiPLg6paNomAISCJJEwUiMMmfXNJjfF/X+io4DATpy5VyFbHBO0V02MRZpP9dOHDy3R+pdFeg4FqGgJBEgUSAYoUTmnJpTuA90dSTuLdalFLugVU3jSrub00/nNOjZxHjNfNexRV8+HTp9bhNjN7zYBJs3MXZpzL43tPu7i5jzQwSLbEg6ouvduvKZXHy0lMAm9XBRIh/ExW1dRvEblTtE3zjbr53fxgJyBB8B1pcPx8YnzG9jZHYE5rYdNzcW83NJvK5v1tvr0tdz0u6qzz2suXtOZL7PBJgAE2ACTIAJMAEmsC8C7NztiyynywSYABNgAkyACTCBb0CAnbtvAJ2zZAJMgAkwASbABJjAvgiwc7cvspwuE2ACTIAJMAEmwAS+AQF27r4BdM6SCTABJsAEmAATYAL7IsDO3b7IcrpMgAkwASbABJgAE/gGBNi5+wbQOUsmwASYABNgAkyACeyLwM773O1LME6XCTABJsAEmAATYALvlcAu+wjv/PNju2S+qcJ23dRv0/w4/G4EWF/MbzcC28Vmu9uOmxuL+bkkXtc36+116es5aYU+d/nwtOwu9DguE2ACTIAJMAEmwAQOjAA7dwemEBaHCTABJsAEmAATYAK7EGDnbhd6HJcJMAEmwASYABNgAgdGgJ27A1MIi8MEmAATYAJMgAkwgV0IsHO3Cz2OywSYABNgAkyACTCBAyPAzt2BKYTFYQJMgAkwASbABJjALgTYuduFHsdlAkyACTABJsAEmMCBEdizc2eiW00h9OEDPshJ1EZ7LL3ZRS2XhKrIkBUV8WwFxniP+XHSL0BghFZehyJsg3W1Gc+N7d1Ev1FCNqk7dURWoOppFBtDWN6cxwaq+RR0VYEsywhpSeTrfZjeMLAwapWQ0kNQ3DDz6UzCm906iuk4tJAC+YOMULbhS8saNlBM6QiJeisr0JJZVOcq7jphfOKtOjl0bmYDafkDxB5X3n852/LpycckpCGZq6HrVZI1RKuSQ0pXbR3JSgh6Ko963xtoFag17o3qSCkfoOTas8Ab5WthWM9Ck2VkWz4rtNPrlzQfA4eHjspwlp1zZGJo27Zm29EHWUFyr53NfP6v4Hxju58rk9VHJS7jg1pEd+4Wnx4oAdrhA2B57Mc7uj6JkASQCAcpQZd3y4Ovc2d5fnd0dRSgQOyUrjo96t026fwoTIHYOfXWSZjD7IXAcn0R0X2HzhNBCkYiFBS2cb8XEV51osv5bWHvvXOKRY6ocHlNndseDQa31Dw7oqAUptPO44TTgM5jQYpkzunq5pZ6gx51LjMUkYJ0fD1T0GOnQBEpTMcXN3Tb61Hn6oSigTBlmg8+3vfNE4oEInR8fk2dwR3d39/R4M4T5qFJJ2GJIidXdHt3T/d3PWqeJSgYSNDFYJLUOmF8uZLd3sxdmpy+Am53l5SQYlS4uaXbW8//wMPt/pqOgwGKnlxRpzegwe01nbnt3USVd5dHFEmc0sW10JEIc0MXx2GSgsfkUeVCTMvtzhv8ji6PwhQOByhwcjO9sX6+d9QsxCgYjlAkIFGm6drgNCnqnAQpeHxJHS+H2x7d+4I+UKcQpUD4iApXHeoJO7q/ozt/oFmib/houd62sHsfp0fqnccoHA6TFCnQre8en+yLwHJ9rpfjCu/s+QSWZv7QobNE0G5kpUDAcfD26dzdis4mNusQhOgPTcoEg086nOdLxSFeisBS+6ABXcQCFMlc0UA4HezcLUS+lN+L2fsdXcQkChdmzfXjwwP5+k56pJuTIElHV+S4d/f2g1Tw5MYXrnceJSl6Tq5PZte/sHD4Zk7hk0J2TigoHdO1L8NbKkQkSrje/jph5hJ+1dx6ZxQNHNMCX2daysGEte/B9bFDhYhwwj1O4DTG5ODhio6kwEJHyht0KT9PIOHEBWPndHka9jl3niCzwyf5PtLtWYQC0VNq3nWoEF7k3D3S9XGAome+Us7SnBw9iroQPNp54OBJwq/wwlK97dhePIo2WjC+yFCAnbuvZhlL9bmmBHuZlrWGLbS7nxCIFdCopaHsedRyaHQx0tJIaZ6MlCTScQtGq++5yIeHQUBDvtFHt5GDJsM33XQY8h22FC9n7ybGJqCE5GmBZUXB7ExclqEoCmBZjp6sLtpdIJlO+sLpqRS0YRvtydILs1VDW8mjnA5N035yoISgwITpnZK3TJimjFBo0mqsE+ZJwosvvAZuME2YspjuXlwGcXXUH0HWdejeIHIS6aSMbru7vD6ZQocKlFWJe9NcdjyqIVc2UawVoS3PbRb7Sb4y4qU2+t0a0uqy+i/sAFDUVb2HBaPWgJUuIafOsuMjP4Gd7N7qo5qvQinXkA1ZohngzyshsBfnTo5X0Gg10TWqSIt+Yc8wRsMhoGrw128FqhaCORpin0v99ly0N5u8rKp7d/rfKryXsHdr1EU9n0PdSqOc87kJc9hG6PdHCOm6U7/GI4wsFao6532o4v4Qw0ll6xp9yLoGs55HStegqhri6SIaQ09roOdRSg5RzhbREtfNPmq5ItpaGeX0JP11wsxJvOz0NXCzhHOnKCvrhqzIsMZj39pF0cpalgVzNJq7LmhYGPdbKObKGCZLKCaXEVrn+hC1XBlWsYaiPmcDT6KvyFdRMW9C/ugT505Z8XCAIYyuBT0uo1VMI64Ju9SRytfwkksL/XK9vrPt7d5Cv5xDVamglld9D3Ovj8L7k3gvzp142tdSaXtUZv9ILVimBdHgzTc19oiDae7dudx/GTkHJuAS2MXex6glZXuR+sc//hnFro5Kq45Vg2tmu4xKP45iPu4IYI5hQYY7sOZKJYaaZFl0yMJ5G2M0MmEZJRTbGor1Nox2HXnFQD6VQ2s6Uqci1zJQVhr4659CUEJxlK0SjLYYEXI/64Rxw676fg3cAOHcWaM6spqKkKIgJJyVXNX3clg8m0bIqKLUGjltmzVGt5ZDqeW8LDF1n60WsvbLGR/x/Q85tJUSWo28h+0qXovvDat5lK0iaiX9SXs7jfEi+YpRZQtGSYcaEqONIWhx8QJQf9aeWyOMRhb6lSIaoRyqLQPtRglav4RktsYP9bZCtrd7q1tGrh5CpZabGziZapoPDpjAnpy7Ay4xi8YE3i2BELL1PgaDHm47TZTjI5TiOnIzb8tHxhrWkM21oVVqKM68LV+YxSemPX1jqXk0GkX7jU1ViyNXqyEnt1BtuWPpJoxqHpW+ipOLKir5JGSjiFyx5emY1wmzWIqXu/q1uAFKtoZ2q4F6ow2ja6BVzUMdVpBK5tGevOgqJytoVTV0cxo+yjLkUBylfhpFMU0iy7NRPzmFan+AQa+HTrOClFVFUk+j7uLfFNCwinzFQqle8k8Jz6fzIvnGUW610KjX0TK6MNoNlJNAO5dEqjZ5XVZM4eMLlHQNjZIzcqfFs6jWy9CMKmq8ImdeM+ufW12U83WEKjWe8l6f2kGF/MNBSbOVMGLrE8UevRNPrN7RO9NetDG/hmirTDgSEzgQArvZu6JqTuev6YgnU9ChIVWuo5Qu+Ud0Rg3kUiWMsy0YeY9nZ6+Bs+y1ej4gYl2V5a7ncmqhFk/6n/hlHUkNaPSFd6HCbOWRrcooG23kxeJL5JDL15FNZZGt9NEtaWuF8cmx9OQ1cBMNmIpkyrPAxNaTgrGaQ61dQSor1qAp0PMN9PMWTGfRJBTZRD1lIuRb7iC2stEgJjY1XbfXSYrp9XLFQK626dzsENV8BVZR6MqFPFmDNVmPOWt7XyZfRU8h5WYFDbptTxqS1Tq6+QriELM1QcRTc6OImg5dGWEopvqfnTqeZvBGD7axewvdch71UAVdz2LG2YjwXEf7Rsm99mK9iZE7TVeBJ2vrTIyGY4i1XatWbbx2BbL874/Ay9m7DD2uAeMhpjOlAue4hVwqj2GqgXY1ORsJEvdCGlTFmQ7zkR/1MYQKURWBkL0mbzwWU7jej/NShtg/T6wD6zbasJJF5GzHzgknazmU8xr6rTbEpOPzYbzprz4+fG5L5Fc0aCFgLBw530eGEpq8fGEaaHdl6MlV6yc16JqMp3rxJbr4ZNhCvfsJv/zjB3yc7sH3EX/58RM+//RXfPwg9qpbHBXCMds237kkdV3Y62S9oRJCKGQu4CLsTCwTmIv8Tk83t/s+Go1f8em/f8Mfp7r+gO/+9z/48vu/8OePH6AWjXdK8/UU+004d2oyCU28oeudbjANtMRbfSnxfMcfJvB2CKxr7+YT52qegYV+V7yMpM8egMZte11cN15Hu5aaXXejynGk4kC3Zfgct2G7jZGaRNJ27mTEU3FY7fp0KtGObr9pO3Eo7c5XvCo9vybWHY0SI+6ig34ujCvY89+Hz21JGcZd9McKNOHhLfyIdWcVtJQ08mJqdumnD2No2aN7G7eJag6Nbg+9nvf/FpfHAQSOLnDb66KydDBwh3x9ZbEgXtSBJsabxSeOdFKBUW/5Hk6sbhtdU0P83Y/aOfA2t3sdpbZXz87x7XkCUjiDq9se2qXJGlyffvjkoAisuWXKwmBr7cNyc0KBvW9ifE/Xx0EKxAp0fTugQe+GzsWGnWJPHt8eWguLwRf3RGAt+xicU5T3uVuogeX81rB3sbcVJIpNdgMeXJ5Q5uySmmID47s7GvQ6dH12RGHJsxed2J8yFrD3H7u66VCn4/9399F9vBV7sTmbGPcGA+pcnVI0EKSjK88u5Y+3dBaVKJg4o+akTtqb6EYK5O6Z/Ng5dTZDPr+xN599uB9Q51JsiBykzGSn3XXCzMN7vdweqXNxSudXzclG0z26bV5QJhqgQOJitocgPdL9YEB39/d017uhy9MEBaUInd64ewre0/VphgoXTXuT4zuhb7Gx+3GEpDX2hFvOb540Uec06Nnnbpt8O3S6aJ+7wRUVzi7p2t5MW7TpHboqCHuN0MmNZy+/wSUlAgGKnV5RZzCgQeeSTqIBCmeak30Zn8r8Vq8s19vm7cUiRo/XxySFeRPjRWz2cW25PtfLbT+bGHvz/irOndi0uEdXpwl7t3MpEKTo8Rk1PX2NVyQ+/joE1jJOdu6WKmMlv+fsfXBBiWCQjq+cDv/h9pJOj2IUDkiTzcXDFD06oYubu9lmxLZDOPlFGfeXZabfAfL8EAHd35zRcTRIAUmiQCRBJ5e35OlynTLdd+gi4+QpBcJ2nbyZq5N3N+eUiYlfKZEIUoDC0WMqXA9mMhHROmG8EF8zt8HVKR1FwxSQxK/6SBSMxChzdk0D30PqHV0kxObwEgWCEYodF+iq56X/SL2rAh27XCfhEplzavoT8mKbHq/kNw3lHPidu23yXeLciV+wycQoEnQ2wbft5+iULjquAzsT5KF3SSeJiG2LUjBCR4V5XrOwb/lopd42bC8WcWLnbhGV/V1bqc81sv0gwmw7lCh+62+H6Btn+7Xz21hAjuAjwPry4dj4hPltjMyOwNy24+bGYn4uidf1zXp7Xfp6Ttpd9fkm1tw9B4nvMwEmwASYABNgAkzgvRBg5+69aJrLyQSYABNgAkyACbwLAuzcvQs1cyGZABNgAkyACTCB90KAnbv3omkuJxNgAkyACTABJvAuCLBz9y7UzIVkAkyACTABJsAE3gsBdu7ei6a5nEyACTABJsAEmMC7IMDO3btQMxeSCTABJsAEmAATeC8Edt7n7r2A4nIyASbABJgAE2ACTOBrEdhlH+E/7CrkLplvmveum/ptmh+H340A64v57UZgu9hsd9txc2MxP5fE6/pmvb0ufT0nrdDnLh+elt2FHsdlAkyACTABJsAEmMCBEWDn7sAUwuIwASbABJgAE2ACTGAXAuzc7UKP4zIBJsAEmAATYAJM4MAIsHN3YAphcZgAE2ACTIAJMAEmsAsBdu52ocdxmQATYAJMgAkwASZwYATYuTswhbA4TIAJMAEmwASYABPYhQA7d7vQ47hMgAkwASbABJgAEzgwAnty7iwMWyVkkxpCigxZVqDGsyi1RrD2BcDsopZLQhX5KSri2QqM8b4y43R3I2Ci3yghG9cQkif6SlfQHu2W6ruKvbW9WxjWs9BkGdnWstpoYij0M6m/H2QFyZpXOWMY1SziquLUbT2NUms4q9tWC2n5A8Q+TYv+Q3ljqipr2EAxpTvtREhDMldD13Rvj1FLygvTsNPVK+i7Qdf9PmRunjKY3TqK6Ti0kAL5g4xQtoEpFoxQjS/goubhkN0DN49s08NRHSnlA5Rce3oJ1hCtSg4pXYVi1+0Q9FQe9f5Mejuw2Uctn4QWEvVfhCkuCOO06XYYWUZISyJf6884GHmEltjYhw+r7Hsm7rs52sbuJ3GW8n838F5pQWmHD4AFsR+oU4iQBJC47/8P08nNw4I4611anJ+Ie0dXRwEKxE7pqtOj3m2Tzo/CFIidU2+9pDnUHggs09dDM0PhcIJOL5rU6Q1ocHtNZ4kgSdEzun3cgyCvNMll/La39ztqFmIUDEcoEpAo01wEW9TfKAXCR1S46lDv7p7u7+/o7t4N+0i3Z1GSwkd03rylwaBHN5cnFA2EKdO8n5B+oMHtLd3O/3cu6DgYoKOrSbj7a/s8enI1swO33k6yux8sSOf2hs4SAQpmmrSoNXm93Bx8980TigQidHx+TZ3Bnc1/cOctaY/OIhIlzjt+xr07crW0DTe3mizn54YQ33d0eRSmcDhAgZOb6Y27yyOKJE7p4vqGbu26fUMXx2GSgsd07ZoHDehC6C9RoOtOjwa9Dl0Juwwe0eWdm9T9pE0v0HXPYXB7fUrRQJCO3YQe7qg3b2Pi/CpDYSlK5wM3rffxvVxv2/SPa/B/H1i/WSmX63M9kRZ5Z+vFdH6aYmHYx9szigXCdHTepN79Az3cNekk4jh60tHVwgZ5YUJzF5cW9rZAESlGF97K/NCkTDBImaa3UZxLkE/3SmCpvuiRHubVcndBMSlMhdu9ivSqEl/Kbyt7F05ZhALRU2redagQXuzcPYq0fZ3sHLLHJmUCgSf1SnTqgejZyocp4dQHgxlyq+TgPEpSdO4B7LFDhYjowOcNxCPH3SUlAhEqLHkSeNXcRLsV9jrKnnJPDzt0GgzTaWd6Yb2DZ7i5iSzl5wYQrt3lEQVj53R5GvY5d54gs8OHKzqShM1MXM/bAoWlBF1OnT0R9IGamSCFTzuOg/p4TcdSkE47rrsqwjzSzUmApExz6sTOMnGPHqkjZDq6Il/y7u03/L1Ub9u0F1vzf8OAv3LRlupzTTn2Mi0rx8UU2xDtUhp6SIGippGNB52xTcucDau/0Gjn0OhipKWR0jwJKkmk4xaM1sYTN55E+HA/BGQoylzKSgghWDCXzRTOBX/Pp9vZu4x4qY1+t4a0itkUqg+kBaPWgJUuIaf6bsxORkOMLA1x3a9ANZ1FfGjA8M7ezmIBGKFRbUHJFpGeRB31R5B1Hbo3nJxEOimj2+4ukRHo12roannk47I35rPHr4Gb2aqhreRRToeWl0e0oZbytA4tj2Hf2Zbbk2RHNeTKJoq1IrSlWvLEMi1YEPI6+jKHQ4xVHbqviApS2SRMozWZahfhLYzH3gbBwtgEQmKq2pO879BsodqwkC5m4UveF+h9nWxn91vyf19oD7q0e3HuRIndiuyUfoj+ZM2FoukvXulGwyGgavD3RwpULQRTdEYHrQIWThCw+gb60JH0OuiMZiGBre1dUaEu7RVFVkMYXQt6XEarmEZcU6GqOlL5GqZLphTRsZoYza9ntR/aRhguq2zdKqpdHflifFomWZFhjcdzD3sWLMuCORrNXZ9Es9qo1kdI5bPY1FReA7eu0YesazDreaR0DaqqIZ4uojH0ODmmeEBWEPL711OuCw924OZPb4hargyrWENRX2lMolZj3G+hmCtjmCyhmHRSkoUNiTJ4iiTuCL1jNILtz8kpFEsajFIWlbZYq+2s8yz3k6i4CfkFs8+G9SraoSzyqedkWxD5jV7ayu635P9GEb7KYu3NufPSGNbyqPz6BZBiKOaTy5+6vJHWPrZgmRZERzFfnRUxPGSa6zxbrp0bB9wHgSFq5QYgRnX4cfsZwHu0d2uE0chCv1JEI5RDtWWg3ShB65eQzNach6RQCtn4GI1ydfrigzVso5Svov9l2YigiVa1gXGq6BsRjGfTCBnV2YtW1hjdWg6llrP4fq7vt7mMG1W05DTy2U0N5TVwG2M0MmEZJRTbGor1Nox2HXnFQD6VQ8t1qM0xTKuPakqDKmZGQiriqTxqszdRntjQ9tz8SQ2reZStImol/Ul7Ow1ptZC1X6j5iO9/yKGtlNBq5KfOuBxPI4kWymXDceRgYWRUkSsb+Gy7hE5KerGNdt5C5S/ixTwVqVoI1W4LWf9T/DRbWF3Uan3E80XMHiFmt9/n0fZ2vzH/9wn4YEu9d+du3M4jXfwZnxFAoiKe9g6WBQv2TQiYMPJZlMdZ1KspbDIY8U3EfcuZ2qNvX6Cka2iUnJE7LZ5FtV6GZlRRs1c4qMjX68haVSS/E2/Cywilawjl8ohLCiYzb35KowaqbRnZYtqnXzlZQauqoZvT8FG8WRmKo9RPoyjmbWXZF9ZJsI961YCaLeKgBmZejJsJMXhlqXk0GkX7jVNViyNXqyEnt1BtTYZFtTzq7Qbq9QbaRhdGo4Ks0kUpmUSpu8glfiFuwyryFQulesk/le7XNiCnUO0PMOj10GlWkBK2oqdRd0d1Q1nUGyUorTS+t3dTCCFZGSOXT0KSZzY0bpdRrI6gF6qolrOIWw3ks6WluyCYrSoa4xTyS9cUzAvK56sIbMp/VVp87xsQWHNt3sJgzy34e+iIFyvEixQSRQudrV+kcDNflt/NSZCk46eLbMUCcilxSdMXsNyE+PurEFimr1nmD3R7HqNA8JiuvC/DzAK866Nl/Ha39w6dLnqh4sFdxD6PXSzgl+j42ru4XayBv6f7h1WL5J10eqIezr844cvikR7u78lJ6oGujiR7Yb0viFhOf3PiLMR/pkK/Xm53dBGTKHo2/47/IzWPJQqufIPCiRs8uXnyssG63Fzei/mJN1yDFDvvedIXLzgEKbDyBQeR6oDOo0t0+uDqnWhwHrPtxG4K7Jc/wpRx34wVyTz06DwRWPKyxB1dJJw85qzULdab/16sN7J1tHH/uDH/N4/3qxdwmT7XFWRvI3dWv4J0+p/45XMAsUIbRjW54En8ZbxZTVeBJ2vrTIyGY8iq+uJr/F5G6veeioV+NY10VUG53UBu0wVU7xjf3uxdvNQSMjEWq9Z9H7EgXozS+S4CIvxkqG5oGBhrccTnZ0tNsUZujHg+t2K0R4YSCjmjfqaBdleGnpwf4h/bL2RY6eLyabk58eZPD59bCKoqYzwezy0lEfzFYOa8ArwlVKFpCswny1B252bnMmyh3v2EX/7xAz5O95b7iL/8+Amff/orPtr7ynnl8R5r0LVF5YK9x51jQmMY7T5C8bi9dlq8WNFV0ih6p98VHaVyForRgjFnola3ilpXQ7740st+vOV4ncfb2P2m/F8nmbct9V6cO2tYQzr1D/z8WUIkU0OtpNkLp0WjJTqORRMHu2BWk0low5Z/E1zTQKsLJFPx5WtDdsmU4+5AwMKwlkaqApTarTUWZu+Q1RuMuq69m0+chOdgxJFOKjDqLbjLu0QMq9tG1xRvyC5xLsYNlKsjxHP5Jw7cuFFBCyl/J71UDLHer4KWkkbefaXWDTuso2ooyOa3n7o/fG4y4qk4rHYdba/zYnUdhze+6gnIeWlNVVX/Q/QLcLNVoObQ6PbQ63n/b3F5HEDg6AK3vS4qkxcmXJXNvvswhhZCqrq0LTaNMqpdDVl3TbZwZO23gmepiCNLvIghpvB9pmiiLdZ0Jov8kOjHZZ9tZfcb8V+QKV/69gTWHeJbFG7xsOGAzmPS3ObFns2MxX50z0yrLMpLXFucn7hzT9fHQQrECnR9O6BB74bOxcaZkQJvirsM5le4vkxfd1fHFJaC9j6IN50Odbz/t7ONWL+CiAedxTJ+a9m72NsKEsV8mz+6xV0yLStuD8QecgGKnV5RZzCgQeeSTqIBCmeas33DHu5oIDY3vhvQbfOcjiMSBRMXNHgyH9ajs6hEkcKtZyrPlUF8P9L9YEB39/d017uhy9MEBaUInd7M71Dm7F0mxc5pndn7V83t8dZmFkycUXPSltmbAEcK5G75dt88o8LFNd10xCbSA+p1run8OOJsFOxrWzfj5mpmOT83xOy7cxr07HN3T9enGSpMNie/u7ujgdhQ3pbNu0Ex0cOdo3ex2XLzQmyCHaDY2e1s6Y69T6lEkcwldQb39HB/R72bCzoOSxRx98JzxRBTiBLvabpcb2v0j/PtxSb8XT3w94sSWK7P9bLZSxA0lQAAIABJREFUwybGYvd0jzM3/ysVe3HunPUYV6cJe+d9KRCk6PEZNX0N3XpAONTLEVhsnM6aKnFv0b8Uu+A1khMVLOY3ufnQo5X2PrigRDBIx+6vQfjUusK5s6vSJZ0kIhSQJJKCEToqXPsdt5tTCkogSAEKRxN0cn5Dd08cO2eNXHB+c3GfHGKdVIAkSBQIRih2XKCr3oLNi++v6Djg+WULXxpPT147N7rv0EUmRuGARFIgbLdlN5627PFW6Cdq3xfrmQW7xMk53cwrYUNuLsmV/NxAk2+/c/dIvasCHcciFJTEA/5Etsw5Nec8f/tXTgASbXUkkaGz68GTB4DHwTUVjh0OdlrhGGWErc3JYK+tFg/yc9ff2+lKvW3RXqzL/71x/lrlXanPNYT4IMJsO34oft9xh+gbZ/u189tYQI7gI8D68uHY+IT5bYzMjsDctuPmxmJ+LonX9c16e136ek7aXfW5lzV3zwnN95kAE2ACTIAJMAEmwAT2Q4Cdu/1w5VSZABNgAkyACTABJvBNCLBz902wc6ZMgAkwASbABJgAE9gPAXbu9sOVU2UCTIAJMAEmwASYwDchwM7dN8HOmTIBJsAEmAATYAJMYD8E2LnbD1dOlQkwASbABJgAE2AC34QAO3ffBDtnygSYABNgAkyACTCB/RDYeZ+7/YjFqTIBJsAEmAATYAJM4P0S2GUf4T/sim2XzDfNe9dN/TbNj8PvRoD1xfx2I7BdbLa77bi5sZifS+J1fbPeXpe+npNW6HOXD0/L7kKP4zIBJsAEmAATYAJM4MAIsHN3YAphcZgAE2ACTIAJMAEmsAsBdu52ocdxmQATYAJMgAkwASZwYATYuTswhbA4TIAJMAEmwASYABPYhQA7d7vQ47hMgAkwASbABJgAEzgwAuzcHZhCWBwmwASYABNgAkyACexCgJ27XehxXCbABJgAE2ACTIAJHBiBvTh31shArZhGXAtBkT9AlkPQkllUWiNY+wJgdlHLJaEqMmRFRTxbgTHeV2ac7k4ErCFalRxSugpFFvoKQU/lUe+bOyX7riJvZe9jGJUs4qoCWVagJnOodeeZj2FUPWH0NEqt4azeGnmEPnyA2IPp6b+MbGtSw80G0vLTMHK2NUtrTTuwhg0UUzpCom6HNCRzNTwRe13lHzq3uXKYrSzUDzJS9Xk9iYAjtPI6FDmJmq+tG6OWlBfoZ6IPvYL+XD5bnY7qSCkfoOTanugm+o0SsnENIbtuq4inK2iPPEHEodlHLZ+EFnLrf3Fx/bdGaFdySE7aig+KjpJPeK9Ny1BUHaliA8O9dTRz5XhVp8vsZUUhnuW/Ii7f+rYEaIcPgAWxH+jmJEzi3tP/MJ3cPCyIs96lxfmJuHd0dRSgQOyUrjo96t026fwoTIHYOfXWS5pD7YHAMn3dXR5RJHFKF9c3dNsb0OD2hi6OwyQFj+n6fg+CvNIkl/Hb1t575zEKBBN0dn1LvV6HrgsJCgaP6OrOBfRIt2dRksJHdN68pcGgRzeXJxQNhCnTnCjm4Y56t7d0O/9/laGwFKXzwSStu0tKSDEq3MyFHczq/1p2cH9Nx8EARU+uqGPbyjWduXX70ZXb//2quXmLct+kTDhM4aBER1czbnaQ+w6dJ4IUjEQoKCXocq7e3A/muNv6uqGzRICCmSbNpebN1W63fRcWntzR5VGYwuEABU5upiEemhkKhxN0etGc6SsRJCl6RrdTfQ3oQsiRKNB1p0eDXoeuCjHbFi+ntkhEjz26EGWMndLlTY8G9/d0f3dH99N0iAbnMZKCCTq/GdD9/T0NOpeUiUgUPrlZWcapwG/oYLndE9Ez9rIQwxr8F8bjiy9CYKU+18hhkXe2RjQnyNLMH27o7OScmrd3dgV7vLumTNhx9gKZG/LUzbXzEgGX5ndboIgUowu3YxGBH5qUCQYp01zVjG2UPQfekMBSfS1K5+GKjqQAZZrbWseiRF/3taX8trH3xxs6CQbo6MrrBdzRZSJA4ULHAfXYpExA6MBfZ4QTFoierXhQeqTOaZgCR1c0Tb13RtHAMW2szjk7GJxHSYrOPaQ9dqgQCdLxtV9OV9uvmptbCLqnZiZMkdNLOovOO3cDuogFKJK5okHvnGILnLtpMt4D4XAHIlSYeVneu9PjpfymIYiETQRj53Qp9O5x7oge6WFeLXcXFJPCVLidJHBboPATmR+omQlS+LQz7R+E42Y/oC9tEoT9ShQ58z/CP1wdkRQ+pYlVe6R+24fL9badvTzP/23z/NalW67P9STby7QslBQq9RLScRUKAFlNIaVJ9hClLKZWXniwcmh0MdLSSGmehJUk0nELRss3hu8JwIcHRcC0YEGBory0dRxUKV9EmK3svd+GYcaRTYU8MqhIZXWM221nmm40xMjSENdFrZ191HQW8aEBY35qzQ1itlBtWEgXs5imbpowZbEsww205vecHYz6I8i6Dt0bXU4inZTRbXdnU7ze+0uOXwW3iezjRhHFfhq1SnxBaTTkG310GzloMtZm0K/V0NXyyMc3VcqcCKMacmUTxVoR2pPcZSh+8wGUEEKwYLoz9sMhxqoOfWosIn0FqWwSptGaTBl3UauPkCrloS8V12kvLNP0SWGaJqCoM1ucE//9nW5jL+vwf38kX1OJ9+PceQlYYwxbZdS6XwAphmJ+UWPljbD58Wg4BFQNqi+qAlULwRQdlu86nxwWAQvjfgvFXBnDZAnF5GFJd4jSbGPv5miEsaJC9XWogKqqkEdDZ42SokCGiZFv/RYAyxRXMVxSkYb1KtqhLPKpWS8sOlxTUeyHu/UYLrYD8TBojcfwrzizYFkWRJn811fn9Bq42SUYN5Av9ZGuVZAUjtKC9WOy6jw4ry6x567VRlU4S/ksvM/AnhBrHg5Ry5VhFWsoLve6fGlZfQN96EhOMpaFnQn7mCuX0CmEnYrroy76Iw1xpYtKNglNVaHqSeSqBmbmqSBdzEFp5JGtdTGGhVG7hFzFRK6S37GcviK8+pON7WUt/q8ey5suwP6cu1EVcbGg+uP3+NNf/4WRdoJLo43Smg3C+tQtWKaFRSOCiniEnHuqWz9dDrlXAlYLWXvB/Ud8/0MObaWEVoMb5OeZb2fvwtkSQyrzgyrONVNUEyCUQjY+RqNcnb6wYA3bKOWr6H9Z6GMAVhe1Wh/xfBHexzZ7NGVUR1ZTEVIUhMRC91z16UtOz9hBPJtGyKii5L6MZY3RreVQajlu3Zx/sALf6+AGjNHIlzBK11BJzpzlFQVb69a4UUVLTiOfnfPu14o9CzSs5lG2iqiV9DVnYIaolRtAtoj0JGs5nkYSLZTLhuPICafMqCJXNvDZ9WXth/IRaqUqxukKWoaBViWFcSWFdGU2GyMnq2g3UhgV/wxVCUFLt6E3uqilnlj6rBB89DyBNfk/nxCH+FYE9ufcQTToYYSDAYgJ2U+/NFAuFlHn15i+la4PK185hWp/gEGvh06zgpRVRVJPo75kdOiwhH+r0qjI1+vICl18J0OWZYTSNYRyecQlZeEUq9mqojFOIZ+bGzfP1tBuNVBvtGF0DbSqeajDClLJPNre4bZn7EBOVtCqaujmNHwUb1+G4ij10yimFUCWnzqr30Q1L8dt3MijNBLTsck1nad1CtxHvWpAzRbhGVxdJ6I/zLCKfMVCqV7yT5P7Q3nOTBj5LMrjLOrV1ExXoSzqjRKUVhrfi2U6cgjJyhi5fBKSPLEzMVr8BYiXG6hm4/bInZ4qoV5JYlitwXC9+lEDpVIDVvIM1WoJaX2MWi6H6tavU3vEf8+H6/J/z4wOvezrLc1bHGrdBX+P9zdUiEr2CxFS7Jy87z0sTnnx1WX53ZwESTpuThfiurFvzyIkJS7J+wKWe4+/909gmb4W5zyg86hkL6hefP/9XV3Gbxt7f7g+Jim4YJH5zQkFpGO6nl+0/nBP9w+TiwsXwAt93NFFwtHZfPSF2nq4puOAtPRFCCfOMjt4pIf7e3JEeqCro+W28mq53V/RcTBKhY7njYTHHp1FxAsV01dV/GgH5xR98nKCP8jjzYnzAsOaDeFifuIN1yDFznuedvaRhC0GMk/bXqIHurXfzj6mqxUN/uODq9PJm6/RSf+wzC7FizrT8vbsNiNy2vG8GftAnUKUAsEMzb0X5IfyBs8W622uoGvYix1jLf5zafPpixJYS58rctzjyN3MrZXFdE/SebL/0u+/+B5Emq4CT9bWmRgNxxBrDXabiJiVg4/2SUCDrskYj8XKGf6sIrCNvStizZI5erKebjQawRL35mcAxSL4ydsQQ8PAWIsjPleRrG4Vta6GfHHNUSZFgxYCxmPv0N18SZfZgQwlNHlBwzTQ7srQk77XLOYTenJ+6NzG7Qban37Fv/7nu9kedR9/wD9/+4L//u17fJBTqM8WnD0p3+ILYzSqLVjpIrL+wdXFwZddHbZQ737CL//4AR+nexx+xF9+/ITPP/0VHz+IPQ7dyBb61TTSVQXldgO5FYv8xB6XjpmNYbT7CMXjztppew31GOP58lpiecDkpbxhG62hjlwxORsVhIJkpYyU1Uar68rD3xsTWIf/xolyhK9JYA/O3QitWh3GcLYI2hq2UHN3sVzUkexYYjWZhDZs+TfKNA27cidT8Rec3thRUI6+gkAfxtBCSCzwXxGKbwHr2rvpdZT1NJKhLlq+nb3HaLf6UOKp5dNs4wbK1RHiufxcGBPtagPjZHFl5+3T17iL/liBJjy8pZ/n7MBCv1JBS0kjL6ZmN/gcOjcxBd7t9dDz/V/jJCwhdtZBr1ubrltbu9jDOqqGgmzeMy26dmRPQDWHRndetltcHv//7L09cOpatu/7X1VdJe0IdYQ6Qh2hjqyO4EToReZE0FWvytzI3MjK4ESmMzK4kXUicyPTVa/KnMicyJwIdQQdQUfQEdoR7MjakbWj8WoKg8WnMZjljzWo8kJIY379xphTQ3NOjRVB5PQKnV4X1eBlKB/DWhbpKlBqNXd+6cJzyrC7OnLW04OCbsLU+mg0hqFKiPcsHLja9CEB8vQFoOUXM8QGUs8Xb9IuJOUfLxBYGC924f9Cfnz5nQlsmdV78dL6acMOFZ5i2gESSdJ0OVbIAjE6OyBK7fryRDXHdJuJUiRRoNvOgAa9e6qIoLjxQihw5ovNYYE3JrBeX2O6vTijwlOQ09FoRAMRdDoTJyl6SgtBTN+4Pp8tu/X8RCt2sHcRCw8SJULBHwdXKYpET+kyCFDcobvLFEUjy/EhRzQYiWCxA+rcVSgTlyiauqLB8rprEKR4UxzJR2pfXVDl5o7anV4QDLlzd0VnJxGKiLwCRexqB480HgxoNB7TqHdP1xcpikpxurjfsEy5LR7mh+e2zkJny7Khpdqw2NZltmn8wdduhdlsd+GCp8fti+hCnLvRTYZiUpROK3d0325TO/zXGc2XdB9GU52KYMt3VyJQdoQSl53Q8irR+DYT6Prsuk29wYA6twVKRESsxtn6sgik/BS8vjOg8YOwkTu6PI1SRMRGXLbZ1ep/qTM76W2TvawZL17m/6XwfbjG7KTPLbU+QhDjMbWvzuk0EadoRDh2EknRGCVOL+i6vXlA3lLH+aWtjX3o0c1FiuIRiaRIlE4yl3Q3GwPmOfDB9ySwXl+P1LspUEbYR+D4SxSJxil1VqG7FQ/ie9b245W1nt9TPV+y98EVpaJRyizs1XqgztUZJWIRkqQIxRJnVFnuk/cXFJVAENdPUnReuafRmptksJ9VPDxtwDa4uaDTkxhFgrwkisYTdHZ5G3ISd7UDsa8vQhKmdpLIFOimt8HRearLZ+a2ivMA507s4QucodeNu1v5LVVw0bmb7oUU6df9SYmr+f7n4H9CAYKxOp46o8vbwdzxey7ikQa3BTqNR4NJgkg8RefXvQUHkIJ+cEonwqaDe02cUudXtGzWz3l+3aOd9LbJuVs7XuzA/+vifPeW7aTPLbX8Jq7tO3ko/m/JA5K/utjvXd6rK8gJFgiwvhZwvPoH83s1siABc9uP2ywV85uR+FzfrLfPpa+XanuoPo+w5+6lKvN1JsAEmAATYAJMgAkwgWMRYOfuWGQ5XybABJgAE2ACTIAJvAMBdu7eAToXyQSYABNgAkyACTCBYxFg5+5YZDlfJsAEmAATYAJMgAm8AwF27t4BOhfJBJgAE2ACTIAJMIFjEWDn7lhkOV8mwASYABNgAkyACbwDAXbu3gE6F8kEmAATYAJMgAkwgWMRODjO3bEqxvkyASbABJgAE2ACTOBHJXBIHOHfHQrtkMJfW/ahQf1eWx7LH0aA9cX8DiOwX2q2u/24zVIxvxmJz/XNevtc+nqptkKfh3x4WfYQepyWCTABJsAEmAATYAIfjAA7dx9MIVwdJsAEmAATYAJMgAkcQoCdu0PocVomwASYABNgAkyACXwwAuzcfTCFcHWYABNgAkyACTABJnAIAXbuDqHHaZkAE2ACTIAJMAEm8MEIsHP3wRTC1WECTIAJMAEmwASYwCEE2Lk7hB6nZQJMgAkwASbABJjAByPwHZw7H/2SAfnbN3yTs2j6RyLgdVHLm9AUGbKiIZmrwpkcqSzO9m0JuHWklW9Q8q23zfcr57aXvU/gVHNIagpkWYFm5lHremsoeRg2SsiZOlRFxjdZgVlzp3KOBVX05bV/MnKig/tNZOVNMt+gWg6ACWqmvCGfb/hmVNHfSWZN9bed+vTcQo2bOKhZaRiBPr9B1iwIsvPPXm2dp375YGu/ddG0DCiyidq6cdjro2aZ0FUxXqsw0kXU+0u2uItMK7/GHmWYawt9uUlfUsIfolnNI21oUOQZb2uV91LjJ906itnk9J4ajBc52HxTXaL0cX8eHMT4xaYNa7Dsf+K3FwUPEXBRz6VR8nKwmzYM2UWrXEQ2CzjdEoxDsua0RybgomaVMVQiRy7nK2W/n733q1lkbRmW3UJN9zGsl1HM5iB3W8hrMz4enKKJbFNFvlxDSzh4sg8f6lTAKKHVyWPlGW1oI2cNYegyIJuoOh2UZlnOvv0uqrky/KQOQEW25sBYup8DHpqlHOqqDg0q1BdlZpnv8v0VuD21060jaxbhmmWUG3bg4MHzocwx7NfWefIXD7b024mDai4He6JAXpvPEHbWRBV52KLuioduvYRSOge/24IV2OIuMoDvefDi57itW5ibMABFe7LXteX/WCfdehGllgarVENZ16D4LlpVC1Z6ArnfRG4dqkkd+WwZyJVgN5PQhY5qxWC8QNdBUXRh/nxsAnTAB8ALqUd0cxohIRf8SRm6e3whyZbLG8vrFCguJehqEEr8cEdn0Sid3T2ETvLh9ySwUV+hSoyuTymaqND1RYwi5/ehK3y4kd8+9v54T+fRCJ3ejENgR3SdilCs0J6fexR5R0/pejQ/tcPBI7WF/k5vKJz7csKHuzOKRs9oa5ccXVMqEqdCZ8tA8YLM1+c2DsbVeKFNG0e3fWzkSWEb+YUUurnfDugqEaH42Q0NehVKSCm6XjaKToFiK+cf6O4sSrGLNgWa30WGiMbXKYqkrrfaXajaX/pwF73NATzc0KkUobMtN+SHh+U+2KFCXKJEJXyjnefIB29M4FX6XFP2UZdlJ40SSv/zK6RoBNIRfdyh04WrZ5EOP00oJrJJH06zf8SSOeuDCLg15MseirUi9NW5oIOy/sqJ97L3fguOl0QuHX5M15DOGZi0Wpj2Eh9OrQE/WwrN5O1A0mvCbvjIFnOz+b01iVw07CaUXBHZ5+mlFbl+rYaubsFKrp/zEQl2kVnJGMCX4eY2UOsaKJbM0EzdYov3autiFpt/be23OqxGH91GHmISd2WGF4A3HGKiGTDCpggF6ZwJz2kGtriLjKjgxPMARdnIYXMjfvArnpiNV6Aom/vZ6jUVmgJ43jqt/uA8P2Dzj+fceS2USv+FX6QTFIvpDdPzb0PEHQ4BTSzjhD8KNF2F5w7xtFsofJGP353AELV8GX6xhqKxeYB592p+wArsY++e62KiaFherdI0DbI7xDAYr4dwuj6MpIxmMYukrkHTDKStGpa3Q4WxDOs2WmoOVnqLHrs27K4Bq5gMJ1089luw6y7SVg7h57QFoV1kFhI8//gq3Lyug6GWhDa0kTcNCB3qyRyqreeRbp+2PpPadvRyv5U1bauzJSsKZLGcuuQj+L4PCDv1gV1kRC091wv27G2xvG2N+QGv+Zj0myjmyxiaJRTNVyDwunCGCoxgW8Ur0rHouxA4knPnwykX8befJZwUayjp65/g3qbFPnzPhyxepFjKUFGCx4y1T49LovzzOxMY2hbKfhE18bLNdy77cxe3n72LvUlrZziCWQ8P4jJ8F67ro18toqHmYTcdtBol6P0SzFxt/UOS30Wt1kfSKmKz2+ahaTcwSRe3zghOGjaachbW2k1AU63tIrNev1+H28R14U8aKJWHMMsNOE4LtTxQz6ZhOcJj2q+t67ktnn2LfisnszDRRLnsBI6cqK/r2MiXHfwa1B7YRUak84ST2LKgayrEeK/pJnLVJtwlx3GxFT/gL7+JXPCS00/4w5/zaCklNBvW5oeoFUQ+uuUqWloexW0PcSvp+MR7ETiKc+f3bRRr/4J0YqFWTvLN+720+1HLHdqwqj5KdX7Z5UOpyPfg4Tco2RoapenMnZgRsutl6I6N2podDl7TRmOShvX8RsZqk9wG7JaMXDG7ZUanj7rtQMsVsfnesYvMavFHP/OduXkTD7/5BkqNGvKmDk3TYVp12DkvWPpeeUflrQC8Vb9Vc6g3SlCaWfxBPJTLKszqBHnLhCQrCFYKd5GBjKzdQrNeR6PloCuc3JKBiZ1DMt/Aupd03wrFp8tHTsPuDzDo9dC+qyLt2zCNLOrPk71bmzRp5JGryyjXy9iyY2JrHnzx+xI4wtuyQ9SKZfwTcRTsamAIx32IEq92K8HsnSgnPAsknurEbEX43PfFy6WtEhjCtqrwiy1Y87U3H2JFRvyzrMPV9D/6mf3sXfQRMT23cuMPzom9N4K/mP2OIplemk3VDRiKi6FYu11YQndRrzUh51ov7KOz0dUs2Obmnui3bNSGSZSam99t30Vms3V8IW6yDMlII7mwZ00Olsv8Wh8uckcYE9+23ypmCa1hCb43gS+rgUM3rCYBsdz8pMRdZKAmkU4/a103kjBVD3rWRsPNoTjL7FnkBz2Soep6sCdWNwyYWROqYaBcdZCvbV+bnbQspK0+zLqD0kL//0FRfpJmv/3MXb+O2t9/A377F/7z//kpiGP101/+axoK5bf/xl9+kpGur9xiDsKlGxqwsrfOgzucQOz/WBgDDyqJEx9MYNhEvfsL/vHXP+Oneay0n/Dvf/sFv/7XX/DTNxEr7eBSvnQG+9i7omnQPBfu0nSGK5b4xDXhdykqVNXDZLLcP4XTLWZYFrH6XRu1rg6raG5+gPLEProJklZ+S0iiSTDj5GeLyG28Ge8is1i/5V9fhZsmNk5O3JWZqWDPGqYPs/u0dZnXwu8j9VsR4266p38Cp9WHmnx27mbl7yIzkxXfsm5Ag7Dj8Fk+XiSgB2GLJpPJ1m1LnlNENteCXmuhnuU76SLDj/3r7Z07KFBjMcTCf9HZu7ISIjGxN+JtoWimCX3YRGg/MeA5aHYBM83Lwm9L+8DctDwa3R56vfBfB9eZCCKnV+j0uqhuf5A8sAKfP/mu9u6FB24jC1PtorkQhHSCVrMPJZl+crySyJoKnHpzwXEQsce6no7kwlO7h5bYR2cWkZ/PwK6ynTSqaCKN4pZ9dBjWYTsKclZ687LtLjKrxS+c+SrcVDMLw22i0Q2viUzgOEMohnBsgF3bugBo248j91vPKcPu6shZmx8UdpERTfD6XQxl4bxsa9CPfq0PZ+hDFS9UPaFYGC8Ex24V6VwTqu2gsfmp60cH+XHbvyY8ys6ndo3D8nh3RpKIdXesOHc0pttMlCKJAt12BjTo3VMlEyMpXqBt4bJ2bigL7kVgV/sQmbcvohznbonyZn472LuIcwaJEqHgj4OrFEWip3R516HBoEN3lymKRpbiQw5EnLkIJS5uqD0Y0KB9TecnEYqd3S3GEhOx5qSX4kj26PJEonihM41dttS+6c9pjDwpUaHN0bN2kXnO/Otze6D7izhJsQxV7ns0GPTmuqz0Zhx2sJGZ6NL3Zn5Lgi/120GFTlbi2U3zeBgNaDQe01jY4dU5nQibu+wsxO17WaZD1xcVurlrU6c3CGz6/vqCElGJTi632dxqO77CmfV6G9PtxRkVru6o3RvQaDSiQeeOKpk4SeF4lkvjxWPvilJRieJn13TfblN74a+3OBZ8BXgfsA3r9bl7RV+KQrw1p10LP75zR0QPPbq5SFE8IpEUidJJ5pLuXhWIdWtT+eIeBHa1D5E1O3ergLfye8neB2JwjlJmIWjxA3WuzigRi5AkRSiWOKNKeznCrOhK13SeilNEkkiKxum0cEuDpXimncv49OFptdrzM4/35xRdDi4+v/p0ML6hTGQ5uPKS0C4yoSQ/BDca0f1lhk6i0lyXV8u6fMlGQszCh1v5hQVf6rdbnLvO5UnwwC/G6njqjC5vBysPAC/LjOiukKFELEqSJCYPhE1nqHDTW3ASl6r8ZX+u19sj9W4KlEnEKSpJBEgUicYpdVahu3CnXhovRleJ6YTM7D8gCH9Lp3S7MXr2l8X73Ru2Xp+7V+ObEN13XlH8/5IHJH91sd+7vFdXkBMsEGB9LeB49Q/m92pkQQLmth+3WSrmNyPxub5Zb59LXy/V9lB9HmHP3UtV5utMgAkwASbABJgAE2ACxyLAzt2xyHK+TIAJMAEmwASYABN4BwLs3L0DdC6SCTABJsAEmAATYALHIsDO3bHIcr5MgAkwASbABJgAE3gHAuzcvQN0LpIJMAEmwASYABNgAsciwM7dschyvkyACTABJsAEmAATeAcC7Ny9A3Rfl72oAAAgAElEQVQukgkwASbABJgAE2ACxyJwcJy7Y1WM82UCTIAJMAEmwASYwI9K4JA4wr87FNohhb+27EOD+r22PJY/jADri/kdRmC/1Gx3+3GbpWJ+MxKf65v19rn09VJthT4P+fCy7CH0OC0TYAJMgAkwASbABD4YAXbuPphCuDpMgAkwASbABJgAEziEADt3h9DjtEyACTABJsAEmAAT+GAE2Ln7YArh6jABJsAEmAATYAJM4BAC7NwdQo/TMgEmwASYABNgAkzggxFg5+6DKYSrwwSYABNgAkyACTCBQwiwc3cIPU7LBJgAE2ACTIAJMIEPRuA4zt2kBlP+BhGnZeFPTsIeHomA10Utb0JTZMiKhmSuCmdypLI42wMJuLCT8qJtCFvRLDgH5vzDJN/L3idwqjkkNQWyrEAz86h1vUVkrTzU5X77TYZZe+5Mk24dxVwSuirykaFoSeSqLbgLOflwmyVkkxoU+alPZktoLQrBHzZQTBtQRb9VdZj5Gp6rNEHNXGMns/oZVfQXytzhxztyW6ydD6eoQ940Jk4clEwV8to2eug3SsgldahzttXtbGUFupmDfdCguEu/3UXmqf6mMR2vhS0aWRQbQ/hzSLvIzIXhdW2kNRmqxSPIM5Wlo4mDmpWGEfT/b5BfM976fVTFmK0V0V3Kln9+TAIHBzFe2yzPg/fb2itHOuminkuj5OVgN20YsotWuYhsFnC6JRhHKpWz3ZeAh4kHpCptVE35ORNZZV0909hytJ+996tZZG0Zlt1CTfcxrJdRzOYgd1vIa9PifNF34+e4rVt4OhVcUDT1ScBB2bIxSVuoNgzoqoxJt4ZSMYus10W/Ou1tfreEdK4JvVpHt6lD8fpolCxk04AzrCIpcps0kDMtuGkbDScJ1e+jXi4hnfbgOCUYsopszYGx5H8CHpqlHOqqvlDHaQW3/fuO3Jaq5TslWE0fT1QXrnp9G/lsGUNZAULdYybkNS1kSxOki1U0avqUW0mMdx6cbhVJkcZrwkrn0TVraPbT0DBBt1aElc0BXQdFfZbba7536bc7yPRrsMp9JIsl1Ks6VGVqi1Y+DV8dBg49dpEJqi7S5pEt9iFgrsH1mgZ+XVm3jqxZhGuWUW7YgYMHz4eyU4t99G0LtYkKiQHvROxDCNEBHwDrU7cvKAYQpAzdjB/o4WH290iP61PsdHZjeZ0CxaUEXQ1C2Tzc0Vk0Smd3D6GTfPg9CWzUF7XpIhqji/b3rM3nK2sjv33s/fGezqMROr0Zh0CM6DoVoVjhWRHj6xRFUtcUlgol2HjYKcRJOqnQrAv2LuMkpa5pFE4xuqKEdEKVJ6FB5SRI0wvLPLapEI9S5nZLvx1dUyoSp0Jn/Wjy4bk9tOkiHqOz6wqllset8Q1lojE6verQ6OZ0lU/A6pEelvEEbGNU6DzBbJ9TVMrQ7QKiDhXiEqWut2t3I7+d+u2+fXtEVwmJYvMGhI1idrwq83h/TrFoii7bY7o7i1DsBx5UNuttTDenEYoX2rRsNjOy274fexVKRE/p+uqMIvECzUxsWxq+djiBzfrcLe+jLMsGT//CdVVVaKoCRZn9yUd5sho6Xbh6Funw06hiIpv04TRfvXDzIZzuL10J34PnC5v40q08WuP2svd+C46XRC4dnivSkM4ZmLRa8+XNiedBKOZ1qvHh+/5COkVVAM/FwqTbZAJPViEuiY/bdyEbxuJsrWwia8rotrqhJbpFlP1aDV3dghVMUS1e2/brY3Dz4JQstAwbdnoNZTWHWreLVjEJWTBd+5FX+46iQoUvJmOmH0WFAg/e82o6IPqdJ0OdKWBt3ltO7tJvd5FZW8R0xk9Rt00NrcrI6SqcbgtVU7D0N9rM2iJ/lJNuA7WugWLJfGW/Fkj7sC0bSrmGnCr6+Y8C7fO382jOXWADYtklcO5U6Mkcqssbbt6InzscAtryEo0CTVfhucOlvUBvVChnsz8BsfQHZX6T3z+jHzPlPvbuuS4miobZ6uqMnKZpkN0hhk+Dtud6kBV194cwz4VTy8NqKLDKufkyo5YvIefVkM/X0fcQ7K2zrDoUq4zck38pKzJ84fDNKhN8Tx1FUd/F809Cfgt23UXayiH8LLeQxYYfH4GbJ5ZjWwZsOztntVhdGeqykhYF1v7y+w76MGDOoBgWSuYQ5VwRTaFcr49avoiWXkY5u82BWpv99OQu/XYXmaUifLeLupVH3c+inF+/iWazjApN27M9S/X4qj+9roOhloQ2tJEX+xw1bcf7sY9+OQ9bqaJmabuPCV8V5Cdr13GcOzztffjtV/zyy6/49ddf8K9//Bf++u8mrNbaIfsAbD58z4e4USx3cTFjCM/jp7kD6B4lqTeBJ54I0/p0ZlfVkExbq5v7j1L4Z890P3sXs+lrZ+SCWToxoyO4+PDEzbllQdfUYMZd003kqk24S0/sYm+dLF5s+P0fkS67SNebT7MnT3yVLOpODXrXwp9VBaphYZhrwakm5/00mctCdWyUmu60j/piX1gepeZ0jFgqMsh40rDRlLOwZh7izur8ANy8FkpWC4ZdQzY8gbpzGzYJDlErN4BcMZSvhnzTQVlp4C9/UqGoSZT9EpxW8dVO8bzUXfrtLjJBhs8vy/z0x39DsWug2qyH6i+EdpGZ144PNhCYuC78SQOl8hBmuQHHaaGWB+rZNCxnXS+bZuR3y8jXVVRr+Vfubd1QET79XQkc5YUKNd9EP+kCqgZN8eE6NeRzf8Xff/kZdbuJcjq/4an1u7adC3svArqFesvAJFiiE7M3fTi1KkqmCdfpBm9lvVfVfuxyZWTtFsROBlW8Ued7cPsNVEs5JPt19BvPM3O61UQ/KxwmF0OngWregGk10ao+Lf34fdSKZThyFpWaCa9po1bNIa82Uc/rgYMnm1U0bQv5vI6ffECS1eAt92LWgTWR1ywh9VG3HWi5LtLLT3LvqrhduHloFYtoJW30s2uWY/euvwfHyqE8yaHZTIeYeXBsC9W+hvMrC0m3gWq9iHxRQaOW3e9mvUu/3UUmaKuKXL0P0/fhTVx0GzZKSQNOw0F97vnuIrM3uB8moTfx8JtvoNQQS6vTZmtWHXZXQ84WD2W5kN08YfG7KFt1qNXu/GWrHwbYV2noblvz1ku9ZsNfuxAjIY/Y/hsyN5V3fx4lKXO38rJGZ92m7vVN4bNHILBJX+uLmm6Wjp7fr+hxvfzXP7uJ3z72/nCbISl6Qc+vTjzxuz+nyMrG+0W2waZ1sfF/4e2IRZmHuzOKSima7tV/pPZFjCKJCvVCG/pHd+cUl9a9CPFID+MxPQSyD3RzKq3dGD+tR4qut9RD1OojcnsQG/9j53QXfpdhdBW8UDF7wWSRKJF4uUW8pLLwwsmC0AN1KgmKRDN0M3uT5el6oA+xCX7wrIDHwQ1lYhIlNhX4lHYTv4Wi5z926be7yExtJvxSzryI+cE2mUe6O5Moyi9UzGnNDjbdB6f2dbnGvh6pc3lC0dObhReigjFE3L+fTWpWBH8fgcDr+uFqBY6yLLvW8Z3N/q5ZPl0r/4qTuqEBK3vrPLjDCWRN41nCV7B8P1ENuq4Ey4IzU3m/unzskvexd0XToHku3PAGe/FSg1iyEde2zITJugENHiZLacOUlEBm8pR/H83WBEnLghHKV8tWUUy6aDWXg13KUFQVipD1HLS6Mgxzee/VBA27CT9bRC4coyVciReO35ObU2/g55//hr/8IRT784//gb//9g/89U/fgnh2y1S2N0eEpxChbRSUWw3kZ3vtgkQ+uo0WfLOIvP6sAFnPo2zp6DeXYxJuL2n71V367S4yMoykDkyG2Gxmu8hsr+2PeFUTezgn7grX4CUoKPNtEs9s+mg0/olf/ud/44+zmJLfvuH3/+u/8dvP/4l/++kbtCLHE3zm9TGPjuDc+XDsEuqtPibBXdrHxKmi2vw5IBA1zP33fGxgqJkm9GFzMYin56DZBcz08x6fDcn59IcgMES/7wWbfd9y0epDNO2NK7GrvXuTyfN+UyMLU+2iuRDEdoJWsw8lmV58Y3Wpvl6/i6Gsw1hwIBaFAhlo0INlHxmyLLa7Lu+vne7tE/tj13989KtVNJUsrOWly2EdtqMgZ4WXHtfnsunse3Izq130er3Fv/sCTqQTXNz10G28Zl+Tj2Eti3QVKLWaKIY96KDxgr8cvB27+KAklkCney83aWATu83nd+m3u8j46HfFi3HGlofxXWQ21/RHvaKaWRhuE41u2BomcJwhFEM8uE0/z+OFgVJryVZ7PXQqKUixM9x0emiVgkiVPyrSz9Hu1cm83c+snzacLquIayt/0VO6eWFJZVvp68sTKcZ0m4lSJFGg286ABr17qmRiJImYPDyFvA3pUa9t0tf47pIKV7d03+7QYDCgXvuWKpk4SdEM3R5gH0dtzDtkvonfTvYuYuFBokQo+OPgKkWR6Cld3gnuHbq7TFE0Eo4P2aHriwrd3LWp0xsEMvfXF5SISnRy2Zkul3cqdHZeoZv7Dg1GIxoNenR/U6BUVAriaM26W0/EsBPxx+46NBo/0HjUodtCgiKR8LLqI40HAxqNxzTq3dP1RYqiUpwu7sNrlwL803Jc4jmO3jZ1fEhu6yos4vUtx7kLyW1alh3dZCgmRem0ckf37Ta1w3+dUaCnx/YFxaUYZSr31BuN6WE8oPb1OZ1EonR2u8w3VOiWZe1d+u0uMoPrczq7vKa7Ti+woUGvTbeXpxSTYnT2tG69i8xirXlZdrPdP9D9RZykWIYq9z0aDHrzvl+ZrfmvGS8W+RI9iq0dB2yrWs6Pf28nsFmf29PNrm6IQjy7vP17feGPNLi5oNNEnKKSRIBEkdgJpc4rdD+aDf3b8910dX15T9IPPbq5SFE8IpEUidJJ5pLu2FHYhPK7nN+kr8fONZ2nTigWebKPaPxN7OO7NOo7FrKJX1CFl+x9cEWpaJQyC0GLH6hzdUaJWIQkKUKxxBlV2uEb/YjuChlKxKIkSSIIuZDJUOGm9xz8dHxPlfNTOhF5BIHKoxRLnNLFdWcp8PGY2lfnlIpHKSJh2idPL+imFw6jOqKrlMhHokg0TolMYen6E2wR2DeyHIB5syI+JLd11d3Ludvy8AyQlLia75Ma3VfobDYOC12eZKhwO3hxT+smfrv0211kHjrXdHGaeOr/wjZidHJ6Tlf3U8dUoNpFZhEpO3eb9DblNKL7ywydRKV5378K9/2148USYXbuFoEc+dd2fb5c+Dchsu8co/h/Yw9I/upiv3d5r64gJ1ggwPpawPHqH8zv1ciCBMxtP26zVMxvRuJzfbPePpe+Xqrtofo8wp67l6rM15kAE2ACTIAJMAEmwASORYCdu2OR5XyZABNgAkyACTABJvAOBNi5ewfoXCQTYAJMgAkwASbABI5FgJ27Y5HlfJkAE2ACTIAJMAEm8A4E2Ll7B+hcJBNgAkyACTABJsAEjkWAnbtjkeV8mQATYAJMgAkwASbwDgTYuXsH6FwkE2ACTIAJMAEmwASOReDgOHfHqhjnywSYABNgAkyACTCBH5XAIXGEf3cotEMKf23Zhwb1e215LH8YAdYX8zuMwH6p2e724zZLxfxmJD7XN+vtc+nrpdoKfR7y4WXZQ+hxWibABJgAE2ACTIAJfDAC7Nx9MIVwdZgAE2ACTIAJMAEmcAgBdu4OocdpmQATYAJMgAkwASbwwQiwc/fBFMLVYQJMgAkwASbABJjAIQTYuTuEHqdlAkyACTABJsAEmMAHI8DO3QdTCFeHCTABJsAEmAATYAKHEGDn7hB6nJYJMAEmwASYABNgAh+MwFGdO3/YRDWfhqEpkL99wzdZRb51JAJeF7W8CU2RISsakrkqnMmRyuJs34bAxEHNerIP+RtkzYLzNjl//Vz2svcJnGoOSdEfZQWamUet621h5cMp6pDlJOzhk5hjQRV9ee2fjFzTDwR9V+g2i6SmQpZlyKoOM29v75NuHWnlG5SlQcIfNlBMG1BF3w7yqWFrtbe0CB+cm6i62yohm9SgyDIULYlctYXFocxDv1FCLqlDFWzFeJetouWua7iLpmVAkU3UFjNZJ7zl3AQ1U96g92/4ZlTRxy4yT0U86UFX5cA+VN2EVesjbI39kr6mPAPVmS2KrFr5NfYowzyssVs4fOZL22zhNTYVZhAeU4S9GkgXGxhOh4GwIB9/ZwIHBzHeVN9Jy4KZ/b/4129CQoIUiSLi+/CPonQX9VwaJS8Hu2nDkF20ykVks4DTLcHYVEk+/34E3DqyZhGuWUa5YQcPAPB8KO9Xo09U8n723q9mkbVlWHYLNd3HsF5GMZuD3G0hr60233dKsJo+1PAlo4RWJ4+Vbjy0kbOGMHQZwATNkoU68rBqRRiaCkwc2MUisjkZfcfCanEualYZQyUSLg2YNJAzLbhpGw0nCdXvo14uIZ324DglGKK4nT8fnRvgBeOmg2S1BqeuwR+2UC3lYE6a6NsmRHO9poVsaYJ0sYpGTZ8yKYnxzoPTrSI5YzJxUM3lYE+UIN3OmNYKqsjWHBhh7yuQ89As5VBXdWhQob4oIxJNnsbrPGqtOkwVcJ0qLCuNvNJHMze1OG/iIZq5RqNkhOovQwsZj+958OLnuK0v2pQibI4/zwResIWdbeo5x+BoWM0ibcso17toGgq8YRNlK4+0p6BfT/N4vsTru/6kAz4A1qce31ImCgIilCjcUm/8uF7ulWc3ltcpUFxK0NUglOHDHZ1Fo3R29xA6yYffk8BGfdGYbk4jFC+0ibWzWSMb+e1j74/3dB6N0OnNOFTgiK5TEYoV2qFzT4cPbbqIx+jsukKp5b61Iv1I7YsYRU5vKJz7stjj/TlFpVNaqMKT0Oj6lKKJCl2LfM7v50kHlROSTirUm58hosc2FeJRytyut57Py030C4liF21aGDEHFUpEUnQ9mkF4pIflpo+uKCHFqNCZyQzoKhGh+NkNDXoVSkgput6mnFmy6X85FPr1wuHomlKROBU6CzVeTLQs83hLGSlKF+1wmke6P4+QdHb31PZHus1E6ORyQfOL+RLR+DpFkdT1VrtbSfRFT2y0e9rFFnaxqWVwYvyQKL6ko4ebU5JiF7RmVFnOgH9vIbBZn1sShS4dZVnWbdho/QJETm007RwMdfYoeRy/deh04epZpPVQ/oqJbNKH0+yHTvLhhyDgNlDrGiiWTH6y20Mhe9l7vwXHSyKXDs9oaEjnDExaLSz2Eg9OyULLsGGnd5hL9ZqwGz6yxdziLN9S28Qsiy8rUJazdGvIlz0Ua0XoS3OCbt+FbBiLs++yiawpo9vqLkkvFbj08+Nzc9EfAroZnqkCoGeR1fpoOrNpM3mVoaJChS8mv58+OqxGH91GHmIydX56dvmNvvu1Grq6BWs+Xbia8aqMsAEfk0m4Vj4mHqCqs1lGD54HKNqysSzmPwmEFB5HFrEs/drFFnaxqaVsIfQoI+jXoUveVHFbx4KQOB8eicARnDsPTquP3yDBSGtwSlmYhg49mYZlO0t7R96mVe5wCGhiWSD8UaDpKjx3iLVbUcKifPxdCXhdB0MtCW1oI28a0DQNejKH6vpNQ9+1bp+hsH3s3XNdTBQNy6tVgr3sDhf2yHhiObZlwLazOw3Qw7qNlpqDld7wEOd7GLaqyJW60EslLIoNUcuX4RdrKK5ZY5XFzWMyWdiLJVwV3/ch2jRzd3bR28fnJvbPAWI5cvEjnDYfk+HmkczvO+jDgBl6wJU17bhOj9+CXXeRtnIIFbtU9TUychrFkg6nNO3zPiZw7BzKfRPVovmU/sm5U8IPI4tZi1+e60FW1NCy7aoMnwH2sYV1NrXIUkG2mIfSsJCrdTGBH+wXzVc95KvWZptYzIR/HYnAEZw7F0M32GgH187jf/2f/8bf//kv/Osf/4P/+x9pZKuLcwSHt8uH7/kQN4HlW4sipgjEbMHhhXAOb0hg4rrwJw2UykOY5QYcp4VaHqhn07Ac1tZ21PvZu3i6FtM9K/MgwbnpjTQo12uhZLVg2DVkt99Xp9X0u6jV+khaRSSXKy721snf8O2n3+NP2RqQq6O5sH8KGNoWyn4RtaXzs6ySuSxUx0ap6U77sT9Bt5ZHqTl1gHa3ls/AzUAuraNvl1AfPjl4Xh8Ny0Ld3Tb7NkSt3AByxd10NoN74PekYaMpZ2E97ZFbl90mGaPYQsvyUf13HaqiIV1TYXebyM2f0D1MPB9OyYCmihkiFXoyi2KjHxrPfYhZIrFPUddUiPFe003kqk24uxvGumrzOexmU7Jpo9VIwy3+GzSho2wLRqOL2i4z/kz5qASO4NzNbhS/4WcYuO494PFxhNuzGIDf8A+7xm9EHlWlHz9zMTPxm2+g1Kghb+rQNB2mVYed89Cwm6+ajfn4rf1MNfTQKhbRStqoZVfcwLUN8Zo2GpM0rHVvZCTLcPoD9Hod3NcsyM0cDNNGf3bjHdqwqj5K9c0vPclmFU1bRzev46fgrdskSv0siqJ+4m3StbX63iffjptRbqBuuigZv5++ZayL5XELOR1Q1m5v8eBYOZQnOdTt77mBvY+67UDLFZdmYsPsN8tMWmUUbRdGwYZdziHpN2DlSqG3qZMoN5to1OtoOl04rQbKpng51kS6NntdVkbWbqFZr6PRctAVD4klAxM7h2S+cZRVonDrvu7xK2zKbaBUasA3L2HbJWSNCWr5POy9X2f/ulS/e8tC++9efbh+w1+HCjHxMgXopBLaDNu+oBhAeMXG3uUKrS+P6P48SlJmthH3OVXnMk5S6prm+5CfL/HRdyCwSV+b9CI2R0snl4ub579DPT9qEZv47WPvD7cZkqJrNjnfn1NEytDtI9HD/TnFYud0F954P7oKXqiohF9WmgMb0VVqzQsA8+tLB+NrSkkROrsTG+kHdJWKUqLSC708IDbVRyky31QfTv9ID+MxPQR78B/mLx6EJWbHX4Lb4wONxw9TNo/3dBaZcZu1Unw/UKeSoEg0Qzdr9fMkO6jQySvG3U38wiWLl2NiIs8tg+tGmeAFixid3YYM7aFHlVTkxZdygrEjfknz90bClXo6npaboKstdVuT7NOf2kVv9KIt7GhTAa0eVU4kil+EX4x7oHbhhCLRM+J3GQ8zqZ30uaWII8zcqdA1KXBSxX6I1c/q8umqzOvO6IYGrOyt8+AOJ8Feg11Wl15XIksfQkALQmO4K0/WYh8VMNtQfUgJXzvtPvauaBo0z4W7FOvMFUvk4poMOPUGfv75b/jLH0Jx7P74H/j7b//AX//0DbJRxWzORBD2uzZqXR1WcRqi40XqqgFDFRvpJ8CwiXr3F/zjr3/GT/OYeT/h3//2C379r7/gp28iZl44RxmKqkIRey88B62uDMN8XZCjT8VNVuYvF/jdJrq+AXNhT6KPvi1C2ygotxrIb9z0Fmb4VseTYIbdzxZDy6jLeW+W8ZwmukoWxfByrmKgVM5BcZqYvzeynCUAw9CBlT2Yi4KybkCDJ8T48yoCr7SpYQvNoYF8MfxinAKzWkbab6HZfVXhLPzGBI7g3GkwswaEe/dzozydnvVdNGot/Cwqr4kB/m1boZkm9GFzMYin5wTGZaaTK3vx3rZ0zu21BFQzC8NtotGdrc+JHCZwnCEUQwzM/NlGYFd79yZii/PTx8jCVLtoLkT2nqDV7ENJpoO3Uc1qF71eb/HvvoAT6QQXd73gzctn3Xho2Q1MzOLujoXbR3+iIHDutTwa3aWyeh1cZyKInF6h0+uiOttbP2tD8O2jX62iqWRh7bh0PEv+ObkNUS834KctZOfwfQxrWaSrQKnVXPsiyqzNR/ke1mE7CnLWlmXgbTKyeH3XC73ZO61lELNOLL0vb56eN8JH1+kDurF1s77X72Io6xB+IH92JbCbTfmei/lLzrJ4EF/Vo9jn7vlr3orftSos9zYEtszqvXhp47ThQ5sKJ1KwNCtknv9EbKrQVPyLJSwKbCyPxnSbiVIkUaDbzoAGvXuqZGIkxQu0LfzSYu78660JbNbXA91fxEmKZahy36PBoEd3lymKRhIUXsl/6/p8tvw289vB3kUsPEiUCAV/HFylKBI9pcu7Dg0GnTnzkMgqIrGEti7OXXB+QxzJx3u6zFxQ5bZNncGIRqMBde6v6fwkQpFEhXrh8GZLJbYvogtx7ogeaTwY0Gg8plHvnq4vUhSV4nRxv3kc+bTcAhZjGgxGNB6PaNC+ocvTWNBPbkNLjKObDMWkKJ1W7ui+3aZ2+K8zCi1zP8F9cSluUQmb+Qm5aUxDKVGhzSvBL8gEMUglip9dU3swpofxiHr3V5SJTZf4AvMY3FDh8ppu7zvUG4gxvU03hVOKSXE6v58F+evQ9UWFbu7a1OkNApu+v76gRFSik8vOKofFZn65X9v19tTcDbawk00FsTIRWjof0fWp6NMXdNMZ0PhB9NE7ujyNUkTEptzSz78c/CM0aCd9bil3QxTiLSlCl7YWPm4HA3E8GiFJilDsJEOF28FBHW5reQ89urlIUTwikRSJ0knmku5CA2Ko2nz4nQhs1ReN6P4yQydRaWofiTO6am++YX+nKn+oYrbye8neB1eUikYpsxAx+IE6V2eUiD31ycQZVV5ivsG5m+59KmzY+zSiu8szSsWjFJHEPluJovEEZQo31JvdlzeQXnXuxL6+CEmQKBKNUyJToJsXMvm83MQ2OhEAXgqYRWIndHpxTYsqmu43FG1c9yclrlb3GG+4oW9QQZDvpms0vqFMZDkY9pL0DjKPg1sqZBIUi4hJAIkisQSdVe6f6z5uU+UsQcH9AyApEqOT04ulMWJEd4UMJWJRkgI7i1AskaHCTe+HDI6+1e5nKlprC7vaVIcuTyIUO79/5huMQ6d0IsYUSCRF45Q6v1qy2Vnh/P0aAjvpc0uG38S1fecAxf8veUDyVxf7vct7dQU5wQIB1tcCjlf/YH6vRhYkYF3F2jYAACAASURBVG77cZulYn4zEp/rm/X2ufT1Um0P1ecR9ty9VGW+zgSYABNgAkyACTABJnAsAuzcHYss58sEmAATYAJMgAkwgXcgwM7dO0DnIpkAE2ACTIAJMAEmcCwC7NwdiyznywSYABNgAkyACTCBdyDAzt07QOcimQATYAJMgAkwASZwLALs3B2LLOfLBJgAE2ACTIAJMIF3IMDO3TtA5yKZABNgAkyACTABJnAsAgfHuTtWxThfJsAEmAATYAJMgAn8qAQOiSP8u0OhHVL4a8s+NKjfa8tj+cMIsL6Y32EE9kvNdrcft1kq5jcj8bm+WW+fS18v1Vbo85APL8seQo/TMgEmwASYABNgAkzggxFg5+6DKYSrwwSYABNgAkyACTCBQwiwc3cIPU7LBJgAE2ACTIAJMIEPRoCduw+mEK4OE2ACTIAJMAEmwAQOIcDO3SH0OC0TYAJMgAkwASbABD4YAXbuPphCuDpMgAkwASbABJgAEziEADt3h9DjtEyACTABJsAEmAAT+GAE3t658+pIy98gYrSs/ZOTsN0jUPC6qOVNaIoMWdGQzFXhTI5QDmd5IIEJaqa83jaEzRhV9A8s4YdIvpe9T+BUc0hqCmRZgWbmUet6W3D5cIo6ZNFnh5vEtst43TqK2SR0VYH8TYaaa+C5RBd2co0taBaceXEe+o0SckkdqvzUt7NVtPYdQ96TWysPdWVclGHWQgOV76JVzcPUVSiyDEU1kC42MPTnQAB/iGY1j7ShBTKyosJIW6j3n8kKaX/YQDFtQBVjoqxAN3OwDxkU9ylX1WHma1hvZj6G9Rx0WUauGW5gqK2zQ7+PqrAVrYju7Fzw7cNtlpA2prxU3YTVGOKF3BZy+Po/dulDu/TFTaQ8DEUfNfXA1r7JCszavh10Uxl8/tUE6IAPgNXUDzd0KoHEtbV/0indjFeT7XJmbXlBwhHdnEYokrigm3aPep07qpzGKJKoUG+XjFnmKAQ26Ws86FCns/x3T5epCEXP7ujhKLX5fJlu4ke0n733KgmKRFN0eduhXq9Nt4UURaOndDNaz+axXaB4LEYxKUFXg9fLjO/OKR6JU6ZyS+3BiMbjEQ1GYe326DIuUarSXrSH3ogen4p7uDujWCxFF1d31O4NaNC5pctUlKSTS+rMhJaq9lG5Pd5mSIqf0+2S7Q/m4+EjdQpxiibOqXJ7T53BgHr3FTqNSRQ7v5/3i9H1KcVTF3QlZAIm93SViZEUzdDtLK+HOzqPSRQ/v6HOaEzjUY/uLlMUjaQ26nKGcRO/ncod31ImGqGT85tnfc3G4gV9jeiukKBoLE7xiERndwsXZ1V5+n4kYbuxWIykeIE6oauBjUoxylwJFj1q35zTSSRGZ3dhOwsl+MKHm/S2Wx96uS+uR/dA7cIJRWKnVLhpU0/Y2nhEo/E2fa7Pic8uEtikz0Wpzb/WeGebhZevbCr88fGBHh7Cf2O6PYsGzl7k9IZm489yfi/93lQedQoUX74BPdzRWTT6Q3bylzh+r+sb9bWuAqNrSkXiVNh0x16X5ouf28hvH3t/vKfzaIROF56sRnSdilCs0F4l+dCmi3iMzq4rlFruWzPpbTKi/8XETXZbb2/TRTRGF2uKnxVB9EgPy/fp0RUlpBgVwnf55wTBOBP6+Xz4ztzG1ymKpK63j39i7HyucXD0cHNKUuSMtvo/wUN15NlJap9TVMrQ7cI9tkMF4Uxfb9MJbea3VK+nytGp9FzuoHJC0snSQ/VjmwrxKGVuZy17pM5lnCInF3Q3alMhtt25e+xVKBE9peurM4osOHfj4KE+en4/fxgQdeo91WHD88i6VnyJcxvHi5360C59cRXTo+hTQjcbHhBXU/CZXQls1uduObz9siwQLAEoioL5n99CvfULgCjSVhbqq+cXtycYOl24ehZpPSSnmMgmfThNXuQLUfmwh/1aDV3dgpWUP2wdP0rF9rL3fguOl0QuHe59GtI5A5NWa2kp3INTstAybNhpZUOzt8t4zRpaioVyNlzeUla+B88X48TS+YWf8up1RYUKH94r197em9vE8yAas725q9cVVYXs+9uXGj1xXbB86j+KCgUevNCKLwRvT4aqbq3BAv0XfyyV6/ZdyIYBI5xQNpE1ZXRb3ac2yEiWWuh3a8hq2N4uvw/bsqGUa8ipPvywzv0uWl3AzJoIjxpGOg192Np/6T5c9y9xvEMf2qkvLsPw4dQa8LMl5LXla/z7vQkcxblbbtSwXoPzK4B4DsWNN4vlVLv/dodDQNOxaF8KNF2F5w7Bq/+7s3wXSb8Fu+4ibeUQ9s/fpS6foNB97N1zXUwUDdqSr6VpGmR3uLCny3NKsFoGbHvzg9hLMl2nD9nQ4dUtpA0dmqYjmS2iEd485nnwoOC1vobfd9CHAfOVxvLe3DzXg9gfF3ZEdjG3vtOHrydhrE3oY9JvopgvY2iWUDSfcjQslMwhyrkimoK510ctX0RLL6OcXZvRLlUJyawvV1Zk+JNJaF+lSCKcMh/CBue7AoUtvlgNH/1yHrZSRc3SVrlNXLi+Bm05I82AhiGGPPCH9LV4uNKH9uqLQzhdH0ZSRrOYRVIXujCQtmpY2v65WDj/+i4Eju/c+Q7s2j/wGySc5C28/cSMD9/zIQaV5bFCzBzC87Y/GX4XzFzINgKTho2mnIWVW/I8tiX6Ya/tZ+/+plmjYCZJzOg8AfVaKFktGHYNGyfdXpSZwHU9+E4JxZaOYr0Fp1WHpTiw0nk0Z7NJ3gSemJlJ69BUBYqqIZm2XnjJY4hauQHkipvrt9Y23pubD0/cQFsWdE0NVjU03USu2oQbno1arvukjnJ9gnQpv/jg4zeRC15c+wl/+HMeLaWEZsMKyWjINx2UlQb+8icVippE2S/BaRVDMsuF7fD7hXKTuSxUx0ap6U7HXX+Cbi2PUnNqYNuauly63y0jX1dRreWXHtyfJL0JfMirDwfBCyTCpl9T2nLpX/n3mj60T1/0Xbiuj361iIaah9100GqUoPdLMHM1nlR5ZxP63bHLF8szjZ8BSCaK+Vc+ah+7cpz/ByDQR912oOW6SC975x+gdj9WFTy0ikW0kjb62U1Ld7vJiOUzX7PQaBSfbswa8rUa+oYJu+kia2mAbqHeMjCR1eAtO3/Sh1OromSacJ1u8HbkIn8PjpVDeZJDs5nevry5mPDIv3ZhIiNrtyB2iajibWXfg9tvoFrKIdmvo9/IrW5X8buoZovomzV0lx985DTs/gBl38fE7aJZq8I0HNSc5tMSmQfHtlDtazi/spB0G6jWi8gXFTRq2fXO0i6UXihXNqto2hbyeR0/+YAkq0HkgmLWgTWRd9eZ30XZqkOtdnnJbxe97CyzoQ+9ui+KCVkx8/4blGwNjZLxNLmiwa5P0DVs1PoWqgvr8ztXkgXfgMCRnTsX9VoTYkU2mrVe+aS9a+tEeAQlmL0Tz2lh/0A8KYs9LuFzu+bKct+HgN+yURsmUWryKLAb8f3sXfQRMT03m6Cbl/W0HBNcbhVhOUnY3WzoJjyd/ZjNgXg7yMx6oZ40F50IebqU2uiL9TKxiUKE50g/zyTpOgwzCSR1VGsOysl0qO966FbTyDY12E4N5ibfc96w5YP35RbURk0inX6ul24kYaoe9KyNhptDMbyvxB+ils2iKpfg1Nc4fmLGStcDh1A3jGDfmWoYKFcd5GsmvKaFnC2j7LRg6WIEzCNv1ZFL55Cr9tEt7fugvb1coVPDaqBv+fAmYvwVIUo81NMeVE0L2dUzh9UjH92yhbpaRTe0mWtmg8GUoGhSsK/Qhyhm4SP2AQZ7OXnkX+CCbX3oNX1xlqtYLYsimZ45dk/ndQOG4mIotgOs30swy4C/j0jguMuy3Rpqf/8NQAxZ63hP2rqhASt76zy4wwlkTVt9Ij4iUM76NQQmaNhN+NkicuEb22uy+AFl97F3RdOgeS7c2ZLoEzfXdeGLazLg1Bv4+ee/4S9/CMWo/ON/4O+//QN//dM3yEYV/98OMkOowT6oyUQsm4U/05cCZHnbTVeDrivBEuZzWh99O4usraDcamDfBYD35LYpTKCsi/1hHiYLenFRz6VR8vJoNks73h91GLqMKXMf3UYLvllEPnDspjqQ9TzKlo5+s/WGS2bhcsO6FjH6hGMHwHPQ6sowzF0f4PpoNP6JX/7nf+OPobiAv/9f/43ffv5P/NtP36AVHUDVoSnTpcFwyXD7GEKDuC3wZ0Zgnz60ri/O8ps616oqbHfZuxb9XMRWDMny4XcncETnzkOrVse/RJNOLFjm8TStmSb0YXPx7SjPQVO8SZVOhp7+vztfLnAbgWEdtqMgd0THf1vxn/XarvbuhZ0rIwtT7aK5EMR2glazDyWZDt5uNKtd9Hq9xb/7Ak6kE1zc9dBt5PH/7iAjtr4n00n4rTpa4XE/eLtRhpHcNms0RL/vQbzoMZ2c8zGsZZGuAqVWE8UDZgLek9smP8PrdzGUhYM0s0YXjZyJolh6blVfMUPZhzP0g9kxMZ8SOND+8n7j2WzaW65mhMudtSH8LfZkVdFUsrA2LvWH5cWxgVJryQ57PXQqKUixM9x0emiVkoCcRDoJdJvOwkPEsNWCq5kwN0FfLu7L/963Dy33RbES62Iyf+pKImsqcOpNhJ9N/G4LXU9H8oC++uVV8j0auFvElPVSW+OwjG/oNCICGYu4Sm8TBGdzeWO6zUQpkijQbWdAg949VURQTxETaSHO0/p28NnjENisL1HeI7UvYiQlKvSjxaPalfZmfjvYu4g/BYkSoejDg6sURaKndHnXocGg8xTUdnOA4qCeIv7gpjh3s4ask3ns0OWJRNHUJd099ckg0G68QO2nPjm+u6TC1S3dt0V9BtRr31IlE58G430aMkY3GYpJUTqt3NF9u03t8F/nOdjxrCri+2Ny69D1RYVu7trTwMODDt1fX1AiKtHJZecpTtuY7s7jJEVSVLi9X2xru02dIAD0mG4vzqjwFNR5NBrRQARtD7g9xxt7bF9QXAT3rdwHgWUfxgNqX4sAv1E6m0c6DlN7Pl7Pb7dyRb8eDwY0Go9p1Lun64sURaU4Xdxviq3XposX4tzNahYEgY4tBTHuXAZBi0UQ495gQO2bi6CNp5sic88y+4Lf6/VGtEsf2qUvUhArE7QQq3Yg4pNGKHFxQ+3BgAbtazo/iVDs7G57PMcvyP+tm7RJn7uWc5QgxqLwIJil+F8qIhmax67ctVYb5LY29qFHNxepINq5FInSSeaS7t7Gp9xQGz79EoGt+hrfUCayHFT3pRx/rOtb+b1k74MrSkWjlFkIWvxAnaszSsQiJEkRiiXOqNLedNN9Yr3OcVtWwyaZcZuuzhIUi0gkRWJBn7wP9cnHzjWdp06C6+IhMBKNU+q8Qvej2RPZA92cSoGzJlgs/0mJKwplN6/Vx+Qm/keGDCViUZLE/+AT8M9Q4aYXClp8T+fBA/FqW0Wb4kHU5kfq3RQok4hTVBJsnridVehuMOM2RTG6r9DZTE6Ud5Khwu1gIeDvHFroYD2/Xcsd0VUqQtJTvRKZAt30ZsGLQ4XMDw9z7kQ24/tLypxEKSJJFImn6Py6E2I6L+jLH6zX22596OW+KPCJB7bIwv+WIs4+9EQ/jgf8pWicTgu3tGSKX579MRq4Xp+7l/RNiO47Qyj+79gDkr+62O9d3qsryAkWCLC+FnC8+gfzezWyIAFz24/bLBXzm5H4XN+st8+lr5dqe6g+j7jn7qWq83UmwASYABNgAkyACTCBtybAzt1bE+X8mAATYAJMgAkwASbwjgTYuXtH+Fw0E2ACTIAJMAEmwATemgA7d29NlPNjAkyACTABJsAEmMA7EmDn7h3hc9FMgAkwASbABJgAE3hrAuzcvTVRzo8JMAEmwASYABNgAu9IgJ27d4TPRTMBJsAEmAATYAJM4K0JHBzn7q0rxPkxASbABJgAE2ACTOBHJ3BIHOHfHQrvkMJfW/ahQf1eWx7LH0aA9cX8DiOwX2q2u/24zVIxvxmJz/XNevtc+nqptkKfh3x4WfYQepyWCTABJsAEmAATYAIfjAA7dx9MIVwdJsAEmAATYAJMgAkcQoCdu0PocVomwASYABNgAkyACXwwAuzcfTCFcHWYABNgAkyACTABJnAIAXbuDqHHaZkAE2ACTIAJMAEm8MEIsHP3wRTC1WECTIAJMAEmwASYwCEE2Lk7hB6nZQJMgAkwASbABJjAByNwNOdu0q0hb+pQFRmyrEBLZlFqDOEfC4DXRS1vQhPlKRqSuSqcybEK43wPJeAPGyimjbl96GYONitsd6x72fsETjWHpKZM+6SZR63rbSnTh1PUIctJ2MNnsUm3jmIuCV0V+chQtCRy1RbcZxEAPtxmCdmkBkV+6pPZElpzoQlqpgwRy2ntn1FFf5bfXm2dJV763iuvt+G2WJP1bOE1kJVXmci55vPY6Q/RrOaRNmZsVRhpC/V+WJce+o0Sckkd6px/NcR/sTY7/dqpXGChb6s6zHwNK2bm9VGzTOiqsA1R/+JS/YHAzrLJ6Zgu7iEvjhEbmO7UuK8stIstuLCTa/qjZsF5EY2HobC1p/v9N1mBWZt39BdTs8CRCNABHwBrUz/2LulEAonrUixOJ7FIcAxEKXM7Xptml5ObyiMa0c1phCKJC7pp96jXuaPKaYwiiQr1dsmYZY5CYKO+Hu7oPCZR/PyGOqMxjUc9urtMUTSSoqvBUaryKTPdyG9Pe+9VEhSJpujytkO9XptuCymKRk/pZrQez2O7QPFYjGJS4lkvj226ODmhzOU13bU7NBj0qH1zQYmIRCeXz73tsVOguBSjzFWbBuMxjQf3dJWJkRS/pM5TceNBhzqd5b97ukxFKHp2Rw+B3Ov79ofktoR4LVshM7qmlJSgwv0Sl8GUxlTklOKpC7q6vadOb0CDzhPbaIZmw+vD3RnFYim6uLqjdiBzS5epKEknl9R5XKrM0s9N/EbXL5dL41vKRCN0cn7zXO5sLJ6XO6AroeNUgW7bPRr02nRTSAS2eD2zxfENnUZjdFoQdvYkc3FCkS1jxEamS+37qj836W03W+jRZVyiVKW92Cd7I5qrbS24B2oXTigSO6XCTZt6Yjwfj2g03p5qbVZ8coHAJn0uCG35sd4725IgfGlT4b3L+NSxE85VoOMx3WamDp6UuX3BWMIlLB5vKo+CG0noBiSSPdzRWTRKZ3fPg+Jibvzr2AQ26qt9TlEpQ7cL/b9DBTG4XO/v/B+7Pd87/4389rH3x3s6j0bo9CbMd0TXqQjFCu3Vpj206SIeo7PrSuBsvOR0dwpxkk4qNPPNxRggpa5pdq8OChhdUUI6ocpMaLXUqXMTiVNh5oHs0dYPz20bW/FgHMnQ3ULfWAdq6dzDDZ1KETqbJ3ykh+WhL+Afo8LMu17KYvZzI7+ZQPh7qdxB5SSwg2c3n4ge21SIiwf7pwp1ChSTUrTY1R/o7ixKsYv2/P7w8LAMYTpGJNYZ0Dam4fp+4ePNetvFFtp0EY3RxZqhYBuy4CEuekpzp3ybMF97FYHN+twtm6Msy8qKAknMNIo1WFkcBP8Ec4+Korz5HOTQ6cLVs0jroawVE9mkD6c5X9wJXeTDdyWgqFDgwQsvm/sePE+Gqr69fbxrW49Q+F723m/B8ZLIpdVQjTSkcwYmrdbzEmhw1YNTstAybNjpXfThw/d9QFEwk1aEHj0X4YVCTCbwZBXbVNyv1dDVLVjJ6ZixV1tDLQwf7pXXm3N7ga3nBYyU5yEz3ITNx54PHwqUeUJZqGPxo6hQ4cN7y70xS+W6fReyYcAIlyybyJoyuq1ucEvwhkNMNANG2BShIJ0z4TnNuS0+t2WWmQpNmNVKA15gOkv+w37vYAti/PWF/bwGkg+n1oCfLSGvvSYdy34PAkdx7vS8hXQU+O2fZWTTRZTyaVj//SsQSaBYNEOu3ts00R0OAU3Hon0p0HQVnjtc2gv0NmVyLgcQMCyUzCHKuSKaQx8Q+2/yRbT0MsrZ197VDqjHJ026j717rouJokFbuKECmqZBdocQaph9PKcEq2XAtrNYEp+JPH97LpxaHlZDgVXOzeW1fAk5r4Z8vg6xFUzsw7KsOhSrjNymTP0W7LqLtJXD7Dltn7Y+V27xaJ+83prbS2x94dyFnOTFFqz75WPSb6KYL2NollA018lMz/l9B30YMGdwN4vucGV9ubIiwxdO/EIOU+dfsBTnxcO/LNoZsjkhHjwgCDtdOj/PyuvCGSowkosNeInpPD0fzAms2ILQB5StD17zxPODIZyuDyMpo1nMIqlr0DQDaasW9Pm5GB+8C4GjOHdQ82i0KkhFfsPP//Of+D9/+wd+jaRQcRyUjLe+efvwPR9iUFnOOZgl9LznjcjvgpgLXSWgId90UFYa+MufVChqEmW/BKdVnN/UV9PwmSmB/exdOA3hmbU5zcCRELOmT2e8FkpWC4ZdQ3aTEwagXzUgi5chfv9HpMsu0vUmqmbosV/Jou7UoHct/FlVoBoWhrkWnGpypZ/O6jJp2GjKWVhz72+/ts7yW/zeL6835bYDW1Ge79aR0zWoigJV3Czz9urLYX4TueDFi5/whz/n0VJKaDasLf1niFq5AeSKW/W6yGzNrxfKTeayUB0bpaY7HXf9Cbq1PErNqYEJv01OZmGiiXLZeXLkfLiOjXzZwa9PCz6rJfvolqtoaXkU06GRfgemq3n96GfW2II3gef3Yad1aKoCRdWQTFvbX7jyXbiuj361iIaah9100GqUoPdLMHM1nlR5ZzM7jnPnOSgXbfxd9NRIDNEIgF//jqpVQiu8FPfOjefi34uA9/+3d/YwyitZn/8/0kj2jfCNYCJ8IzwRTARvBFmzEVxppWYj2AgymKh7ss4gg42aDEZaqdkINoKN8EQwEWwEG8GNYKL2G+EnOqsyXzZgmobm6Y/nILUo21V1qn7nlH0oV52GXsmhNFSRLldQysUg6wVkCi2+IbyXSiy5BjqFAjqRCqpJm6N2oE1aroXhaIRBr416QYOeCSF2r29nbMwhqoUH6HISxWoJubgPw1IKmbrbjvkh6hUdaqoA+7P7gOgPeOoUbqfkAZRUFZ1WA/VGB3pfR6uSgzouIR7LobN2wAUBOY7KcITRYIBus4S4WUEslET94CZFA3ouhYd5CvVKfPPq/CyQL8iVYyW0Khr6GQ2/iF26vgjuh0kUhD2JndVCqC+FeuMeSiuJP1vRFHyIlebI5GKQZAWbN8u2Bs4bGaTqMh7qD1i9sQdwGlNbNZyEiy1oOdQ7DdTrDXT0PvRGCSmlj/tYDPd9l6lU8SoX36Ekq2jcL2futEgKlfoDNL2CKq+Iel97O21p3uFchxf8Laid9q82VOSpK9ZvT9qUDy83VHhuamRf0n245sNnD8sjaqe9JCWam4W469K9Q4u61xf5++oE3PQldm+JXZqPo+2C6cWoRgm/RAcXS1+9pR9TgBu/c+z9+SlBkjdLe+ul22nyrDa3PLfT5PenqWkfoJOytaHi0Bp2OzVLp5tF8gvqZle71bcqpkkzTQHJtlnCVsFCyBblHTswzhvbH5HbJWzp+YkSHmm7IcHGbZscUTEoWRsStudE6pl61i7pBNWObWSxFXLjZ8tiS7rJXdDzbEbLPRHPVLs51DaixfM6D9GoGHZsylkLmbWzFPQEKO0wTKKLmK4r/0LfL+vttbYwoXJYIm+6vfdstbAJu5S8BzZhiM0Zwl5tg/8Lcf5RXXlZn8dbcoWZuyE6+h8AJCTvS4iJVztqHJVKBgExgae3oNt/gb6Bb6uFVGBvbZ2B6XgOWVU364DeQBRXcTEBE/1GB2asgIy2fb0iaxk85DQMW7vx0i4W+OUqOMfeFVWFakwx3Zk5n06nMMU1GdDrDfzxxz/w+59tcdZ++xv++f1f+PtfvkEOlWALd+fgqmghqJiv6h+i1ZkjksvBvgpDTZZQiEzRae3WMkej0oKZLCDlXDiLc/rqaJjt4Jy63orb/7yALRQNmg+Yz4/dODWENBnz+dy2DMXEsJJEsqLgodNAxrlUzUbmkuQhuaI+GYrPt5yFM3R0+jJCMcc2C0uoiHG3nKmbQ+8M4YtEHGunDb2AZKoDrdpBfWedwCX2ekmPP2fZc2xBhaYpMNyWNokNOj7jgF2KzT0ivu3nJPVVWn0F526t1O8Y68PNjUYsZraeKy7T7pcAVWMxaOOWM0CnoaPVB2Jx9zU+l8jksucSEPYhA+buWkgThnh4icXW51b9k5Q71d4N+4M+lETM10fLESh6jk5rCCUSt3Y3xkp9DAYD5187j6AURLY5QL+RcTx47biNYR9jqJYTIh7sQsXioeD8LNf2ifWxjs+4joquIJXbf2V4al8d9bkcnFrXNbj91wvYYt7HcK5AEx6e62cIfWzCJzbIWHlMjKtJxEvAfaeFgt3Ldq3jnAu7cnfrEGuySmgpSeSOvOo39AdU+hpSYonGqgqjX0I81YKvoqOx6/UDuMRed1v5tY/PtYUxhkPD2nS1XqRhGvYNLxEkYwr0emv5bF9BNPsd9A0NkavZ3NfW1pv17vjE3vGrbtOGo3KYPBBBjCXy+IMUDHhJWh0H73qHp3iPi7KuuskjEnH0vOQJ5+mpN6LRoE1FK2Bq/sWAnSeI5SxnEnDT16KbXQa4LbatoJfPsxF1H9MU9Hjpdh2F9UyZX6mYG7+T7F3Eh4NEYVuAulE5Sh7vDd01RfDh3ipw9E58yF2Aq6C6m2p6RbpNF6nW7tFoMqHJaEDtWp6iXokC+W2MsoGIdyYCJjd7NJk902zSo6d82ApC63z1unyFK4W3MfKcTXj92P6Q3JydWh7tsqUFdctZKtaa1O0NrADRvWaZboMe8kTLqxiCM3rK3lJ+FZx4MpnQSARtTwRIssUbm9QS5Je8dFNsUrvbpa79r3c8MO1hfqfJJVrQbDSiyWxGJw6UbAAAIABJREFUk0GbHrNR8koByrbt7/qJnifLPCKQdbMsxr6Hwne9VeBqosWgvLSp28f99ncH7kt79pgeAv81zx3WG9EptjBr3lG+/ERtKzD5iAbdp5VNJehpvVTCipUJciytGj1SVOguW6PuaESj7iOlgx7y3zbddfQ18b95r9z0eaqgqwQxFus8BrU8JcJ+8kgSQfKQP3hD2dp28J7aQHu+o519HlAtG6WARyLJ46Vg4o6aa6O0V8LpH0bgmL4m7SLdhgPk3dhHgvJPo7Md/x/WqR8o6Bg/esneR+Lh6KWEI2jxM/XKtxT2e0gSYzJ8S0VrUeyRTu0+LGdtKqZvrP86Y/1gk7zkD99Q9rG3czOfUbecpmjASx4JyzF5k6XaYCey7qxGCc9ucOWd9rzU153sH5LbThutw122RDSqZekmKO6bIEgSeQNhur17ou3y1MXq3roaO+IHtDdA0dsiNTeZlmvcBIdDf1K47AwuvdO2w/xOkSsqmlj/fUJatSucyO/rnIh6d0HrB7+4Vweit3S3M/Yn5fBqQuBAH6QbWsdD3mn65j98bH6M7GX4uicO6+00W1j0HikdDZLfIy0nZYRNpYvUntjXzfXoTjhu6fbGCRc0nweibMB61kveAN3k7fb6dXlfu2eH9Xm61G8i67nTgOJ/Ql5Q/NVif7S8VzeQCzgIsL4cOF59wPxejcwqwNzO47YuxfzWJD7XN+vtc+nrpdZeqs8rrLl7qcl8nQkwASbABJgAE2ACTOBaBNi5uxZZrpcJMAEmwASYABNgAu9AgJ27d4DOIpkAE2ACTIAJMAEmcC0C7NxdiyzXywSYABNgAkyACTCBdyDAzt07QGeRTIAJMAEmwASYABO4FgF27q5FlutlAkyACTABJsAEmMA7EGDn7h2gs0gmwASYABNgAkyACVyLwMVx7q7VMK6XCTABJsAEmAATYAI/K4FL4gj/6VJolwh/rexLg/q9Vh7nv4wA64v5XUbgvNJsd+dxW5difmsSn+ub9fa59PVSa4U+L/nwa9lL6HFZJsAEmAATYAJMgAl8MALs3H0whXBzmAATYAJMgAkwASZwCQF27i6hx2WZABNgAkyACTABJvDBCLBz98EUws1hAkyACTABJsAEmMAlBNi5u4Qel2UCTIAJMAEmwASYwAcjwM7dB1MIN4cJMAEmwASYABNgApcQYOfuEnpclgkwASbABJgAE2ACH4zA1Zy7uV5BJqbBJ8uQfRoiqRJaU/N63Tf6qGZiUBUZsqJa8vT59cRxzZcRMMcNFOIh+IS+fBpimSr6xmV1/lSlz7L3OfRSChFVgSwrUGMZVI9CN6EXNMhyBJXxlu68X0chFYHmE/XIUNQIUqUOptssm5Qh8iZXeb/J8KUasKvZYQeyAi2WQsU+cM0xWqUM4iEViriXKD6E4jnUh/ZaNuJeTlyLWycD37dvELGptn8yYtXtTeg13DDXcR/zQQ6VMNzr1RSViGyTs5Kp5qAfyNvKhaDIMdiaspfrrBPTOuLKNyiZzrb4SfoyMGzcIxULLe/XwhZDSRQaY9ifEBavZGSbZ9c2hNQTuG8b9xOnzrD7k/j/xEg/fNfpgg+Ag6UXvTwFJZC47vjzJuhpcrDISSfd5BFNqHbjIU84S7XugAa9JhVv/OQJF2lwUs2c6RoEXPU1e6KE10PBdI26gxGNek90t9bX4hot+Zx1uvI7094HxTB5vFG6e+rRYNClp3yUvN4bqrmMyUU3TwG/n/xSmMqjFcNFl7LBICXuHqnZ7dFoNKBuLUthj0TBO+domzXTFPAEKFF8ou5oQrPZhEaT560ynpuU9ksUSNeoN5nRbDKg5l2UvJ7oRt7k8YYC0SyVn9rUs2ylTeWEnyRxL5ltq7Kn3oPb4ilBUiBNT70e9Wx/o3UbX8HteVCmhN9DgYCfpOChe9iA7gISRYtdh6zeYEKO4TPrUjHqJW8gQF4pSo/rtthhHUi787NnntDjjZ/8fg950u3NhZP0NShSOHBD+ccn6vYGNBr1qHl3Q17JT9nuqgezGt14/XSTF3Y2oNGgS7VskDw22xBCX+S+adnXT7jr7Yzn44n8vz7V9+uhuz5Pa9Nh7+y0spbjtp91RrUbybomhe+o+0y0mDxROrB09PzZrvMGtF+B6xnXzvbyFLA/gEQNz0269Xrptml7mLjWzBeuQcBNX6NicP+htehSPuClxBPra60LN350jr0v2pT2euimZn/CT+gx6iF/vrsWuf1+7lI24KfbxyJFd8fWNtcm1csHLJ2ufUBr/Pn9dNu0y9tkXya6afJKCXpyeCQ9ygvH5Zgn8lyjG8lDt01HwU3l78Ft9hglT/SRjvR20z57Yo/brEYJ4dSUezSp3eyPE6twl7Je4QjZa9pNj6gc9lDgtkYj4Uy9sXMnnDhvuEiPWb/DudtthXX8gr6WZSZUDkvkz/c2VTw/7+p3aRvh4sbK6FzuGyFfKPGmdi8eoSfw/0L4PlxXXPV5Ykuv8Fp2jP7wOwAJkUwBMQWQ1RRKhSgkAH90WgdeM1w2wTnW+5hqScQ1Wz1KDMmICb21/1LDlouT70BgOpxCDoUQssuWY0jGZPQ7fcerGXsWTi8JnGXvww50I4JU3GfDqCKeCmHe6eyMSQP6fQ6dUAWVuGLL75Y0YZomoChY5zZaVXSUHB6Sdnk75RUfFBgwtm8uAdOAYcjw+dY17ZQRh4YJEwoURT5w0f3UNbnNDcPRf/dW2K/sc4MvhWq/j04hAlkwPfQRjEzR/0MX1+c05BpD9BsZaDLedkxNq8g8GChUC9BOqfkkfRmYC4S+rU739euDqgCGseVyHvc1o5/j+yy7hzDnrS6WpPb5/xwEP2cvr+DciRvWEoZYj7P+KOs70XyK6ZnLZdZ17X5Px2NA1aA6LihQNR+M6fjgWiBHVj74oQRkRYY5nzvWXonHj3AQjOl05/wPbdqnEHaOvQuuc0WFuuNrqaoKeTrGePu8hKHfI9cJoVJJYif7Ph9jCr2aQa6hIPeQ2uTv60PIIQ1GPYd4SIOqaogkC2jYBYVyuI+N8ZAqoCXOG0NUMwV0tAc8JLf3jq1QE/NhC4XMA8axexRi2yunpK7JzZga1nrAQ60+2DYXboAM366SdiswDBhQcMz/FUVkVd0427tVnH88RjXzALNQRSH0Um9P05c57aOey6BuJvGQcfzkczbT6EMfKwhFtr/iX83dWeNPcXSO3R8Ec4D/wXx88kMQuIJzpyGkiTm67+jXxSJ5E8a4hUKpAzGfZz3E37TrJkzDhHAYdm81lkNpGKf8tnzTFnFlxwlEUkn49AruW9Olbsw5+tUM7ltLr9/mZxyv6Ke8ep69m24zS9Zsm5gtW8E0OrjPdRCqVHFs0m1YCkEWmwd+/Q3xhyni9RZKYpre+swxnRow9XsUOhoK9Q70Th05RUcunkFrM1OnItPS8aA08PtffFB8ETyY99A7YkbI9jFbSMli08Av+PNfM+go92g1cs48tuyHk9fkZsIQDlcnB031Qdx3VC2GVKmF3T1kx7kdbvneWWMOwxyiEteg+hQoPhWReO6FzTF7tZx1YlzJ4cEsoHof2rvfbio8SV9zVGPLTSG//PYfKPRDKLXqR2zORP+hhI6aQSG+vtOfzn3Ttp8ucZ7d72M6xH8/F5/5OASu4NypSBXi8AL4z3/+Hf/x6y/49S+/o2H4rHMQr1PWY/PjcOCW/EACcqyEVkVDP6PhF2s3dQT3wyQKSfEOX77CbMMP7NynFmWgUyigE6mgKnRx5KPlWhiORhj02qgXNOiZEGL3+mrW1bBm7001h0ajYO10VbUIMtUqMnILldZ6X60BvZJDaagiXa6glItB1gvIFFrO2XY5jspwhNFggG6zhLhZQSyURH1dzZF2/phLMpKVDlr1OhodHX29Yzk/80oKkUwDG18WwHFuJ7ZWy6HeaaBeb6Cj96E3SkgpfdzHYrjvX/Gn0biCXMnEff3euaRit9kn6cuHVH2I0WiAXreJh8gU95EQMlvP31HrvJFBqi7jof6AyOb5cTp3R2V88GoCh/m/uhou8CMJnLg272A29wV/Cxo95SkRDVIgGKabdJm6T1nyi92zgbuzd7C6yWunvSQlmnsbNXp3AZKij+SyGfBgn/jk2xFw09dWwoKeZzNartt9tjbiiA03/FkScON3jr0/i92c3izt0W2nybPa1PDcTpPfnybHHohJ2dpQYVvDflA9z81b247M5eL43d2zRAtqJiTyrnRslfHe0ONou3B+MapRwi+RfdH8vsARFYMSudnKj+a2377lmYXgKTajHLkBObk5axKbBQ7vlnXmWx4tmXvT7b37II2KFLx4Q8WIylEvhYsDW/0LErboud2/9zpbeFxfy7wL6maXu4O32yWWV2btLAU9AUo7DNMpwX50Cnd7/q+Sfku7tzN5LX97WU6fT8BNn6fWeIWZO+GaytBSFbT0IcbDPjr1HNDX8QcAfyz+ytcpL7u6WkgF9tbWGZiO59a6kxfXDb0sgnNchYAMxedbzuQaOjp9GaHYkTU3V2nD56v0HHtXVBWqMcXUPo0EYDqdwhTXZECvN/DHH//A73+2xWr77W/45/d/4e9/+WbFXLOFu3OAU7QQVMxX9fugqjLm8/nOkgixEUJMzoqpFxP9RgdmrICMWPG/+shaBg85DcPW4bh5y2xi6ceh+te1HP6+FrfD0gDZYmJgvsPcnt/JzX7ltWkVmqZYr4evMnc3bqHe/zf+9fe/4pdNLL9f8F/+8W/85//6Hb98k5FqubX5FH3Jy7V087FjptPQC0imOtCqHdSPrROwiT6Fuy37l0+eY/drKOfwX5fl7/clcCXnztYpcwq9kkKm+v8AKYicePViu/wWSTUWgzZuoWN/TWPoaPWBWDzy5vLeos1ch52AiWGphJaSRO6F14H2Uj9r+lR7N+zOVSiJmK+Plj1AMObotIZQInHrNVus1MdgMHD+tfMISkFkmwNr56Vz09JWA8awjzFUaNYvKRmReARmp47Oei2fyGr2lw68tSBeXjp55u6aWBOGtW1SOTJuh9DHJnxiM8i2CS+mrsXNTbDFRBaOjVsOsYfEzs0938tXxhgODYgNMsdfqL9c08EcagaN/o5tDHp4THjguSmjN+ij5LrB5RR9mRj2xca40GZTjtEvIZ5qwVfR0Ui5Wd5+a0/hvl/q6545y+7FpvQz+X9dkp+sZ6dO8R3K5zptOLijoOQhr9dD0iaQsZduyvYp/UM1Hj/nKo9m9JTwkiecp6feiEaDNhVFoNNAnnrbNz7HK+erb07AXV8Lmo1GNJnNaDJo02M2Sl4pQNn2a6OEvXmTP1SF7vxOsHcRCw8ShTfRh4lG5Sh5vDd01xTBh0XgWBEw2Bag+FDvJ4/OOHe9It2mi1Rr92g0mdBkNKB2LU9Rr0SBvC2G5aJHd0GJvNE7aq7GpBV8OJCndZzaRTdLAclPiWKbBpMZPc9G1H1MU9DjpVsrQvGMnrK3lC83rWDXk8mERiJAeSJAknid6/K688dz69Fjtki1ZncZaHnUo/ZjlsJeEdi5t3yNeSo3mw7cXsvOmneULz9R2woiPaJB92nFxCVI/Ju8lrU1zJbsZr22OHen6Wv0mKZbEQRbBDAWOhUBte9uyC9t4yIuBuWlTd0+Urvbpa7jb7CKJ3gCd1tbv3ryLe3+NP5fnej79s9dn6e16wpBjInEGo+w9R8qJJK8AQon8vTYvfzBfbSzzwOqZaMU8EgkebwUTNxR0+XmfxoaznUpAXd9TagcFY6/RJ6VfdQGHLx4l7c7PxFh9AV7H4mHo5cSjqDFz9Qr31LY7yFJ8pA/fEvFl8blrnM3a1MxfUNBUYf44SZ5yR++oexjbz+A76xL5dsw+a0x6bfGZHtnTE7aRboNi/+gIBFEm4IJyj+NVuu6FjSo5Smxvr6yl+htkZq2dXrvz21CzXyCwn4vSeK+Z7FNUL42oI1Vv4bbqkNuzt2i90jpaNDiijWTdJHaE5dfsj/MuTtNX8+9R8reLO1C2Ljk8VPwJk3l9vY/bEzKYdvEwM5/OpJuaBnr/ATuu8bxhY/f8n5xGv8vDPMDdO2oPk9o3zeR59zJRvE/FC8o/mqxP1reqxvIBRwEWF8OHK8+YH6vRmYVYG7ncVuXYn5rEp/rm/X2ufT1Umsv1ef119y91AO+zgSYABNgAkyACTABJvBmBNi5ezOUXBETYAJMgAkwASbABN6fADt3768DbgETYAJMgAkwASbABN6MADt3b4aSK2ICTIAJMAEmwASYwPsTYOfu/XXALWACTIAJMAEmwASYwJsRYOfuzVByRUyACTABJsAEmAATeH8C7Ny9vw64BUyACTABJsAEmAATeDMCF8e5e7OWcEVMgAkwASbABJgAE2ACFoFL4gj/6VKGlwh/rexLg/q9Vh7nv4wA64v5XUbgvNJsd+dxW5difmsSn+ub9fa59PVSa4U+L/nwa9lL6HFZJsAEmAATYAJMgAl8MALs3H0whXBzmAATYAJMgAkwASZwCQF27i6hx2WZABNgAkyACTABJvDBCLBz98EUws1hAkyACTABJsAEmMAlBNi5u4Qel2UCTIAJMAEmwASYwAcjwM7dB1MIN4cJMAEmwASYABNgApcQYOfuEnpclgkwASbABJgAE2ACH4zAlZ07A/1KHL5v3/BNjqE63en9tIP7ZASqIkNWfAjFC2iMzZ1MJx4afVQzsVVdKiKpEvT5iWU52zsRmKKVC0ERtnFIV6xTd72cxWYOvZRCRFUgywrUWAbVvuEuAyb0ggZZjqAy3mab9+sopCLQfKIeGYoaQarUwe7wFiUMkTe5yvtNhi/VwJ7EuY5qLo6Q1a5vkNUc9LU4c4xWKYN4SIUir+8TOdSHe7WsSxz/vha3TmZ5nxP3us2fjJjNsF/DDXMd9zEf5FAJQ9ceHRk/b83N0YYjcjFFJSLbGKx42HVq1XXcFof3of061lwd94s59IrNpkNJ3LfGOPgUOYmpo6Nf5+Asu7d13xyiJPSqFtC3nebkByZAF3wAuJdeTOgpHSAJIJEPUpQeJ7bsz13KBqTltXUe8e2/pebMls+WdJc3odqNhzzhLNW6Axr0mlS88ZMnXKSBrTwnfywBd30R0axLxaiXvIEAeYVt7OmcderO7zw2g2KYPN4o3T31aDDo0lM+Sl7vDdXs49JmIotungJ+P/mlMJVHqwuLLmWDQUrcPVKz26PRaEDdWpbCHomCd87RNmumKeAJUKL4RN3RhGazCY0mzzYJRDSpUcLvoWC6TM3eiCazGU1GE1rnmjzeUCCapfJTm3qDEY16bSon/CR5E/S0ZzPLqt+D2+IpQVIgTU+9HvVsf6N1G1/B7XlQtpgEAn6Sgi73sBfGzznc1opx53fKuB3QXUCiaLHr4NAbTGixFkBEL9niYjZwll8xbeaDJPnz1LUqW1DvThzfULG5tMX2Y5qCHj/d7jxETmJqa99nTLrr7bz7xZbBwtKX3+8nKZCn3vYCp65IwF2fpwk94p29XIGr8Ocu3UW9luMmeTxLB2/HuZs9RpfnPVEqDxa0mD3RrX/pCAaLzofEuiWu8np5CtgfQKLAc5NuvV66ba4fE+ta+PtHEXDVF42oHPZQ4LZGo0GRwoecO9apNX4O6uocNos2pb0euqmtvQ1R84Qeox7y57v7YqwfX366fSxSdHds7eemXj5gOSJrH9Aaf/79h6yz6Mz6URbIdzfOnPO6y9FzjW4kD9027e7CNq+r3V2Rm7ifeaKPZKe7bZF7ao/brEYJr59uyj2a1G5cnLsTxs8hkS9wWxdx5XfKuKUuZb1+yh4wqXX99Fpb3BQcUTEoUbi4srJFk249wg6c93jh2HqCd9sf9icx3Qj5tAlXvZ1j9zYKC3GP9t7QY/mWPOzc2chcN+mqzxPFXuW1rDluodP/NzzhPBrVJJS9mUsDeqeP7wCkWA6ZkAzZl0Ih6bdyjls6bG+B9krvnhjrfUy1JOKa7YoSQzJiQm+5v9Sw5ebkDyWgIdcYot/IQJNx8BUK69RdIWexGXagGxGk4j5bxSriqRDmnc7Oqz8D+n0OnVAFlfj+6LVVsEqaME0TUJTNWDdaVXSUHB6Sdnk7JacNVPshFO5jm3I7OQ4fGiZMKFAU+fB1l7PX5DY3DEf/XZqwc3qfG3wpVPt9dAoRyILpwc/L4+dgsTO5bes6Qa5pwDCFbral9lKvssVtaVOvoDqNIZdZ3einY0xNDZGQU5iaTCEy1qGv1wmcxHQr56ulzrL7NQRziEquAuWhipRP2Ov6An9/dAJXce7kSAmNVhN9vYKkcujhPcV0Klw7QFXVzY1dDWmQAHwfDw+u33GDOR2PAVWD6sigQNV8MMQNwHGeDz4CAdmm90PtYZ0eorI8dw4bYzrFXFGh7vhaYvzJ0zHsS10N/R65TgiVShI72fcbZUyhVzPINRTkHlKb/H19CDmkwajnEA9pUFUNkaRzTa3R1zFWI1DHFWRiIeteoEVSKHXcRqyJ+bCFQuYB49g9CrH95hw7c01uxtSw1g2f7G66cANk+HaVdKBTL40fZ5HLuNnrelGuYcCAAp/T37JXgdfY4rbgHI1SA2aygNTaKBUFMgxMd9frCgcTU4w3ZnQa062sr5U6x+6XBEwMHzKoKCVUcypOtu2vhe/T9uYqzp24QWnxpDUrc5iMibm1HlqCbLsLiAXT1kcMzpPXS5swDROy2JSxI0wRPx8N4+DM0E5WPvxQBFin7uo4j43pNrNkzbbZxpvRwX2ug1ClimOTbsNSCLJY4P7rb4g/TBGvt1CKrZ/oc0ynBkz9HoWOhkK9A71TR07RkYtn0Fo9jOfTKcx5A/cPY8QeGtD1DqoZoJ6MI6fbpgjMFlKyWJj/C/781ww6yj1ajRzsE/XuvNZXrsnNhCGcmk4OmuqDuO+oWgypUgtTWzdES45zW7f1jb7fhNsr22LMYYjZnrgG1adA8amIxHOOjTsn26Jd9LiOiu5DphDf3ud9caQiczQeKljvCzLHwn4rGH4/NKlgr/BnSZ9n94KO2X9Apu5DqZrZmTj5Wdh97n5eybn73FC49Uzg5yRgoFMooBOpoCqm3I98tFwLw9EIg14b9YIGPRNC7F5f7YQ1rNc3pppDo1GwdrqqWgSZahUZuYVKazmlYswNfDdDuG9UkYktZ/diuToqKQONSmu7q1aOozIcYTQYoNssIW5WEAslUd/MzBxp6A+5JCNZ6aBVr6PR0dEXTup9CHOxizPTgH1i6Ti3N27se3DTcqh3GqjXG+jofeiNElJKH/exGO77O57uyd01oVeqGEcKyIXshVTk6nWkhD38Kls7t33JKnyZHCKSgle+tbdXzGmzj4dcHb5SFRnnKzFm80kI/Ol92rmatv/jO8zlFJ7VDGP9Ql+EV9idhnNtqAiPoFizd+LWYS8mfk2LxR/2c67V8IUPRIB16q6M89iIMSJmsfcmxFev0azLnQJyegSVvn2d7PKBvPtYlhUVmuX/aQhF4ohrKWipBzQKOnK+5YjTIjHnL345hJgGNIbCK1MBWYYUiiOyfs1mdVpGKKLBrIqlGSksn+UyfJpmvfLVQiHEkjH4QiE8lHRkqqe+m70eN6vZvgji8a3WtFAEMZ8BLVlBY5pCYfWAPM5tW/5tUm/B7bUtUaDF4ttZVU1DKBYBIhpKVR0Pkbh1v37JFh1S5y1UGgaS1ZTTnkQmNYmKnkTFmGNuvQ6WgX4BFfiQYqfEeiK+/vloov+QQ91XQt/m2W3uAbsPWoey+OCjEHinmTsVmuaxGEyn080DZzocW5ssoIagvsIj00IqsLe2zsB0PIdYI+J4dnwU8tyOowRYp+54zmGjqCpUY7q3PkmMP1NckwG93sAff/wDv//ZFqvtt7/hn9//hb//5ZsVc81to5OihaBivqrfB1WVMZ/Pd5ZEiI0QwqdbDm5VrC2bTx0zW6LX1uYMHPtRpiGkHarfnZm4ci1ublJli4mBuX3qbiezk9vOxTc/PI/b5c0Q93vFenUt9H+KLdpljhsVdJQUcsdmkxUffKsZgbGuY65Fdn402Gv8udKvt/shGo3/i3//n/+O39axBb99w6//7X/j+x//A//xyzeohU0kyp8L5ifq7Ts5dzIi8QiEe/ddr6IuVnOLX2etPyx0gVhs+8vvBJiqyC926Npf0xg6Wn0gFo/wzN0JDD9aFtapu0ZOZWPYnatQEjFfHy1HZO85Oq0hlEjcmiGLlfoYDAbOv3YeQSmIbHNg7W52mwwxhn2MoUKzfkktx7fZqaNjnyo0++j0lzNzone+WBKhaQsNx+u6OXR9DCUknEW3zxD62IRPbAZxy3Lg/LW4HRBlnbKYyMKhcssBOLm553ubK+dxu1z2GMOhsd08d4ItbmSaOiqVIbRcAbFTlD1v4KEyRSSTW836bmr6aROvt/sQ7js794HBAL1iFJL/FrXeAJ37yE/L89N0/MSQKQeznRSHpZ0mz6Egxose3QUPBDE+ElTVXd6MnhJe8oTz9NQb0WjQpqIIdCpi8hwOhXWwP3zybQm468smZ1Sk4KE4d8Q6ded3AhsR2woShTfRh4lG5Sh5vDd0ZwV87VHzLkpejy1AsU0tm+Tk0Rnnrlek23SRau0ejSYTmowG1K7lKeqVSMSr2wy31fj2Ru+s4MRiTFrBhwPrALRCwjO1swGS/AkqtgdWQOR1m5ahLmf0lL2lfLlJ3cGIJpMJjUSA8kSAJBF3yyX48o/n1qPHbJFqze4y0PKoR+3HLIW9IrBzb8nkVG4b8ERWLFC3IMbrfAfHz3nc1lW681vnIKKDcolmzTvKl5+obQW4HtGg+7TSV4KebPo61RafnxLk8dyQIzyjrRn0LAJjz2g2GVGvWaREQCJvtEyjjSHaM5/I1Fnk0xy56+28+8Vux61A3X4OYrzL5VrH7vo8TeJ1ghjbZbs5dyKPiLJP67d8AAACb0lEQVR+Gya/RyJJ8lqR6GsDZ0BKe1VHO/s8oFo2SgFRl8dLwcQdNW03E3s9nP4xBI7qa90El4eEdfkn1+lRfi+xGZUp6vVSwvFUfKZe+ZbCfg9Jkof84Vsqdl8Iu7vr3M3aVEzfUFDUYf1o85I/fEPZx95+AN9Zl8rr8e3xW2OyvTcmJ9S+S1DQK+4ByzaVN21a0KCWp0RY/BcT8UNQIo83QNHbIjXdnt5E7sGfhVFdhduEmvkEhf1ekiTx33hEPxKUrw22wZlfw201Ns537s7jth6SR+1uncll3C56j5SOBq17+kZf6SK1J7ve1im2OKFyWCJvur390bCWv/5uZ8m7Zh6MUrrYpj1R67zikSOC57/kMNvyf6bkUb2dZffO3rNz5+Rx7aOj+jxB+DeR59xpRvE/FC8o/mqxP1reqxvIBRwEWF8OHK8+YH6vRmYVYG7ncVuXYn5rEp/rm/X2ufT1Umsv1ec7rbl7qVt8nQkwASbABJgAE2ACTOAcAuzcnUONyzABJsAEmAATYAJM4IMSYOfugyqGm8UEmAATYAJMgAkwgXMIsHN3DjUuwwSYABNgAkyACTCBD0qAnbsPqhhuFhNgAkyACTABJsAEziHAzt051LgME2ACTIAJMAEmwAQ+KAF27j6oYrhZTIAJMAEmwASYABM4h8DFce7OEcplmAATYAJMgAkwASbABNwJXBJH+E/u1b585RLBL9fOOZgAE2ACTIAJMAEmwAReS4Bfy76WGOdnAkyACTABJsAEmMAHJsDO3QdWDjeNCTABJsAEmAATYAKvJcDO3WuJcX4mwASYABNgAkyACXxgAv8fwiZdopK9fAYAAAAASUVORK5CYII=" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When the query is complete, the results appear below the query. The results should look like the following:\n", + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `loss` column represents the loss metric calculated after the given iteration\n", + "on the training dataset. Since you performed a logistic regression, this column\n", + "is the [log loss](https://en.wikipedia.org/wiki/Cross_entropy#Cross-entropy_error_function_and_logistic_regression).\n", + "The `eval_loss` column is the same loss metric calculated on\n", + "the holdout dataset (data that is held back from training to validate the model).\n", "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
precisionrecallaccuracyf1_scorelog_lossroc_auc
10.4378380.0754190.9852490.1286740.0476820.982956
" + "For more details on the `ML.TRAINING_INFO` function, see the\n", + "[BigQuery ML syntax reference](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use the Model\n", + "## Evaluate your model\n", "\n", - "### Predict purchases per country\n", + "After creating your model, you evaluate the performance of the classifier using\n", + "the [`ML.EVALUATE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-evaluate)\n", + "function. You can also use the [`ML.ROC_CURVE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-roc)\n", + "function for logistic regression specific metrics.\n", "\n", - "Here we try to predict the number of transactions made by visitors of each country, sort the results and select the top 10 countries by purchases." + "A classifier is one of a set of enumerated target values for a label. For\n", + "example, in this tutorial you are using a binary classification model that\n", + "detects transactions. The two classes are the values in the `label` column:\n", + "`0` (no transactions) and not `1` (transaction made).\n", + "\n", + "To run the `ML.EVALUATE` query that evaluates the model:" ] }, { @@ -155,52 +205,60 @@ "source": [ "%%bigquery\n", "SELECT\n", - " country,\n", - " SUM(predicted_label) as total_predicted_purchases\n", - "FROM\n", - " ml.PREDICT(MODEL `bqml_tutorial.sample_model`, (\n", - "SELECT\n", - " IFNULL(device.operatingSystem, \"\") AS os,\n", - " device.isMobile AS is_mobile,\n", - " IFNULL(totals.pageviews, 0) AS pageviews,\n", - " IFNULL(geoNetwork.country, \"\") AS country\n", - "FROM\n", - " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", - "WHERE\n", - " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))\n", - "GROUP BY country\n", - "ORDER BY total_predicted_purchases DESC\n", - "LIMIT 10;" + " *\n", + "FROM ML.EVALUATE(MODEL `bqml_tutorial.sample_model`, (\n", + " SELECT\n", + " IF(totals.transactions IS NULL, 0, 1) AS label,\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(geoNetwork.country, \"\") AS country,\n", + " IFNULL(totals.pageviews, 0) AS pageviews\n", + " FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + " WHERE\n", + " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))" ] }, { + "attachments": { + "image.png": { + "image/png": "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" + } + }, "cell_type": "markdown", "metadata": {}, "source": [ - "Notice this query is very similar to the evaluation query we demonstrated in the previous section. Instead of `ml.EVALUATE`, we use `ml.PREDICT` here and we wrap the BQML portion of the query with standard SQL commands. Concretely, we're interested in the country and the sum of purchases for each country, so that's what we `SELECT`, `GROUP BY` and `ORDER BY`. `LIMIT` is used here to ensure we only get the top 10 results. You should see a table similar to this:\n", + "When the query is complete, the results appear below the query. The\n", + "results should look like the following:\n", + "![image.png](attachment:image.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Because you performed a logistic regression, the results include the following\n", + "columns:\n", "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
countrytotal_predicted_purchases
0UnitedStates467
1Canada8
2Taiwan6
3India5
4UnitedKingdom3
5Turkey3
6Japan2
7Germany2
8HongKong2
9Singapore2
" + "+ [`precision`](https://developers.google.com/machine-learning/glossary/#precision)\n", + "+ [`recall`](https://developers.google.com/machine-learning/glossary/#recall)\n", + "+ [`accuracy`](https://developers.google.com/machine-learning/glossary/#accuracy)\n", + "+ [`f1_score`](https://en.wikipedia.org/wiki/F1_score)\n", + "+ [`log_loss`](https://developers.google.com/machine-learning/glossary/#Log_Loss)\n", + "+ [`roc_auc`](https://developers.google.com/machine-learning/glossary/#AUC)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### Predict purchases per user\n", + "## Use your model to predict outcomes\n", + "\n", + "Now that you have evaluated your model, the next step is to use it to predict\n", + "outcomes. You use your model to predict the number of transactions made by\n", + "website visitors from each country. And you use it to predict purchases per user.\n", "\n", - "Here is another example. This time we try to predict the number of transactions each visitor makes, sort the results and select the top 10 visitors by transactions." + "To run the query that uses the model to predict the number of transactions:" ] }, { @@ -211,58 +269,89 @@ "source": [ "%%bigquery\n", "SELECT\n", - " fullVisitorId,\n", + " country,\n", " SUM(predicted_label) as total_predicted_purchases\n", - "FROM\n", - " ml.PREDICT(MODEL `bqml_tutorial.sample_model`, (\n", - "SELECT\n", - " IFNULL(device.operatingSystem, \"\") AS os,\n", - " device.isMobile AS is_mobile,\n", - " IFNULL(totals.pageviews, 0) AS pageviews,\n", - " IFNULL(geoNetwork.country, \"\") AS country,\n", - " fullVisitorId\n", - "FROM\n", - " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", - "WHERE\n", - " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))\n", - "GROUP BY fullVisitorId\n", - "ORDER BY total_predicted_purchases DESC\n", - "LIMIT 10;" + "FROM ML.PREDICT(MODEL `bqml_tutorial.sample_model`, (\n", + " SELECT\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(totals.pageviews, 0) AS pageviews,\n", + " IFNULL(geoNetwork.country, \"\") AS country\n", + " FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + " WHERE\n", + " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))\n", + " GROUP BY country\n", + " ORDER BY total_predicted_purchases DESC\n", + " LIMIT 10" ] }, { + "attachments": { + "image.png": { + "image/png": "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" + } + }, "cell_type": "markdown", "metadata": {}, "source": [ - "You should see a table similar to this:\n", + "When the query is complete, the results appear below the query. The\n", + "results should look like the following. Because model training is not\n", + "deterministic, your results may differ.\n", "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
countrytotal_predicted_purchases
094178574712951310453
183889310329550527462
274203005015230124602
38069922490326866502
403763940560921891132
529694186761262587982
64890384027656840032
70576935009275810772
81122883309288959422
912809936612043474502
" + "![image.png](attachment:image.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Congratulations!\n", + "In the next example, you try to predict the number of transactions each website\n", + "visitor will make. This query is identical to the previous query except for the\n", + "`GROUP BY` clause. Here the `GROUP BY` clause — `GROUP BY fullVisitorId`\n", + "— is used to group the results by visitor ID.\n", "\n", - "You completed the tutorial. Looking for a challenge? Try making a linear regression model with BQML.\n", - "\n", - "What we've covered:\n", - "+ Create a binary logistic regression model\n", - "+ Evaluate the model\n", - "+ Use model to make predictions" + "To run the query that predicts purchases per user:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%bigquery\n", + "SELECT\n", + " fullVisitorId,\n", + " SUM(predicted_label) as total_predicted_purchases\n", + "FROM ML.PREDICT(MODEL `bqml_tutorial.sample_model`, (\n", + " SELECT\n", + " IFNULL(device.operatingSystem, \"\") AS os,\n", + " device.isMobile AS is_mobile,\n", + " IFNULL(totals.pageviews, 0) AS pageviews,\n", + " IFNULL(geoNetwork.country, \"\") AS country,\n", + " fullVisitorId\n", + " FROM\n", + " `bigquery-public-data.google_analytics_sample.ga_sessions_*`\n", + " WHERE\n", + " _TABLE_SUFFIX BETWEEN '20170701' AND '20170801'))\n", + " GROUP BY fullVisitorId\n", + " ORDER BY total_predicted_purchases DESC\n", + " LIMIT 10" + ] + }, + { + "attachments": { + "image.png": { + "image/png": "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" + } + }, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When the query is complete, the results appear below the query. The\n", + "results should look like the following:\n", + "![image.png](attachment:image.png)" ] }, { @@ -282,15 +371,6 @@ "source": [ "client.delete_dataset(dataset, delete_contents=True)" ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Next Steps\n", - "\n", - "For more information about BQML, please refer to the [documentation](https://cloud.google.com/bigquery/docs/bigqueryml-intro)." - ] } ], "metadata": { From c9c688af60172ba3d66f60a54f76c93fc1be8f90 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 10:33:38 -0800 Subject: [PATCH 17/24] update bq tutorials per Jeff's comments --- .../tutorials/bigquery/BigQuery Basics.ipynb | 38 +++++------ .../bigquery/BigQuery Query Magic.ipynb | 14 ++-- ...ipynb => BigQuery command-line tool.ipynb} | 64 +++++++++++++++---- ...=> Visualizing BigQuery public data.ipynb} | 26 ++++---- 4 files changed, 90 insertions(+), 52 deletions(-) rename notebooks/tutorials/bigquery/{BigQuery Shell Commands.ipynb => BigQuery command-line tool.ipynb} (50%) rename notebooks/tutorials/bigquery/{Visualize BigQuery Public Data.ipynb => Visualizing BigQuery public data.ipynb} (73%) diff --git a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb index a55744301b0..2ade591fbfb 100644 --- a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Basics.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# BigQuery Basics\n", + "# BigQuery basics\n", "\n", "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library." ] @@ -35,13 +35,11 @@ "To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API.\n", "\n", "### Client project\n", - "The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.\n", - "\n", - "See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials.\n", + "The `bigquery.Client` object uses your default project. Alternatively, you can specify a project in the `Client` constructor. For more information about how the default project is determined, see the [google-auth documentation](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html).\n", "\n", "\n", "### Client location\n", - "Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables.\n", + "Locations are required for certain BigQuery operations such as creating a dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables.\n", "\n", "Run the following to create a client with your default project:" ] @@ -60,7 +58,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Alternatively, you can explicitly specify a project when constructing the client:" + "To explicitly specify a project when constructing the client, set the `project` parameter:" ] }, { @@ -78,9 +76,9 @@ "source": [ "## Run a query on a public dataset\n", "\n", - "The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", + "The following example queries the BigQuery `usa_names` public dataset to find the 10 most popular names. `usa_names` is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", "\n", - "Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + "Use the [Client.query](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a pandas [`DataFrame`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." ] }, { @@ -90,8 +88,10 @@ "outputs": [], "source": [ "query = \"\"\"\n", - " SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current`\n", - " WHERE state = \"TX\"\n", + " SELECT name, SUM(number) as total\n", + " FROM `bigquery-public-data.usa_names.usa_1910_current`\n", + " GROUP BY name\n", + " ORDER BY total DESC\n", " LIMIT 10\n", "\"\"\"\n", "query_job = client.query(\n", @@ -110,11 +110,11 @@ "source": [ "## Run a parameterized query\n", "\n", - "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", + "BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when you construct a query with user input. Query parameters are only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query.\n", "\n", - "To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", + "To specify a parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, the following query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value.\n", "\n", - "For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." + "For more information, see [Running parameterized queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation." ] }, { @@ -153,7 +153,7 @@ "source": [ "## Create a new dataset\n", "\n", - "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset. You need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery)." ] }, { @@ -175,7 +175,7 @@ "source": [ "## Write query results to a destination table\n", "\n", - "For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation." + "For more information, see [Writing query results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation." ] }, { @@ -240,7 +240,7 @@ "source": [ "## Load data from a local file to a table\n", "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + "The following example demonstrates how to load a local CSV file into a new table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a local data source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." ] }, { @@ -275,9 +275,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Load data from Google Cloud Storage to a table\n", + "## Load data from Cloud Storage to a table\n", "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." + "The following example demonstrates how to load a local CSV file into a new table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to loading data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." ] }, { @@ -293,7 +293,7 @@ " bigquery.SchemaField('post_abbr', 'STRING')\n", " ],\n", " skip_leading_rows=1,\n", - " # The source format defaults to CSV, so the line below is optional.\n", + " # The source format defaults to CSV. The line below is optional.\n", " source_format=bigquery.SourceFormat.CSV\n", ")\n", "uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'\n", diff --git a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb index a6a2dc701f0..9c948679a7b 100644 --- a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb @@ -4,9 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# BigQuery Query Magic\n", + "# BigQuery query magic\n", "\n", - "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame." + "Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`. The `%%bigquery` magic runs a SQL query and returns the results as a pandas `DataFrame`." ] }, { @@ -15,9 +15,9 @@ "source": [ "## Run a query on a public dataset\n", "\n", - "The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", + "The following example queries the BigQuery `usa_names` public dataset. `usa_names` is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879.\n", "\n", - "The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." + "The following example shows how to invoke the magic (`%%bigquery`), and how to pass in a standard SQL query in the body of the code cell. The results are displayed below the input cell as a pandas [`DataFrame`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html)." ] }, { @@ -65,7 +65,7 @@ "source": [ "## Explicitly specify a project\n", "\n", - "By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify." + "By default, the `%%bigquery` magic command uses your default project to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify." ] }, { @@ -97,7 +97,7 @@ "source": [ "## Assign the query results to a variable\n", "\n", - "If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command." + "To save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The following example saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell that invokes the magic command." ] }, { @@ -129,7 +129,7 @@ "source": [ "## Run a parameterized query\n", "\n", - "Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter." + "Parameterized queries are useful if you need to run a query with certain parameters that are calculated at run time. Note that the value types must be JSON serializable. The following example defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter." ] }, { diff --git a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb b/notebooks/tutorials/bigquery/BigQuery command-line tool.ipynb similarity index 50% rename from notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb rename to notebooks/tutorials/bigquery/BigQuery command-line tool.ipynb index 3116d69963e..f9c709e4533 100644 --- a/notebooks/tutorials/bigquery/BigQuery Shell Commands.ipynb +++ b/notebooks/tutorials/bigquery/BigQuery command-line tool.ipynb @@ -6,7 +6,7 @@ "source": [ "# BigQuery command-line tool\n", "\n", - "The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`." + "The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) and can be used to interact with BigQuery. When you use CLI commands in a notebook, the command must be prepended with a `!`." ] }, { @@ -15,7 +15,7 @@ "source": [ "## View available commands\n", "\n", - "To view the available commands for the BigQuery command-line tool, use the `--help` flag." + "To view the available commands for the BigQuery command-line tool, use the `help` command." ] }, { @@ -33,9 +33,9 @@ "source": [ "## Create a new dataset\n", "\n", - "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", + "A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset. You need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery).\n", "\n", - "First, define a name for your new dataset:" + "First, name your new dataset:" ] }, { @@ -51,9 +51,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The command below creates a new dataset in the US using the ID defined above.\n", + "The following command creates a new dataset in the US using the ID defined above.\n", "\n", - "NOTE: In the examples below, the `dataset_id` variable is referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters." + "NOTE: In the examples in this notebook, the `dataset_id` variable is referenced in the commands using both `{}` and `$`. To avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters." ] }, { @@ -65,13 +65,24 @@ "!bq --location=US mk --dataset $dataset_id" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The response should look like the following:\n", + "\n", + "```\n", + "Dataset 'your-project-id:your_new_dataset' successfully created.\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## List datasets\n", "\n", - "The command below lists lists all datasets in your current project." + "The following command lists all datasets in your default project." ] }, { @@ -83,13 +94,26 @@ "!bq ls" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The response should look like the following:\n", + "\n", + "```\n", + " datasetId \n", + " ------------------------------ \n", + " your_new_dataset \n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load data from a local file to a table\n", "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." + "The following example demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a local data source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation." ] }, { @@ -98,16 +122,23 @@ "metadata": {}, "outputs": [], "source": [ - "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_local_file 'resources/us-states.csv'" + "!bq \\\n", + " --location=US \\\n", + " load \\\n", + " --autodetect \\\n", + " --skip_leading_rows=1 \\\n", + " --source_format=CSV \\\n", + " {dataset_id}.us_states_local_file \\\n", + " 'resources/us-states.csv'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Load data from Google Cloud Storage to a table\n", + "## Load data from Cloud Storage to a table\n", "\n", - "The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." + "The following example demonstrates how to load a local CSV file into a new table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to loading data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation." ] }, { @@ -116,7 +147,14 @@ "metadata": {}, "outputs": [], "source": [ - "!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" + "!bq \\\n", + " --location=US \\\n", + " load \\\n", + " --autodetect \\\n", + " --skip_leading_rows=1 \\\n", + " --source_format=CSV \\\n", + " {dataset_id}.us_states_gcs \\\n", + " 'gs://cloud-samples-data/bigquery/us-states/us-states.csv'" ] }, { @@ -125,7 +163,7 @@ "source": [ "## Run a query\n", "\n", - "The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose." + "The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose." ] }, { diff --git a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb b/notebooks/tutorials/bigquery/Visualizing BigQuery public data.ipynb similarity index 73% rename from notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb rename to notebooks/tutorials/bigquery/Visualizing BigQuery public data.ipynb index 1df73278925..607938d6fbd 100644 --- a/notebooks/tutorials/bigquery/Visualize BigQuery Public Data.ipynb +++ b/notebooks/tutorials/bigquery/Visualizing BigQuery public data.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Vizualizing BigQuery Data in a Jupyter Notebook\n", + "# Vizualizing BigQuery data in a Jupyter notebook\n", "\n", "[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime.\n", "\n", @@ -15,11 +15,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Using Jupyter Magics to Query BigQuery Data\n", + "## Using Jupyter magics to query BigQuery data\n", "\n", "The BigQuery Python client library provides a magic command that allows you to run queries with minimal code.\n", "\n", - "The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year." + "The BigQuery client library provides a cell magic, `%%bigquery`. The `%%bigquery` magic runs a SQL query and returns the results as a pandas `DataFrame`. The following cell executes a query of the BigQuery natality public dataset and returns the total births by year." ] }, { @@ -42,7 +42,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization." + "The following command to runs the same query, but this time the results are saved to a variable. The variable name, `total_births`, is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization." ] }, { @@ -65,7 +65,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas." + "The next cell uses the pandas `DataFrame.plot` method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas." ] }, { @@ -121,9 +121,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Using Python to Query BigQuery Data\n", + "## Using Python to query BigQuery data\n", "\n", - "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", + "Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas `Dataframe`, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks.\n", "\n", "To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API." ] @@ -143,7 +143,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.)." + "Use the [`Client.query`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.)." ] }, { @@ -174,7 +174,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time." + "To chart the query results in your `DataFrame`, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time." ] }, { @@ -220,7 +220,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Finally, chart the query results in your DataFrame." + "Finally, chart the query results in your `DataFrame`." ] }, { @@ -239,11 +239,11 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### What's Next\n", + "## What's Next\n", "\n", - "+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more.\n", + "+ __Learn more about writing queries for BigQuery__ — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more.\n", "\n", - "+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference)." + "+ __Explore BigQuery syntax__ — The preferred dialect for SQL queries in BigQuery is standard SQL. Standard SQL syntax is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference)." ] } ], From d183113c37c8a0ea449b8ccd2ccc3aa9941c6c71 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 10:34:29 -0800 Subject: [PATCH 18/24] fixes titles to be sentence case --- .../Cloud Storage Client Library.ipynb | 35 +++++----- ....ipynb => Storage command-line tool.ipynb} | 66 +++++++++++++++++-- 2 files changed, 78 insertions(+), 23 deletions(-) rename notebooks/tutorials/storage/{Storage Commands.ipynb => Storage command-line tool.ipynb} (80%) diff --git a/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb b/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb index ce5eeec9809..8e275a7ea63 100644 --- a/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Cloud Storage Client Library\n", + "# Cloud Storage client library\n", "\n", "This tutorial shows how to get started with the [Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html)." ] @@ -47,6 +47,7 @@ "outputs": [], "source": [ "client = storage.Client()\n", + "\n", "print(\"Client created using default project: {}\".format(client.project))" ] }, @@ -82,12 +83,12 @@ "outputs": [], "source": [ "# Replace the string below with a unique name for the new bucket\n", - "bucket_name = 'your-new-bucket'\n", + "bucket_name = \"your-new-bucket\"\n", "\n", "# Creates the new bucket\n", "bucket = client.create_bucket(bucket_name)\n", "\n", - "print('Bucket {} created.'.format(bucket.name))" + "print(\"Bucket {} created.\".format(bucket.name))" ] }, { @@ -129,9 +130,9 @@ "source": [ "bucket = client.get_bucket(bucket_name)\n", "\n", - "print('Bucket name: {}'.format(bucket.name))\n", - "print('Bucket location: {}'.format(bucket.location))\n", - "print('Bucket storage class: {}'.format(bucket.storage_class))" + "print(\"Bucket name: {}\".format(bucket.name))\n", + "print(\"Bucket location: {}\".format(bucket.location))\n", + "print(\"Bucket storage class: {}\".format(bucket.storage_class))" ] }, { @@ -155,13 +156,13 @@ }, "outputs": [], "source": [ - "blob_name = 'us-states.txt'\n", + "blob_name = \"us-states.txt\"\n", "blob = bucket.blob(blob_name)\n", "\n", - "source_file_name = 'resources/us-states.txt'\n", + "source_file_name = \"resources/us-states.txt\"\n", "blob.upload_from_filename(source_file_name)\n", "\n", - "print('File uploaded to {}.'.format(bucket.name))" + "print(\"File uploaded to {}.\".format(bucket.name))" ] }, { @@ -203,10 +204,10 @@ "source": [ "blob = bucket.get_blob(blob_name)\n", "\n", - "print('Name: {}'.format(blob.id))\n", - "print('Size: {} bytes'.format(blob.size))\n", - "print('Content type: {}'.format(blob.content_type))\n", - "print('Public URL: {}'.format(blob.public_url))" + "print(\"Name: {}\".format(blob.id))\n", + "print(\"Size: {} bytes\".format(blob.size))\n", + "print(\"Content type: {}\".format(blob.content_type))\n", + "print(\"Public URL: {}\".format(blob.public_url))" ] }, { @@ -224,10 +225,10 @@ }, "outputs": [], "source": [ - "output_file_name = 'resources/downloaded-us-states.txt'\n", + "output_file_name = \"resources/downloaded-us-states.txt\"\n", "blob.download_to_filename(output_file_name)\n", "\n", - "print('Downloaded blob {} to {}.'.format(blob.name, output_file_name))" + "print(\"Downloaded blob {} to {}.\".format(blob.name, output_file_name))" ] }, { @@ -253,7 +254,7 @@ "blob = client.get_bucket(bucket_name).get_blob(blob_name)\n", "blob.delete()\n", "\n", - "print('Blob {} deleted.'.format(blob.name))" + "print(\"Blob {} deleted.\".format(blob.name))" ] }, { @@ -274,7 +275,7 @@ "bucket = client.get_bucket(bucket_name)\n", "bucket.delete()\n", "\n", - "print('Bucket {} deleted.'.format(bucket.name))" + "print(\"Bucket {} deleted.\".format(bucket.name))" ] }, { diff --git a/notebooks/tutorials/storage/Storage Commands.ipynb b/notebooks/tutorials/storage/Storage command-line tool.ipynb similarity index 80% rename from notebooks/tutorials/storage/Storage Commands.ipynb rename to notebooks/tutorials/storage/Storage command-line tool.ipynb index 8c98b08ba72..a4a2d44f9f9 100644 --- a/notebooks/tutorials/storage/Storage Commands.ipynb +++ b/notebooks/tutorials/storage/Storage command-line tool.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Storage Commands\n", + "# Storage command-line tool\n", "\n", "The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`." ] @@ -49,7 +49,7 @@ "outputs": [], "source": [ "# Replace the string below with a unique name for the new bucket\n", - "bucket_name = 'your-new-bucket'" + "bucket_name = \"your-new-bucket\"" ] }, { @@ -86,7 +86,7 @@ "outputs": [], "source": [ "# Replace the string below with your project ID\n", - "project_id = 'your-project-id'" + "project_id = \"your-project-id\"" ] }, { @@ -98,6 +98,17 @@ "!gsutil ls -p $project_id" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The response should look like the following:\n", + "\n", + "```\n", + "gs://your-new-bucket/\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -106,18 +117,33 @@ "\n", "The next cell shows how to get information on metadata of your Cloud Storage buckets.\n", "\n", - "To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes)." + "To learn more about specific bucket properties, see [Bucket locations](https://cloud.google.com/storage/docs/locations) and [Storage classes](https://cloud.google.com/storage/docs/storage-classes)." ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "scrolled": true + }, "outputs": [], "source": [ "!gsutil ls -L -b gs://{bucket_name}/" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The response should look like the following:\n", + "```\n", + "gs://your-new-bucket/ :\n", + " Storage class: MULTI_REGIONAL\n", + " Location constraint: US\n", + " ...\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -158,13 +184,23 @@ "!gsutil ls -r gs://{bucket_name}/**" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The response should look like the following:\n", + "```\n", + "gs://your-new-bucket/us-states.txt\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Get a blob and display metadata\n", "\n", - "See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." + "See [Viewing and editing object metadata](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata." ] }, { @@ -176,6 +212,24 @@ "!gsutil ls -L gs://{bucket_name}/us-states.txt" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The response should look like the following:\n", + "\n", + "```\n", + "gs://your-new-bucket/us-states.txt:\n", + " Creation time: Fri, 08 Feb 2019 05:23:28 GMT\n", + " Update time: Fri, 08 Feb 2019 05:23:28 GMT\n", + " Storage class: STANDARD\n", + " Content-Language: en\n", + " Content-Length: 637\n", + " Content-Type: text/plain\n", + "...\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, From edd347494381587cf9ed2c65b189ef2508102b8f Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 10:35:11 -0800 Subject: [PATCH 19/24] update rendered to be unexecuted versions with output examples for command line --- notebooks/rendered/bigquery-basics.md | 197 +------- .../rendered/bigquery-command-line-tool.md | 101 ++++ notebooks/rendered/bigquery-query-magic.md | 437 +--------------- notebooks/rendered/bigquery-shell-commands.md | 392 --------------- .../rendered/cloud-storage-client-library.md | 72 +-- .../rendered/storage-command-line-tool.md | 155 ++++++ notebooks/rendered/storage-commands.md | 328 ------------ .../visualize-bigquery-public-data_10_0.png | Bin 17935 -> 0 bytes .../visualize-bigquery-public-data_16_0.png | Bin 13836 -> 0 bytes .../visualize-bigquery-public-data_20_0.png | Bin 12577 -> 0 bytes .../visualize-bigquery-public-data_6_0.png | Bin 7326 -> 0 bytes .../visualize-bigquery-public-data.md | 466 ------------------ .../visualizing-bigquery-public-data.md | 146 ++++++ 13 files changed, 446 insertions(+), 1848 deletions(-) create mode 100644 notebooks/rendered/bigquery-command-line-tool.md delete mode 100644 notebooks/rendered/bigquery-shell-commands.md create mode 100644 notebooks/rendered/storage-command-line-tool.md delete mode 100644 notebooks/rendered/storage-commands.md delete mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png delete mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png delete mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png delete mode 100644 notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png delete mode 100644 notebooks/rendered/visualize-bigquery-public-data.md create mode 100644 notebooks/rendered/visualizing-bigquery-public-data.md diff --git a/notebooks/rendered/bigquery-basics.md b/notebooks/rendered/bigquery-basics.md index 38a04a69eb4..c72b37f6fc0 100644 --- a/notebooks/rendered/bigquery-basics.md +++ b/notebooks/rendered/bigquery-basics.md @@ -1,5 +1,5 @@ -# BigQuery Basics +# BigQuery basics [BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. This page shows you how to get started with the Google BigQuery API using the Python client library. @@ -16,13 +16,11 @@ import pandas To use the BigQuery Python client library, start by initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. ### Client project -The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. +The `bigquery.Client` object uses your default project. Alternatively, you can specify a project in the `Client` constructor. For more information about how the default project is determined, see the [google-auth documentation](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html). ### Client location -Locations are required for certain BigQuery operations such as creating a Dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables. +Locations are required for certain BigQuery operations such as creating a dataset. If a location is provided to the client when it is initialized, it will be the default location for jobs, datasets, and tables. Run the following to create a client with your default project: @@ -32,10 +30,7 @@ client = bigquery.Client(location="US") print("Client creating using default project: {}".format(client.project)) ``` - Client creating using default project: your-project-id - - -Alternatively, you can explicitly specify a project when constructing the client: +To explicitly specify a project when constructing the client, set the `project` parameter: ```python @@ -44,15 +39,17 @@ Alternatively, you can explicitly specify a project when constructing the client ## Run a query on a public dataset -The following example runs a query on the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. +The following example queries the BigQuery `usa_names` public dataset to find the 10 most popular names. `usa_names` is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. -Use the [Client.query()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe()](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). +Use the [Client.query](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run the query, and the [QueryJob.to_dataframe](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.QueryJob.html#google.cloud.bigquery.job.QueryJob.to_dataframe) method to return the results as a pandas [`DataFrame`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). ```python query = """ - SELECT name FROM `bigquery-public-data.usa_names.usa_1910_current` - WHERE state = "TX" + SELECT name, SUM(number) as total + FROM `bigquery-public-data.usa_names.usa_1910_current` + GROUP BY name + ORDER BY total DESC LIMIT 10 """ query_job = client.query( @@ -65,72 +62,13 @@ df = query_job.to_dataframe() df ``` - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
name
0Mary
1Ruby
2Annie
3Willie
4Ruth
5Gladys
6Maria
7Frances
8Margaret
9Helen
-
- - - ## Run a parameterized query -BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when queries are constructed using user input. This feature is only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query. +BigQuery supports query parameters to help prevent [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) when you construct a query with user input. Query parameters are only available with [standard SQL syntax](https://cloud.google.com/bigquery/docs/reference/standard-sql/). Query parameters can be used as substitutes for arbitrary expressions. Parameters cannot be used as substitutes for identifiers, column names, table names, or other parts of the query. -To specify a named parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, this query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value. +To specify a parameter, use the `@` character followed by an [identifier](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#identifiers), such as `@param_name`. For example, the following query finds all the words in a specific Shakespeare corpus with counts that are at least the specified value. -For more information, see [Running Parameterized Queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation. +For more information, see [Running parameterized queries](https://cloud.google.com/bigquery/docs/parameterized-queries) in the BigQuery documentation. ```python @@ -158,89 +96,9 @@ query_job = client.query(sql, location="US", job_config=job_config) query_job.to_dataframe() ``` - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wordword_count
0the614
1I577
2and490
3to486
4a407
5of367
6my314
7is307
8in291
9you271
10that270
11me263
-
- - - ## Create a new dataset -A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset. You need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). ```python @@ -253,7 +111,7 @@ dataset = client.create_dataset(dataset_id) # API request ## Write query results to a destination table -For more information, see [Writing Query Results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. +For more information, see [Writing query results](https://cloud.google.com/bigquery/docs/writing-results) in the BigQuery documentation. ```python @@ -274,9 +132,6 @@ query_job.result() # Waits for the query to finish print("Query results loaded to table {}".format(table_ref.path)) ``` - Query results loaded to table /projects/your-project-id/datasets/your_new_dataset/tables/your_new_table_id - - ## Load data from a pandas DataFrame to a new table @@ -301,12 +156,9 @@ job.result() # Waits for table load to complete. print("Loaded dataframe to {}".format(table_ref.path)) ``` - Loaded dataframe to /projects/your-project-id/datasets/your_new_dataset/tables/monty_python - - ## Load data from a local file to a table -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. +The following example demonstrates how to load a local CSV file into a new table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a local data source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. ```python @@ -332,12 +184,9 @@ print('Loaded {} rows into {}:{}.'.format( job.output_rows, dataset_id, table_ref.path)) ``` - Loaded 50 rows into your_new_dataset:/projects/your-project-id/datasets/your_new_dataset/tables/us_states_from_local_file. +## Load data from Cloud Storage to a table - -## Load data from Google Cloud Storage to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. +The following example demonstrates how to load a local CSV file into a new table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to loading data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. ```python @@ -348,7 +197,7 @@ job_config = bigquery.LoadJobConfig( bigquery.SchemaField('post_abbr', 'STRING') ], skip_leading_rows=1, - # The source format defaults to CSV, so the line below is optional. + # The source format defaults to CSV. The line below is optional. source_format=bigquery.SourceFormat.CSV ) uri = 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' @@ -367,11 +216,6 @@ destination_table = client.get_table(table_ref) print('Loaded {} rows.'.format(destination_table.num_rows)) ``` - Starting job 1c54e163-d785-4551-b4b7-7170ba07e00a - Job finished. - Loaded 50 rows. - - ## Cleaning Up The following code deletes the dataset created for this tutorial, including all tables in the dataset. @@ -386,6 +230,3 @@ client.delete_dataset(dataset, delete_contents=True) print('Deleted dataset: {}'.format(dataset.path)) ``` - - Deleted dataset: /projects/your-project-id/datasets/your_new_dataset - diff --git a/notebooks/rendered/bigquery-command-line-tool.md b/notebooks/rendered/bigquery-command-line-tool.md new file mode 100644 index 00000000000..9d824a09065 --- /dev/null +++ b/notebooks/rendered/bigquery-command-line-tool.md @@ -0,0 +1,101 @@ + +# BigQuery command-line tool + +The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) and can be used to interact with BigQuery. When you use CLI commands in a notebook, the command must be prepended with a `!`. + +## View available commands + +To view the available commands for the BigQuery command-line tool, use the `help` command. + + +```python +!bq help +``` + +## Create a new dataset + +A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset. You need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). + +First, name your new dataset: + + +```python +dataset_id = "your_new_dataset" +``` + +The following command creates a new dataset in the US using the ID defined above. + +NOTE: In the examples in this notebook, the `dataset_id` variable is referenced in the commands using both `{}` and `$`. To avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. + + +```python +!bq --location=US mk --dataset $dataset_id +``` + +The response should look like the following: + +``` +Dataset 'your-project-id:your_new_dataset' successfully created. +``` + +## List datasets + +The following command lists all datasets in your default project. + + +```python +!bq ls +``` + +The response should look like the following: + +``` + datasetId + ------------------------------ + your_new_dataset +``` + +## Load data from a local file to a table + +The following example demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a local data source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. + + +```python +!bq \ + --location=US \ + load \ + --autodetect \ + --skip_leading_rows=1 \ + --source_format=CSV \ + {dataset_id}.us_states_local_file \ + 'resources/us-states.csv' +``` + +## Load data from Cloud Storage to a table + +The following example demonstrates how to load a local CSV file into a new table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to loading data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. + + +```python +!bq \ + --location=US \ + load \ + --autodetect \ + --skip_leading_rows=1 \ + --source_format=CSV \ + {dataset_id}.us_states_gcs \ + 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' +``` + +## Run a query + +The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose. + +## Cleaning Up + +The following code deletes the dataset created for this tutorial, including all tables in the dataset. + + +```python +!bq rm -r -f --dataset $dataset_id +``` diff --git a/notebooks/rendered/bigquery-query-magic.md b/notebooks/rendered/bigquery-query-magic.md index 8e800003602..6200ac53084 100644 --- a/notebooks/rendered/bigquery-query-magic.md +++ b/notebooks/rendered/bigquery-query-magic.md @@ -1,13 +1,13 @@ -# BigQuery Query Magic +# BigQuery query magic -Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come pre-loaded with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. +Jupyter magics are notebook-specific shortcuts that allow you to run commands with minimal syntax. Jupyter notebooks come with many [built-in commands](https://ipython.readthedocs.io/en/stable/interactive/magics.html). The BigQuery client library, `google-cloud-bigquery`, provides a cell magic, `%%bigquery`. The `%%bigquery` magic runs a SQL query and returns the results as a pandas `DataFrame`. ## Run a query on a public dataset -The following example queries the BigQuery `usa_names` public dataset, which is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. +The following example queries the BigQuery `usa_names` public dataset. `usa_names` is a Social Security Administration dataset that contains all names from Social Security card applications for births that occurred in the United States after 1879. -The example below shows how to invoke the magic (`%%bigquery`) and pass in a Standard SQL query in the body of the code cell. The results are displayed below the input cell as a [pandas DataFrame](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). +The following example shows how to invoke the magic (`%%bigquery`), and how to pass in a standard SQL query in the body of the code cell. The results are displayed below the input cell as a pandas [`DataFrame`](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html). ```python @@ -19,76 +19,6 @@ ORDER BY count DESC LIMIT 10 ``` - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - ## Display verbose output As the query job is running, status messages below the cell update with the query job ID and the amount of time the query has been running. By default, this output is erased and replaced with the results of the query. If you pass the `--verbose` flag, the output will remain below the cell after query completion. @@ -103,84 +33,9 @@ ORDER BY count DESC LIMIT 10 ``` - Executing query with job ID: 0e3ca180-c6e9-4298-bbc4-b68e7e6fdebd - Query executing: 0.52s - Query complete after 0.83s - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - ## Explicitly specify a project -By default, the `%%bigquery` magic command uses the project associated with your credentials to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. +By default, the `%%bigquery` magic command uses your default project to run the query. You may also explicitly provide a project ID using the `--project` flag. Note that your credentials must have permissions to create query jobs in the project you specify. ```python @@ -197,79 +52,9 @@ ORDER BY count DESC LIMIT 10 ``` - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - ## Assign the query results to a variable -If you would like to save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The example below saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell invoking the magic command. +To save the results of your query to a variable, provide a variable name as a parameter to `%%bigquery`. The following example saves the results of the query to a variable named `df`. Note that when a variable is provided, the results are not displayed below the cell that invokes the magic command. ```python @@ -282,153 +67,13 @@ LIMIT 10 ``` - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - - ```python df ``` - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
- - - ## Run a parameterized query -Parameterized queries are useful if you need to run a query with certain parameters calculated at run time. Note that the value types must be JSON serializable. The example below defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. +Parameterized queries are useful if you need to run a query with certain parameters that are calculated at run time. Note that the value types must be JSON serializable. The following example defines a parameters dictionary and passes it to the `--params` flag. The key of the dictionary is the name of the parameter, and the value of the dictionary is the value of the parameter. ```python @@ -444,71 +89,3 @@ GROUP BY name ORDER BY count DESC LIMIT @limit ``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
namecount
0James5001762
1John4875934
2Robert4743843
3Michael4354622
4William3886371
5Mary3748377
6David3595923
7Richard2542659
8Joseph2518578
9Charles2273860
-
diff --git a/notebooks/rendered/bigquery-shell-commands.md b/notebooks/rendered/bigquery-shell-commands.md deleted file mode 100644 index 1b9d7ada952..00000000000 --- a/notebooks/rendered/bigquery-shell-commands.md +++ /dev/null @@ -1,392 +0,0 @@ - -# BigQuery command-line tool - -The BigQuery command-line tool is installed as part of the [Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/), and can be used to interact with BigQuery using shell commands instead of Python code. Note that shell commands in a notebook must be prepended with a `!`. - -## View available commands - -To view the available commands for the BigQuery command-line tool, use the `--help` flag. - - -```python -!bq help -``` - - Python script for interacting with BigQuery. - - - USAGE: bq [--global_flags] [--command_flags] [args] - - - Any of the following commands: - cancel, cp, extract, head, help, init, insert, load, ls, mk, mkdef, partition, - query, rm, shell, show, update, version, wait - - - cancel Request a cancel and waits for the job to be cancelled. - - Requests a cancel and then either: a) waits until the job is done if - the sync flag is set [default], or b) returns immediately if the sync - flag is not set. Not all job types support a cancel, an error is - returned if it cannot be cancelled. Even for jobs that support a - cancel, success is not guaranteed, the job may have completed by the - time the cancel request is noticed, or the job may be in a stage - where it cannot be cancelled. - - Examples: - bq cancel job_id # Requests a cancel and waits until the job is done. - bq --nosync cancel job_id # Requests a cancel and returns - immediately. - - Arguments: - job_id: Job ID to cancel. - - cp Copies one table to another. - - Examples: - bq cp dataset.old_table dataset2.new_table - bq cp --destination_kms_key=kms_key dataset.old_table - dataset2.new_table - - extract Perform an extract operation of source_table into destination_uris. - - Usage: - extract - - Examples: - bq extract ds.summary gs://mybucket/summary.csv - - Arguments: - source_table: Source table to extract. - destination_uris: One or more Google Cloud Storage URIs, separated by - commas. - - head Displays rows in a table. - - Examples: - bq head dataset.table - bq head -j job - bq head -n 10 dataset.table - bq head -s 5 -n 10 dataset.table - - help Help for all or selected command: - bq help [] - - To retrieve help with global flags: - bq --help - - To retrieve help with flags only from the main module: - bq --helpshort [] - - init Authenticate and create a default .bigqueryrc file. - - insert Inserts rows in a table. - - Inserts the records formatted as newline delimited JSON from file - into the specified table. If file is not specified, reads from stdin. - If there were any insert errors it prints the errors to stdout. - - Examples: - bq insert dataset.table /tmp/mydata.json - echo '{"a":1, "b":2}' | bq insert dataset.table - - Template table examples: Insert to dataset.template_suffix table - using dataset.template table as its template. - bq insert -x=_suffix dataset.table /tmp/mydata.json - - load Perform a load operation of source into destination_table. - - Usage: - load [] - - The is the fully-qualified table name of table to - create, or append to if the table already exists. - - The argument can be a path to a single local file, or a - comma-separated list of URIs. - - The argument should be either the name of a JSON file or a - text schema. This schema should be omitted if the table already has - one. - - In the case that the schema is provided in text form, it should be a - comma-separated list of entries of the form name[:type], where type - will default to string if not specified. - - In the case that is a filename, it should contain a single - array object, each entry of which should be an object with properties - 'name', 'type', and (optionally) 'mode'. See the online documentation - for more detail: - https://developers.google.com/bigquery/preparing-data-for-bigquery - - Note: the case of a single-entry schema with no type specified is - ambiguous; one can use name:string to force interpretation as a - text schema. - - Examples: - bq load ds.new_tbl ./info.csv ./info_schema.json - bq load ds.new_tbl gs://mybucket/info.csv ./info_schema.json - bq load ds.small gs://mybucket/small.csv name:integer,value:string - bq load ds.small gs://mybucket/small.csv field1,field2,field3 - - Arguments: - destination_table: Destination table name. - source: Name of local file to import, or a comma-separated list of - URI paths to data to import. - schema: Either a text schema or JSON file, as above. - - ls List the objects contained in the named collection. - - List the objects in the named project or dataset. A trailing : or . - can be used to signify a project or dataset. - * With -j, show the jobs in the named project. - * With -p, show all projects. - - Examples: - bq ls - bq ls -j proj - bq ls -p -n 1000 - bq ls mydataset - bq ls -a - bq ls --filter labels.color:red - bq ls --filter 'labels.color:red labels.size:*' - bq ls --transfer_config --transfer_location='us' - --filter='dataSourceIds:play,adwords' - bq ls --transfer_run --filter='states:SUCCESSED,PENDING' - --run_attempt='LATEST' projects/p/locations/l/transferConfigs/c - bq ls --transfer_log --message_type='messageTypes:INFO,ERROR' - projects/p/locations/l/transferConfigs/c/runs/r - - mk Create a dataset, table, view, or transfer configuration with this - name. - - See 'bq help load' for more information on specifying the schema. - - Examples: - bq mk new_dataset - bq mk new_dataset.new_table - bq --dataset_id=new_dataset mk table - bq mk -t new_dataset.newtable name:integer,value:string - bq mk --view='select 1 as num' new_dataset.newview - (--view_udf_resource=path/to/file.js) - bq mk -d --data_location=EU new_dataset - bq mk --transfer_config --target_dataset=dataset --display_name=name - -p='{"param":"value"}' --data_source=source - bq mk --transfer_run --start_time={start_time} --end_time={end_time} - projects/p/locations/l/transferConfigs/c - - mkdef Emits a definition in JSON for a GCS backed table. - - The output of this command can be redirected to a file and used for - the external_table_definition flag with the "bq query" and "bq mk" - commands. It produces a definition with the most commonly used values - for options. You can modify the output to override option values. - - Usage: - mkdef [] - - Examples: - bq mkdef 'gs://bucket/file.csv' field1:integer,field2:string - - Arguments: - source_uris: a comma-separated list of uris. - schema: The argument should be either the name of a JSON - file or - a text schema. - - In the case that the schema is provided in text form, it should be a - comma-separated list of entries of the form name[:type], where type - will - default to string if not specified. - - In the case that is a filename, it should contain a - single array object, each entry of which should be an object with - properties 'name', 'type', and (optionally) 'mode'. See the online - documentation for more detail: - https://developers.google.com/bigquery/preparing-data-for-bigquery - - Note: the case of a single-entry schema with no type specified is - ambiguous; one can use name:string to force interpretation as a - text schema. - - partition Copies source tables into partitioned tables. - - Usage: bq partition - - - Copies tables of the format to a - destination partitioned table, with the date suffix of the source - tables becoming the partition date of the destination table - partitions. - - If the destination table does not exist, one will be created with a - schema and that matches the last table that matches the supplied - prefix. - - Examples: - bq partition dataset1.sharded_ dataset2.partitioned_table - - query Execute a query. - - Query should be specifed on command line, or passed on stdin. - - Examples: - bq query 'select count(*) from publicdata:samples.shakespeare' - echo 'select count(*) from publicdata:samples.shakespeare' | bq query - - Usage: - - - rm Delete the dataset, table, or transfer config described by - identifier. - - Always requires an identifier, unlike the show and ls commands. By - default, also requires confirmation before deleting. Supports the -d - -t flags to signify that the identifier is a dataset or table. - * With -f, don't ask for confirmation before deleting. - * With -r, remove all tables in the named dataset. - - Examples: - bq rm ds.table - bq rm -r -f old_dataset - bq rm --transfer_config=projects/p/locations/l/transferConfigs/c - - shell Start an interactive bq session. - - show Show all information about an object. - - Examples: - bq show -j - bq show dataset - bq show [--schema] dataset.table - bq show [--view] dataset.view - bq show --transfer_config projects/p/locations/l/transferConfigs/c - bq show --transfer_run - projects/p/locations/l/transferConfigs/c/runs/r - bq show --encryption_service_account - - update Updates a dataset, table, view or transfer configuration with this - name. - - See 'bq help load' for more information on specifying the schema. - - Examples: - bq update --description "Dataset description" existing_dataset - bq update --description "My table" existing_dataset.existing_table - bq update -t existing_dataset.existing_table - name:integer,value:string - bq update --destination_kms_key - projects/p/locations/l/keyRings/r/cryptoKeys/k - existing_dataset.existing_table - bq update --view='select 1 as num' existing_dataset.existing_view - (--view_udf_resource=path/to/file.js) - bq update --transfer_config --display_name=name - -p='{"param":"value"}' - projects/p/locations/l/transferConfigs/c - bq update --transfer_config --target_dataset=dataset - --refresh_window_days=5 --update_credentials - projects/p/locations/l/transferConfigs/c - - version Return the version of bq. - - wait Wait some number of seconds for a job to finish. - - Poll job_id until either (1) the job is DONE or (2) the specified - number of seconds have elapsed. Waits forever if unspecified. If no - job_id is specified, and there is only one running job, we poll that - job. - - Examples: - bq wait # Waits forever for the currently running job. - bq wait job_id # Waits forever - bq wait job_id 100 # Waits 100 seconds - bq wait job_id 0 # Polls if a job is done, then returns immediately. - # These may exit with a non-zero status code to indicate "failure": - bq wait --fail_on_error job_id # Succeeds if job succeeds. - bq wait --fail_on_error job_id 100 # Succeeds if job succeeds in 100 - sec. - - Arguments: - job_id: Job ID to wait on. - secs: Number of seconds to wait (must be >= 0). - - - Run 'bq --help' to get help for global flags. - Run 'bq help ' to get help for . - - -## Create a new dataset - -A dataset is contained within a specific [project](https://cloud.google.com/bigquery/docs/projects). Datasets are top-level containers that are used to organize and control access to your [tables](https://cloud.google.com/bigquery/docs/tables) and [views](https://cloud.google.com/bigquery/docs/views). A table or view must belong to a dataset, so you need to create at least one dataset before [loading data into BigQuery](https://cloud.google.com/bigquery/loading-data-into-bigquery). - -First, define a name for your new dataset: - - -```python -dataset_id = "your_new_dataset" -``` - -The command below creates a new dataset in the US using the ID defined above. - -NOTE: In the examples below, the `dataset_id` variable is referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. - - -```python -!bq --location=US mk --dataset $dataset_id -``` - - Dataset 'your-project-id:your_new_dataset' successfully created. - - -## List datasets - -The command below lists lists all datasets in your current project. - - -```python -!bq ls -``` - - datasetId - ------------------------------ - your_new_dataset - - -## Load data from a local file to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Loading Data into BigQuery from a Local Data Source](https://cloud.google.com/bigquery/docs/loading-data-local) in the BigQuery documentation. - - -```python -!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_local_file 'resources/us-states.csv' -``` - - Upload complete. - Waiting on bqjob_r6e3244e44cef905c_00000168c0b8a070_1 ... (2s) Current status: DONE - - -## Load data from Google Cloud Storage to a table - -The example below demonstrates how to load a local CSV file into a new or existing table. See [SourceFormat](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.job.SourceFormat.html#google.cloud.bigquery.job.SourceFormat) in the Python client library documentation for a list of available source formats. For more information, see [Introduction to Loading Data from Cloud Storage](https://cloud.google.com/bigquery/docs/loading-data-cloud-storage) in the BigQuery documentation. - - -```python -!bq --location=US load --autodetect --skip_leading_rows=1 --source_format=CSV {dataset_id}.us_states_gcs 'gs://cloud-samples-data/bigquery/us-states/us-states.csv' -``` - - Waiting on bqjob_r262c33706835e862_00000168c0b8bf2b_1 ... (1s) Current status: DONE - - -## Run a query - -The BigQuery command-line tool has a `query` command for running queries, but it is recommended to use the [Magic command](./BigQuery%20Query%20Magic.ipynb) for this purpose. - -## Cleaning Up - -The following code deletes the dataset created for this tutorial, including all tables in the dataset. - - -```python -!bq rm -r -f --dataset $dataset_id -``` - \ No newline at end of file diff --git a/notebooks/rendered/cloud-storage-client-library.md b/notebooks/rendered/cloud-storage-client-library.md index c9f9cd61015..b0a2b3e371e 100644 --- a/notebooks/rendered/cloud-storage-client-library.md +++ b/notebooks/rendered/cloud-storage-client-library.md @@ -1,5 +1,5 @@ -# Cloud Storage Client Library +# Cloud Storage client library This tutorial shows how to get started with the [Cloud Storage Python client library](https://googleapis.github.io/google-cloud-python/latest/storage/index.html). @@ -23,12 +23,10 @@ Run the following to create a client with your default project: ```python client = storage.Client() + print("Client created using default project: {}".format(client.project)) ``` - Client created using default project: your-project-id - - Alternatively, you can explicitly specify a project when constructing the client: @@ -43,17 +41,14 @@ For more information about naming buckets, see [Bucket name requirements](https: ```python # Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' +bucket_name = "your-new-bucket" # Creates the new bucket bucket = client.create_bucket(bucket_name) -print('Bucket {} created.'.format(bucket.name)) +print("Bucket {} created.".format(bucket.name)) ``` - Bucket your-new-bucket created. - - ## List buckets in a project @@ -65,10 +60,6 @@ for item in buckets: print("\t" + item.name) ``` - Buckets in your-project-id: - your-new-bucket - - ## Get bucket metadata The next cell shows how to get information on metadata of your Cloud Storage buckets. @@ -79,16 +70,11 @@ To learn more about specific bucket properties, see [Bucket Locations](https://c ```python bucket = client.get_bucket(bucket_name) -print('Bucket name: {}'.format(bucket.name)) -print('Bucket location: {}'.format(bucket.location)) -print('Bucket storage class: {}'.format(bucket.storage_class)) +print("Bucket name: {}".format(bucket.name)) +print("Bucket location: {}".format(bucket.location)) +print("Bucket storage class: {}".format(bucket.storage_class)) ``` - Bucket name: your-new-bucket - Bucket location: US - Bucket storage class: STANDARD - - ## Upload a local file to a bucket Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. @@ -99,18 +85,15 @@ For more information, including how to rename an object, see the [Object name re ```python -blob_name = 'us-states.txt' +blob_name = "us-states.txt" blob = bucket.blob(blob_name) -source_file_name = 'resources/us-states.txt' +source_file_name = "resources/us-states.txt" blob.upload_from_filename(source_file_name) -print('File uploaded to {}.'.format(bucket.name)) +print("File uploaded to {}.".format(bucket.name)) ``` - File uploaded to your-new-bucket. - - ## List blobs in a bucket @@ -122,10 +105,6 @@ for item in blobs: print("\t" + item.name) ``` - Blobs in your-new-bucket: - us-states.txt - - ## Get a blob and display metadata See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. @@ -134,31 +113,22 @@ See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metada ```python blob = bucket.get_blob(blob_name) -print('Name: {}'.format(blob.id)) -print('Size: {} bytes'.format(blob.size)) -print('Content type: {}'.format(blob.content_type)) -print('Public URL: {}'.format(blob.public_url)) +print("Name: {}".format(blob.id)) +print("Size: {} bytes".format(blob.size)) +print("Content type: {}".format(blob.content_type)) +print("Public URL: {}".format(blob.public_url)) ``` - Name: your-new-bucket/us-states.txt/1549421467685211 - Size: 637 bytes - Content type: text/plain - Public URL: https://storage.googleapis.com/your-new-bucket/us-states.txt - - ## Download a blob to a local directory ```python -output_file_name = 'resources/downloaded-us-states.txt' +output_file_name = "resources/downloaded-us-states.txt" blob.download_to_filename(output_file_name) -print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) +print("Downloaded blob {} to {}.".format(blob.name, output_file_name)) ``` - Downloaded blob us-states.txt to resources/downloaded-us-states.txt. - - ## Cleaning up ### Delete a blob @@ -168,12 +138,9 @@ print('Downloaded blob {} to {}.'.format(blob.name, output_file_name)) blob = client.get_bucket(bucket_name).get_blob(blob_name) blob.delete() -print('Blob {} deleted.'.format(blob.name)) +print("Blob {} deleted.".format(blob.name)) ``` - Blob us-states.txt deleted. - - ### Delete a bucket Note that the bucket must be empty before it can be deleted. @@ -183,12 +150,9 @@ Note that the bucket must be empty before it can be deleted. bucket = client.get_bucket(bucket_name) bucket.delete() -print('Bucket {} deleted.'.format(bucket.name)) +print("Bucket {} deleted.".format(bucket.name)) ``` - Bucket your-new-bucket deleted. - - ## Next Steps Read more about Cloud Storage in the documentation: diff --git a/notebooks/rendered/storage-command-line-tool.md b/notebooks/rendered/storage-command-line-tool.md new file mode 100644 index 00000000000..5789efae99d --- /dev/null +++ b/notebooks/rendered/storage-command-line-tool.md @@ -0,0 +1,155 @@ + +# Storage command-line tool + +The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. + +## List available commands + +The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: + + +```python +!gsutil help +``` + +## Create a storage bucket + +Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. + +Start by defining a globally unique name. + +For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). + + +```python +# Replace the string below with a unique name for the new bucket +bucket_name = "your-new-bucket" +``` + +NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. + +Next, create the new bucket with the `gsutil mb` command: + + +```python +!gsutil mb gs://{bucket_name}/ +``` + +## List buckets in a project + +Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. + + +```python +# Replace the string below with your project ID +project_id = "your-project-id" +``` + + +```python +!gsutil ls -p $project_id +``` + +The response should look like the following: + +``` +gs://your-new-bucket/ +``` + +## Get bucket metadata + +The next cell shows how to get information on metadata of your Cloud Storage buckets. + +To learn more about specific bucket properties, see [Bucket locations](https://cloud.google.com/storage/docs/locations) and [Storage classes](https://cloud.google.com/storage/docs/storage-classes). + + +```python +!gsutil ls -L -b gs://{bucket_name}/ +``` + +The response should look like the following: +``` +gs://your-new-bucket/ : + Storage class: MULTI_REGIONAL + Location constraint: US + ... +``` + +## Upload a local file to a bucket + +Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. + +An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. + +For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). + + +```python +!gsutil cp resources/us-states.txt gs://{bucket_name}/ +``` + +## List blobs in a bucket + + +```python +!gsutil ls -r gs://{bucket_name}/** +``` + +The response should look like the following: +``` +gs://your-new-bucket/us-states.txt +``` + +## Get a blob and display metadata + +See [Viewing and editing object metadata](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. + + +```python +!gsutil ls -L gs://{bucket_name}/us-states.txt +``` + +The response should look like the following: + +``` +gs://your-new-bucket/us-states.txt: + Creation time: Fri, 08 Feb 2019 05:23:28 GMT + Update time: Fri, 08 Feb 2019 05:23:28 GMT + Storage class: STANDARD + Content-Language: en + Content-Length: 637 + Content-Type: text/plain +... +``` + +## Download a blob to a local directory + + +```python +!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt +``` + +## Cleaning up + +### Delete a blob + + +```python +!gsutil rm gs://{bucket_name}/us-states.txt +``` + +### Delete a bucket + +The following command deletes all objects in the bucket before deleting the bucket itself. + + +```python +!gsutil rm -r gs://{bucket_name}/ +``` + +## Next Steps + +Read more about Cloud Storage in the documentation: ++ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/storage-commands.md b/notebooks/rendered/storage-commands.md deleted file mode 100644 index 91f3e2c8bf9..00000000000 --- a/notebooks/rendered/storage-commands.md +++ /dev/null @@ -1,328 +0,0 @@ - -# Storage Commands - -The [Google Cloud SDK](https://cloud-dot-devsite.googleplex.com/sdk/docs/) provides a set of commands for working with data stored in Cloud Storage. This notebook introduces several `gsutil` commands for interacting with Cloud Storage. Note that shell commands in a notebook must be prepended with a `!`. - -## List available commands - -The `gsutil` command can be used to perform a wide array of tasks. Run the `help` command to view a list of available commands: - - -```python -!gsutil help -``` - - Usage: gsutil [-D] [-DD] [-h header]... [-m] [-o] [-q] [command [opts...] args...] - Available commands: - acl Get, set, or change bucket and/or object ACLs - cat Concatenate object content to stdout - compose Concatenate a sequence of objects into a new composite object. - config Obtain credentials and create configuration file - cors Get or set a CORS JSON document for one or more buckets - cp Copy files and objects - defacl Get, set, or change default ACL on buckets - defstorageclass Get or set the default storage class on buckets - du Display object size usage - hash Calculate file hashes - help Get help about commands and topics - iam Get, set, or change bucket and/or object IAM permissions. - kms Configure Cloud KMS encryption - label Get, set, or change the label configuration of a bucket. - lifecycle Get or set lifecycle configuration for a bucket - logging Configure or retrieve logging on buckets - ls List providers, buckets, or objects - mb Make buckets - mv Move/rename objects and/or subdirectories - notification Configure object change notification - perfdiag Run performance diagnostic - rb Remove buckets - requesterpays Enable or disable requester pays for one or more buckets - retention Provides utilities to interact with Retention Policy feature. - rewrite Rewrite objects - rm Remove objects - rsync Synchronize content of two buckets/directories - setmeta Set metadata on already uploaded objects - signurl Create a signed url - stat Display object status - test Run gsutil unit/integration tests (for developers) - update Update to the latest gsutil release - version Print version info about gsutil - versioning Enable or suspend versioning for one or more buckets - web Set a main page and/or error page for one or more buckets - - Additional help topics: - acls Working With Access Control Lists - anon Accessing Public Data Without Credentials - apis Cloud Storage APIs - crc32c CRC32C and Installing crcmod - creds Credential Types Supporting Various Use Cases - dev Contributing Code to gsutil - encoding Filename encoding and interoperability problems - encryption Using Encryption Keys - metadata Working With Object Metadata - naming Object and Bucket Naming - options Top-Level Command-Line Options - prod Scripting Production Transfers - projects Working With Projects - retries Retry Handling Strategy - security Security and Privacy Considerations - subdirs How Subdirectories Work - support Google Cloud Storage Support - throttling Throttling gsutil - versions Object Versioning and Concurrency Control - wildcards Wildcard Names - - Use gsutil help for detailed help. - -## Create a storage bucket - -Buckets are the basic containers that hold your data. Everything that you store in Cloud Storage must be contained in a bucket. You can use buckets to organize your data and control access to your data. - -Start by defining a globally unique name. - -For more information about naming buckets, see [Bucket name requirements](https://cloud.google.com/storage/docs/naming#requirements). - - -```python -# Replace the string below with a unique name for the new bucket -bucket_name = 'your-new-bucket' -``` - -NOTE: In the examples below, the `bucket_name` and `project_id` variables are referenced in the commands using `{}` and `$`. If you want to avoid creating and using variables, replace these interpolated variables with literal values and remove the `{}` and `$` characters. - -Next, create the new bucket with the `gsutil mb` command: - - -```python -!gsutil mb gs://{bucket_name}/ -``` - - Creating gs://your-new-bucket/... - - -## List buckets in a project - -Replace 'your-project-id' in the cell below with your project ID and run the cell to list the storage buckets in your project. - - -```python -# Replace the string below with your project ID -project_id = 'your-project-id' -``` - - -```python -!gsutil ls -p $project_id -``` - - gs://your-new-bucket/ - - -## Get bucket metadata - -The next cell shows how to get information on metadata of your Cloud Storage buckets. - -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). - - -```python -!gsutil ls -L -b gs://{bucket_name}/ -``` - - gs://your-new-bucket/ : - Storage class: STANDARD - Location constraint: US - Versioning enabled: None - Logging configuration: None - Website configuration: None - CORS configuration: None - Lifecycle configuration: None - Requester Pays enabled: None - Labels: None - Default KMS key: None - Time created: Wed, 06 Feb 2019 02:51:19 GMT - Time updated: Wed, 06 Feb 2019 02:51:19 GMT - Metageneration: 1 - ACL: - [ - { - "entity": "project-owners-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "owners" - }, - "role": "OWNER" - }, - { - "entity": "project-editors-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "editors" - }, - "role": "OWNER" - }, - { - "entity": "project-viewers-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "viewers" - }, - "role": "READER" - } - ] - Default ACL: - [ - { - "entity": "project-owners-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "owners" - }, - "role": "OWNER" - }, - { - "entity": "project-editors-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "editors" - }, - "role": "OWNER" - }, - { - "entity": "project-viewers-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "viewers" - }, - "role": "READER" - } - ] - - -## Upload a local file to a bucket - -Objects are the individual pieces of data that you store in Cloud Storage. Objects are referred to as "blobs" in the Python client library. There is no limit on the number of objects that you can create in a bucket. - -An object's name is treated as a piece of object metadata in Cloud Storage. Object names can contain any combination of Unicode characters (UTF-8 encoded) and must be less than 1024 bytes in length. - -For more information, including how to rename an object, see the [Object name requirements](https://cloud.google.com/storage/docs/naming#objectnames). - - -```python -!gsutil cp resources/us-states.txt gs://{bucket_name}/ -``` - - Copying file://resources/us-states.txt [Content-Type=text/plain]... - - Operation completed over 1 objects/637.0 B. - - -## List blobs in a bucket - - -```python -!gsutil ls -r gs://{bucket_name}/** -``` - - gs://your-new-bucket/us-states.txt - - -## Get a blob and display metadata - -See [documentation](https://cloud.google.com/storage/docs/viewing-editing-metadata) for more information about object metadata. - - -```python -!gsutil ls -L gs://{bucket_name}/us-states.txt -``` - - gs://your-new-bucket/us-states.txt: - Creation time: Wed, 06 Feb 2019 02:51:25 GMT - Update time: Wed, 06 Feb 2019 02:51:25 GMT - Storage class: STANDARD - Content-Language: en - Content-Length: 637 - Content-Type: text/plain - Hash (crc32c): AmYMRQ== - Hash (md5): NmfddAHdCzyvAHCifeGtwg== - ETag: CKeP/OmMpuACEAE= - Generation: 1549421485426599 - Metageneration: 1 - ACL: [ - { - "entity": "project-owners-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "owners" - }, - "role": "OWNER" - }, - { - "entity": "project-editors-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "editors" - }, - "role": "OWNER" - }, - { - "entity": "project-viewers-129776587519", - "projectTeam": { - "projectNumber": "129776587519", - "team": "viewers" - }, - "role": "READER" - }, - { - "email": "user@example.com", - "entity": "user-user@example.com", - "role": "OWNER" - } - ] - TOTAL: 1 objects, 637 bytes (637 B) - - -## Download a blob to a local directory - - -```python -!gsutil cp gs://{bucket_name}/us-states.txt resources/downloaded-us-states.txt -``` - - Copying gs://your-new-bucket/us-states.txt... - - Operation completed over 1 objects/637.0 B. - - -## Cleaning up - -### Delete a blob - - -```python -!gsutil rm gs://{bucket_name}/us-states.txt -``` - - Removing gs://your-new-bucket/us-states.txt... - - Operation completed over 1 objects. - - -### Delete a bucket - -The following command deletes all objects in the bucket before deleting the bucket itself. - - -```python -!gsutil rm -r gs://{bucket_name}/ -``` - - Removing gs://your-new-bucket/... - - -## Next Steps - -Read more about Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) -+ [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png b/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png deleted file mode 100644 index 0bed3d1ad6539a9c5ed68b9b11a6492ed7bf684b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17935 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 diff --git a/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png b/notebooks/rendered/visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png deleted file mode 100644 index b70b433e9adf852f6404b63ed2aa40467b9d1a50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7326 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 J)oHI^{sWfAD^36a diff --git a/notebooks/rendered/visualize-bigquery-public-data.md b/notebooks/rendered/visualize-bigquery-public-data.md deleted file mode 100644 index 39afe255d69..00000000000 --- a/notebooks/rendered/visualize-bigquery-public-data.md +++ /dev/null @@ -1,466 +0,0 @@ - -# Vizualizing BigQuery Data in a Jupyter Notebook - -[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. - -Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. - -## Using Jupyter Magics to Query BigQuery Data - -The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. - -The BigQuery client library provides a cell magic, `%%bigquery`, which runs a SQL query and returns the results as a pandas DataFrame. The following cell executes a query of the BigQuery Natality Public dataset and returns the total births by year. - - -```python -%%bigquery -SELECT - source_year AS year, - COUNT(is_male) AS birth_count -FROM `bigquery-public-data.samples.natality` -GROUP BY year -ORDER BY year DESC -LIMIT 15 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
-
- - - -The following command to runs the same query, but this time save the results to a new variable `total_births`, which is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. - - -```python -%%bigquery total_births -SELECT - source_year AS year, - COUNT(is_male) AS birth_count -FROM `bigquery-public-data.samples.natality` -GROUP BY year -ORDER BY year DESC -LIMIT 15 -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
yearbirth_count
020084255156
120074324008
220064273225
320054145619
420044118907
520034096092
620024027376
720014031531
820004063823
919993963465
1019983945192
1119973884329
1219963894874
1319953903012
1419943956925
-
- - - -The next cell uses the pandas DataFrame.plot() method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. - - -```python -total_births.plot(kind='bar', x='year', y='birth_count'); -``` - - -![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_6_0.png) - - -Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. - - -```python -%%bigquery births_by_weekday -SELECT - wday, - SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, - SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births -FROM `bigquery-public-data.samples.natality` -WHERE wday IS NOT NULL -GROUP BY wday -ORDER BY wday ASC -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
wdaymale_birthsfemale_births
0142935754093357
1260958405831111
2367272176412155
3466187296307782
4565830156284434
5665186366223584
6747619504530052
-
- - - -Visualize the query results using a line chart. - - -```python -births_by_weekday.plot(x='wday'); -``` - - -![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_10_0.png) - - -## Using Python to Query BigQuery Data - -Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas Dataframe, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. - -To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. - - -```python -from google.cloud import bigquery - -client = bigquery.Client() -``` - -Use the [`Client.query()`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). - - -```python -sql = """ -SELECT - plurality, - COUNT(1) AS count, - year -FROM - `bigquery-public-data.samples.natality` -WHERE - NOT IS_NAN(plurality) AND plurality > 1 -GROUP BY - plurality, year -ORDER BY - count DESC -""" -df = client.query(sql).to_dataframe() -df.head() -``` - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pluralitycountyear
021392092007
121388662008
221372392006
321332852005
421323442004
-
- - - -To chart the query results in your DataFrame, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. - - -```python -pivot_table = df.pivot(index='year', columns='plurality', values='count') -pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); -``` - - -![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_16_0.png) - - -Run the following query to retrieve the count of births by the number of gestation weeks. - - -```python -sql = """ -SELECT - gestation_weeks, - COUNT(1) AS count -FROM - `bigquery-public-data.samples.natality` -WHERE - NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 -GROUP BY - gestation_weeks -ORDER BY - gestation_weeks -""" -df = client.query(sql).to_dataframe() -``` - -Finally, chart the query results in your DataFrame. - - -```python -ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) -ax.set_title('Count of Births by Gestation Weeks') -ax.set_xlabel('Gestation Weeks') -ax.set_ylabel('Count'); -``` - - -![png](visualize-bigquery-public-data-resources/visualize-bigquery-public-data_20_0.png) - - -### What's Next - -+ Learn more about writing queries for BigQuery — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. - -+ Explore BigQuery syntax — The preferred dialect for SQL queries in BigQuery is standard SQL, which is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). diff --git a/notebooks/rendered/visualizing-bigquery-public-data.md b/notebooks/rendered/visualizing-bigquery-public-data.md new file mode 100644 index 00000000000..bbd4bb34830 --- /dev/null +++ b/notebooks/rendered/visualizing-bigquery-public-data.md @@ -0,0 +1,146 @@ + +# Vizualizing BigQuery data in a Jupyter notebook + +[BigQuery](https://cloud.google.com/bigquery/docs/) is a petabyte-scale analytics data warehouse that you can use to run SQL queries over vast amounts of data in near realtime. + +Data visualization tools can help you make sense of your BigQuery data and help you analyze the data interactively. You can use visualization tools to help you identify trends, respond to them, and make predictions using your data. In this tutorial, you use the BigQuery Python client library and pandas in a Jupyter notebook to visualize data in the BigQuery natality sample table. + +## Using Jupyter magics to query BigQuery data + +The BigQuery Python client library provides a magic command that allows you to run queries with minimal code. + +The BigQuery client library provides a cell magic, `%%bigquery`. The `%%bigquery` magic runs a SQL query and returns the results as a pandas `DataFrame`. The following cell executes a query of the BigQuery natality public dataset and returns the total births by year. + + +```python +%%bigquery +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + +The following command to runs the same query, but this time the results are saved to a variable. The variable name, `total_births`, is given as an argument to the `%%bigquery`. The results can then be used for further analysis and visualization. + + +```python +%%bigquery total_births +SELECT + source_year AS year, + COUNT(is_male) AS birth_count +FROM `bigquery-public-data.samples.natality` +GROUP BY year +ORDER BY year DESC +LIMIT 15 +``` + +The next cell uses the pandas `DataFrame.plot` method to visualize the query results as a bar chart. See the [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/visualization.html) to learn more about data visualization with pandas. + + +```python +total_births.plot(kind='bar', x='year', y='birth_count'); +``` + +Run the following query to retrieve the number of births by weekday. Because the `wday` (weekday) field allows null values, the query excludes records where wday is null. + + +```python +%%bigquery births_by_weekday +SELECT + wday, + SUM(CASE WHEN is_male THEN 1 ELSE 0 END) AS male_births, + SUM(CASE WHEN is_male THEN 0 ELSE 1 END) AS female_births +FROM `bigquery-public-data.samples.natality` +WHERE wday IS NOT NULL +GROUP BY wday +ORDER BY wday ASC +``` + +Visualize the query results using a line chart. + + +```python +births_by_weekday.plot(x='wday'); +``` + +## Using Python to query BigQuery data + +Magic commands allow you to use minimal syntax to interact with BigQuery. Behind the scenes, `%%bigquery` uses the BigQuery Python client library to run the given query, convert the results to a pandas `Dataframe`, optionally save the results to a variable, and finally display the results. Using the BigQuery Python client library directly instead of through magic commands gives you more control over your queries and allows for more complex configurations. The library's integrations with pandas enable you to combine the power of declarative SQL with imperative code (Python) to perform interesting data analysis, visualization, and transformation tasks. + +To use the BigQuery Python client library, start by importing the library and initializing a client. The BigQuery client is used to send and receive messages from the BigQuery API. + + +```python +from google.cloud import bigquery + +client = bigquery.Client() +``` + +Use the [`Client.query`](https://googleapis.github.io/google-cloud-python/latest/bigquery/generated/google.cloud.bigquery.client.Client.html#google.cloud.bigquery.client.Client.query) method to run a query. Execute the following cell to run a query to retrieve the annual count of plural births by plurality (2 for twins, 3 for triplets, etc.). + + +```python +sql = """ +SELECT + plurality, + COUNT(1) AS count, + year +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(plurality) AND plurality > 1 +GROUP BY + plurality, year +ORDER BY + count DESC +""" +df = client.query(sql).to_dataframe() +df.head() +``` + +To chart the query results in your `DataFrame`, run the following cell to pivot the data and create a stacked bar chart of the count of plural births over time. + + +```python +pivot_table = df.pivot(index='year', columns='plurality', values='count') +pivot_table.plot(kind='bar', stacked=True, figsize=(15, 7)); +``` + +Run the following query to retrieve the count of births by the number of gestation weeks. + + +```python +sql = """ +SELECT + gestation_weeks, + COUNT(1) AS count +FROM + `bigquery-public-data.samples.natality` +WHERE + NOT IS_NAN(gestation_weeks) AND gestation_weeks <> 99 +GROUP BY + gestation_weeks +ORDER BY + gestation_weeks +""" +df = client.query(sql).to_dataframe() +``` + +Finally, chart the query results in your `DataFrame`. + + +```python +ax = df.plot(kind='bar', x='gestation_weeks', y='count', figsize=(15,7)) +ax.set_title('Count of Births by Gestation Weeks') +ax.set_xlabel('Gestation Weeks') +ax.set_ylabel('Count'); +``` + +## What's Next + ++ __Learn more about writing queries for BigQuery__ — [Querying Data](https://cloud.google.com/bigquery/querying-data) in the BigQuery documentation explains how to run queries, create user-defined functions (UDFs), and more. + ++ __Explore BigQuery syntax__ — The preferred dialect for SQL queries in BigQuery is standard SQL. Standard SQL syntax is described in the [SQL Reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/). BigQuery's legacy SQL-like syntax is described in the [Query Reference (legacy SQL)](https://cloud.google.com/bigquery/query-reference). From 8fe80592113581aef969536a1dd7c78b5e388703 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 13:27:44 -0800 Subject: [PATCH 20/24] apply default project and sentence case fixes --- notebooks/rendered/cloud-storage-client-library.md | 13 +++++-------- notebooks/rendered/storage-command-line-tool.md | 4 ++-- ...{BigQuery Basics.ipynb => BigQuery basics.ipynb} | 0 ...Query Magic.ipynb => BigQuery query magic.ipynb} | 0 ...ipynb => Getting started with BigQuery ML.ipynb} | 0 ...ary.ipynb => Cloud Storage client library.ipynb} | 13 +++++-------- .../storage/Storage command-line tool.ipynb | 4 ++-- 7 files changed, 14 insertions(+), 20 deletions(-) rename notebooks/tutorials/bigquery/{BigQuery Basics.ipynb => BigQuery basics.ipynb} (100%) rename notebooks/tutorials/bigquery/{BigQuery Query Magic.ipynb => BigQuery query magic.ipynb} (100%) rename notebooks/tutorials/bigquery/{Getting Started with BigQuery ML.ipynb => Getting started with BigQuery ML.ipynb} (100%) rename notebooks/tutorials/storage/{Cloud Storage Client Library.ipynb => Cloud Storage client library.ipynb} (90%) diff --git a/notebooks/rendered/cloud-storage-client-library.md b/notebooks/rendered/cloud-storage-client-library.md index b0a2b3e371e..7fde6e40117 100644 --- a/notebooks/rendered/cloud-storage-client-library.md +++ b/notebooks/rendered/cloud-storage-client-library.md @@ -14,20 +14,17 @@ Start by importing the library: from google.cloud import storage ``` -Next, initialize a client object, which is used to interact with the Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable. - -See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials. +The `storage.Client` object uses your default project. Alternatively, you can specify a project in the `Client` constructor. For more information about how the default project is determined, see the [google-auth documentation](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html). Run the following to create a client with your default project: ```python client = storage.Client() - print("Client created using default project: {}".format(client.project)) ``` -Alternatively, you can explicitly specify a project when constructing the client: +To explicitly specify a project when constructing the client, set the `project` parameter: ```python @@ -64,7 +61,7 @@ for item in buckets: The next cell shows how to get information on metadata of your Cloud Storage buckets. -To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes). +To learn more about specific bucket properties, see [Bucket locations](https://cloud.google.com/storage/docs/locations) and [Storage classes](https://cloud.google.com/storage/docs/storage-classes). ```python @@ -156,6 +153,6 @@ print("Bucket {} deleted.".format(bucket.name)) ## Next Steps Read more about Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Storage key terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-to guides](https://cloud.google.com/storage/docs/how-to) + [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/rendered/storage-command-line-tool.md b/notebooks/rendered/storage-command-line-tool.md index 5789efae99d..d6fffa759de 100644 --- a/notebooks/rendered/storage-command-line-tool.md +++ b/notebooks/rendered/storage-command-line-tool.md @@ -150,6 +150,6 @@ The following command deletes all objects in the bucket before deleting the buck ## Next Steps Read more about Cloud Storage in the documentation: -+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms) -+ [How-To Guides](https://cloud.google.com/storage/docs/how-to) ++ [Storage key terms](https://cloud.google.com/storage/docs/key-terms) ++ [How-to guides](https://cloud.google.com/storage/docs/how-to) + [Pricing](https://cloud.google.com/storage/pricing) diff --git a/notebooks/tutorials/bigquery/BigQuery Basics.ipynb b/notebooks/tutorials/bigquery/BigQuery basics.ipynb similarity index 100% rename from notebooks/tutorials/bigquery/BigQuery Basics.ipynb rename to notebooks/tutorials/bigquery/BigQuery basics.ipynb diff --git a/notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb b/notebooks/tutorials/bigquery/BigQuery query magic.ipynb similarity index 100% rename from notebooks/tutorials/bigquery/BigQuery Query Magic.ipynb rename to notebooks/tutorials/bigquery/BigQuery query magic.ipynb diff --git a/notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb b/notebooks/tutorials/bigquery/Getting started with BigQuery ML.ipynb similarity index 100% rename from notebooks/tutorials/bigquery/Getting Started with BigQuery ML.ipynb rename to notebooks/tutorials/bigquery/Getting started with BigQuery ML.ipynb diff --git a/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb b/notebooks/tutorials/storage/Cloud Storage client library.ipynb similarity index 90% rename from notebooks/tutorials/storage/Cloud Storage Client Library.ipynb rename to notebooks/tutorials/storage/Cloud Storage client library.ipynb index 8e275a7ea63..34f747b5786 100644 --- a/notebooks/tutorials/storage/Cloud Storage Client Library.ipynb +++ b/notebooks/tutorials/storage/Cloud Storage client library.ipynb @@ -33,9 +33,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Next, initialize a client object, which is used to interact with the Cloud Storage API. The project used by the client will default to the project associated with the credentials file stored in the `GOOGLE_APPLICATION_CREDENTIALS` environment variable.\n", - "\n", - "See the [google-auth](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html) for more information about Application Default Credentials.\n", + "The `storage.Client` object uses your default project. Alternatively, you can specify a project in the `Client` constructor. For more information about how the default project is determined, see the [google-auth documentation](https://google-auth.readthedocs.io/en/latest/reference/google.auth.html).\n", "\n", "Run the following to create a client with your default project:" ] @@ -47,7 +45,6 @@ "outputs": [], "source": [ "client = storage.Client()\n", - "\n", "print(\"Client created using default project: {}\".format(client.project))" ] }, @@ -55,7 +52,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Alternatively, you can explicitly specify a project when constructing the client:" + "To explicitly specify a project when constructing the client, set the `project` parameter:" ] }, { @@ -119,7 +116,7 @@ "\n", "The next cell shows how to get information on metadata of your Cloud Storage buckets.\n", "\n", - "To learn more about specific bucket properties, see [Bucket Locations](https://cloud.google.com/storage/docs/locations) and [Storage Classes](https://cloud.google.com/storage/docs/storage-classes)." + "To learn more about specific bucket properties, see [Bucket locations](https://cloud.google.com/storage/docs/locations) and [Storage classes](https://cloud.google.com/storage/docs/storage-classes)." ] }, { @@ -285,8 +282,8 @@ "## Next Steps\n", "\n", "Read more about Cloud Storage in the documentation:\n", - "+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms)\n", - "+ [How-To Guides](https://cloud.google.com/storage/docs/how-to)\n", + "+ [Storage key terms](https://cloud.google.com/storage/docs/key-terms)\n", + "+ [How-to guides](https://cloud.google.com/storage/docs/how-to)\n", "+ [Pricing](https://cloud.google.com/storage/pricing)" ] } diff --git a/notebooks/tutorials/storage/Storage command-line tool.ipynb b/notebooks/tutorials/storage/Storage command-line tool.ipynb index a4a2d44f9f9..21e62ae8236 100644 --- a/notebooks/tutorials/storage/Storage command-line tool.ipynb +++ b/notebooks/tutorials/storage/Storage command-line tool.ipynb @@ -298,8 +298,8 @@ "## Next Steps\n", "\n", "Read more about Cloud Storage in the documentation:\n", - "+ [Storage Key Terms](https://cloud.google.com/storage/docs/key-terms)\n", - "+ [How-To Guides](https://cloud.google.com/storage/docs/how-to)\n", + "+ [Storage key terms](https://cloud.google.com/storage/docs/key-terms)\n", + "+ [How-to guides](https://cloud.google.com/storage/docs/how-to)\n", "+ [Pricing](https://cloud.google.com/storage/pricing)" ] } From f33463a87fc68e622fd1d257f5dc4bb21e417492 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 18:22:09 -0800 Subject: [PATCH 21/24] fixes bqml resources --- .../getting-started-with-bigquery-ml.md | 19 ++++---- .../Getting started with BigQuery ML.ipynb | 43 ++++++------------ .../bigquery/resources/model-evaluation.png | Bin 0 -> 11193 bytes .../resources/purchase-predictions.png | Bin 0 -> 41932 bytes .../resources/training-statistics.png | Bin 0 -> 49904 bytes .../resources/transaction-predictions.png | Bin 0 -> 23642 bytes 6 files changed, 26 insertions(+), 36 deletions(-) create mode 100644 notebooks/tutorials/bigquery/resources/model-evaluation.png create mode 100644 notebooks/tutorials/bigquery/resources/purchase-predictions.png create mode 100644 notebooks/tutorials/bigquery/resources/training-statistics.png create mode 100644 notebooks/tutorials/bigquery/resources/transaction-predictions.png diff --git a/notebooks/rendered/getting-started-with-bigquery-ml.md b/notebooks/rendered/getting-started-with-bigquery-ml.md index 9acbc5caad2..b59f5f9b0b5 100644 --- a/notebooks/rendered/getting-started-with-bigquery-ml.md +++ b/notebooks/rendered/getting-started-with-bigquery-ml.md @@ -70,7 +70,7 @@ table, you do not see query results. The output is an empty `DataFrame`. ## Get training statistics To see the results of the model training, you can use the -[`ML.TRAINING_INFO`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train) +[`ML.TRAINING_INFO`](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train) function, or you can view the statistics in the BigQuery web UI. This functionality is not currently available in the BigQuery Classic web UI. In this tutorial, you use the `ML.TRAINING_INFO` function. @@ -100,7 +100,8 @@ FROM Note: Typically, it is not a best practice to use a `SELECT *` query. Because the model output is a small table, this query does not process a large amount of data. As a result, the cost is minimal. When the query is complete, the results appear below the query. The results should look like the following: -![image.png](attachment:image.png) + +![Training statistics table](../tutorials/bigquery/resources/training-statistics.png) The `loss` column represents the loss metric calculated after the given iteration on the training dataset. Since you performed a logistic regression, this column @@ -109,13 +110,13 @@ The `eval_loss` column is the same loss metric calculated on the holdout dataset (data that is held back from training to validate the model). For more details on the `ML.TRAINING_INFO` function, see the -[BigQuery ML syntax reference](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train). +[BigQuery ML syntax reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train). ## Evaluate your model After creating your model, you evaluate the performance of the classifier using -the [`ML.EVALUATE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-evaluate) -function. You can also use the [`ML.ROC_CURVE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-roc) +the [`ML.EVALUATE`](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-evaluate) +function. You can also use the [`ML.ROC_CURVE`](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-roc) function for logistic regression specific metrics. A classifier is one of a set of enumerated target values for a label. For @@ -145,7 +146,8 @@ FROM ML.EVALUATE(MODEL `bqml_tutorial.sample_model`, ( When the query is complete, the results appear below the query. The results should look like the following: -![image.png](attachment:image.png) + +![Model evaluation results table](../tutorials/bigquery/resources/model-evaluation.png) Because you performed a logistic regression, the results include the following columns: @@ -191,7 +193,7 @@ When the query is complete, the results appear below the query. The results should look like the following. Because model training is not deterministic, your results may differ. -![image.png](attachment:image.png) +![Model predictions table](../tutorials/bigquery/resources/model-predictions.png) In the next example, you try to predict the number of transactions each website visitor will make. This query is identical to the previous query except for the @@ -224,7 +226,8 @@ FROM ML.PREDICT(MODEL `bqml_tutorial.sample_model`, ( When the query is complete, the results appear below the query. The results should look like the following: -![image.png](attachment:image.png) + +![Purchase predictions table](../tutorials/bigquery/resources/purchase-predictions.png) ## Cleaning up diff --git a/notebooks/tutorials/bigquery/Getting started with BigQuery ML.ipynb b/notebooks/tutorials/bigquery/Getting started with BigQuery ML.ipynb index 7d535e942f0..e3f8625f10e 100644 --- a/notebooks/tutorials/bigquery/Getting started with BigQuery ML.ipynb +++ b/notebooks/tutorials/bigquery/Getting started with BigQuery ML.ipynb @@ -112,7 +112,7 @@ "## Get training statistics\n", "\n", "To see the results of the model training, you can use the\n", - "[`ML.TRAINING_INFO`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train)\n", + "[`ML.TRAINING_INFO`](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train)\n", "function, or you can view the statistics in the BigQuery web UI. This functionality\n", "is not currently available in the BigQuery Classic web UI.\n", "In this tutorial, you use the `ML.TRAINING_INFO` function.\n", @@ -152,16 +152,13 @@ ] }, { - "attachments": { - "image.png": { - "image/png": "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" - } - }, + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "When the query is complete, the results appear below the query. The results should look like the following:\n", - "![image.png](attachment:image.png)" + "\n", + "![Training statistics table](./resources/training-statistics.png)" ] }, { @@ -175,7 +172,7 @@ "the holdout dataset (data that is held back from training to validate the model).\n", "\n", "For more details on the `ML.TRAINING_INFO` function, see the\n", - "[BigQuery ML syntax reference](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train)." + "[BigQuery ML syntax reference](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-train)." ] }, { @@ -185,8 +182,8 @@ "## Evaluate your model\n", "\n", "After creating your model, you evaluate the performance of the classifier using\n", - "the [`ML.EVALUATE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-evaluate)\n", - "function. You can also use the [`ML.ROC_CURVE`](/bigquery/docs/reference/standard-sql/bigqueryml-syntax-roc)\n", + "the [`ML.EVALUATE`](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-evaluate)\n", + "function. You can also use the [`ML.ROC_CURVE`](https://cloud.google.com/bigquery/docs/reference/standard-sql/bigqueryml-syntax-roc)\n", "function for logistic regression specific metrics.\n", "\n", "A classifier is one of a set of enumerated target values for a label. For\n", @@ -220,17 +217,14 @@ ] }, { - "attachments": { - "image.png": { - "image/png": "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" - } - }, + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "When the query is complete, the results appear below the query. The\n", "results should look like the following:\n", - "![image.png](attachment:image.png)" + "\n", + "![Model evaluation results table](./resources/model-evaluation.png)" ] }, { @@ -287,11 +281,7 @@ ] }, { - "attachments": { - "image.png": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYkAAAFOCAYAAABzMOGxAAAgAElEQVR4Aey9P3CkSpb/+9WLFwFjFWuJtcSzxLPEWmIt8bPEWmIssVazVrOWGKtrvfK6xhJjNRvxIpqxmms1YzVjiWs112qu1VyraatpS7QlZOWLpP6XSn9KXfpT0qmIUvEn85yTn0zykCcTscEYY6APESACRIAIEIEFBP6vBcfoEBEgAkSACBCBlgA5CWoIRIAIEAEicCkBchKXoqETRIAIEAEiQE6C2gARIAJEgAhcSoCcxKVo6AQRIAJEgAiQk6A2QASIABEgApcSICdxKRo6QQSIABEgAv/3bRBsbGzcJhvlIQJEgAgQgUdAYJnH427lJHgZl1FyFRPucFYl6yo9dO5xE6B28Ljrh6x7OgSWvcmncNPTqXsqCREgAkRg5QTISawcKQkkAkSACDwdAuQknk5dUkmIABEgAisnQE5i5UhJIBEgAkTg6RAgJ/F06pJKQgSIABFYOQFyEitHSgKJABEgAk+HADmJp1OXVBIiQASIwMoJkJNYOVIS+PQIVAgMEXx9ueQka1C8GLa4gY0NEWZYD+wtApiKCEl1EFcPW4Sir7UsNxQP2cOacgvtC9jeQso6ZSEnsU619SC2lvB1EQ96QVchTOnnOugmcSBPd5oPwvIBlVY58q/n+FHmKIZ+40bWrID9jfRQokdL4NZPXD/aEpFhqyVQRIjyc0BerdhlpFVJhPQHIC6TaSZtgyRM8H3m2DPbMXykJyZKUYeh3rzsP89+sS4BwPniU3T0kRGgkcSjqJAGRdyFrauQRRGiJEPRTLhRMbauySN4lg5FEiGKEhTdghfmmNwUDu/4NzYgu+k4H8oARht6kDE+nLpQNjYgmiGyuAtLUyBxvbIGs5ugHOau0z4ss4ff+NX89W/4941BCMOOGwCjEIyGflEjD10YigRR9fD/eeognCBZiCYGoo4sSK0MDf18YuLlWzXywIbp/bPtUH78/T8GckUDwShkUmcIXBMa1y1KkFUddjdGwU3kn6ZA5BpwfuEu4hz//K9/GcjQ+hiYwG3vwjY0qDKXIUJSdFjdGOVIxlDUjX+GfDe0PtLUh60P+MqqCS8e0eXShqELxUXalIg9E6okQh6HtEbtYlg/kgLN8hDls4bV2ZyOqIIozVmbejD/z5/xH4aFYNKsgGqaHy+7CsP2kdZLsB9yk1UDdj/FqGoGFgzLJfN2rUC3feSYN27O1pndISNe51mCrqUNrhFZgzWtq45gDkNsg/Y5ENJEFkTe5kQLbbMFMAh3iTCCCgN2MkRRhz+umhJJ34Ghyu11IckKNMNBMMddQg7fHl6Tw7KlU+0duFnbqlIfjqFCbq9tGYpqwPJCZGNZN2gHvJ171vA6ENHabDroJ+NCzVBdaofd4jP41023yLggyyplLRC/Foe+vN1nmwDjLACBCe1vh+2//dbaf/bpmO11ps4Lk+3d1x/ZWZvqCzveFVoZmy9PJuX+8obttek32fjwyUu2NdYlsM3tXbaz3Rnr3zv+0ub/+HqPbW8OZELYZNs7O2xnZ5cdnXCN39ibPX5OYDv7e2P7hd3X7PPn12xnWIbD96dDW07Z+8OBjjbNxMJ2a3E7+MzeHOywrVHZO1tsh9uw+4K1Ys9O2NHO0D6ACcJku7P3hn3mkr+9Yy92t1intQess8XLsMN2D9+wQSlP2YeXWwxCh21t83OTtNtHJ0O2o7KCdV58mLN8we40Xy53Z5ftjDnusFcfBzXG2Ht22NbNNtvf3xryB9s6+tgK/fL2YMi1w7Z399je9uYgTWefvRkYz9i3t2x/xKdlgLYsnVauwPbfDvmPbBJ22XELhjF2esKOtifMxvy2j9hHdnP2wuYO29vbZVtDndsvT9hA6xn7eLQ9bM+Dts3rudMZtrUtrue6z4jRoH55/e1ubw5lCmxvVJjTd2x/qP/w/YgvY2fvDgZphQM2Ovz59U7LsbO7z3ZH7IR9NkD1jb0/nNQFhOH1OOY2skcYlkNgnal2t3nwblh2Xq4btK2p+mvb5vYWa+tu64i1lxlj7Pp2wDkPbR5ep4Prltf/oA+Zprz4WptOMbvN/7ne0p9llVylYJWyrtLzaM+dnbCXW4NOf3P/Dfvctu9T9uXjyXj73cHwotp+yT60dX7KTo52ho1/nw3awW2cBNj2yw/DRv157GSE/bds1LQ+v94d6LlwQU86Tu4otg9esbcfTtjJp2/sjH1hx60DAescvh/IP3vPDtsLkl/Yox5uUiuXt4NT9nZ/0JHNd9Bf3uwNGeyyVx8H3dK39y/YdusQNtnEQU10jzvNiWrGzk7Z6RljZ/z39Bv7+GrIdlzmSVnnbZgWM94edcgQ2O7rzwNHwx3a9rCeX3wYOp9Rh8OPb7G9ozfs/ckJ+/iFGzNqF1MdIfvG3g7bwsiRjDo8CDvs6IQzOGOfx87laicx4bfDjgYNi519+9TW4aAsN2C/9YJ9GPqhs49Hg5sD3uHyBnQ64g62efB20J6/TTn2Md8xuQUbE0ad/bdjx/7+cOgwW4fGdS3vJHib6+wcstfvPrCTk0+DNv/p1bD9dNje64/DtvuFfTz5NLxOJvZg6wV7314oU46lczh2Rm1hrmtb47ayzY5GNw+nX9jHT8Mr8EbtYNI+J9fuGfv26SPjTWn+c/m1Np9ysE/hpqXGXXeQuEiQfuVyN2F1Xaht4J2Hk4zhdo40+9Eq3nE8mO3cgASj60JvA7sp4nQ2/HBzK7dgOuZw8K9C04cTD3U9Fca6gbQdD1Hch2MaMDQZIhTYjgFu3g8+n9AATRq38woQdNi2cgOh1yVpkCVZG4YSdAeePghhyJYHa4fn/Y40uUFMi4d5eg4MRcSf/vQv+Jd/+Vf8+19/H8TLl+VwwWQFhqkO5lJEA5ax1ab4nufjkN4oy9bLEInvwjIM6IoIFAmytl2I4GE/x3HgOF0k1WBmpioKVDyckQ1iR4LuomtwBiJUx4O1OZJ82e80PxfdQcNqQ468Dq/+TPICJSKP2+bADQo0bZsskPMoR5khb5vuFizPGbRn2YDn6m3buFrH/FkBmmVg0HIkmLaBDk9S5shn41vzGS/fF/bQjyN0bROGobXTbmWWDeqmY8D19MG1ISrQDe1CkGzH9mC1qGSY9rBMTY16dDnepG2pBrS2IH/gb4YG0/WRVBL0UR3cqB3I0PQBmfN/utB0G90wB1QdvCn97Icmrn+W4M/mH3dEMpRF12ZTo2pjkwIkaSqWK8njueS6HgcvF1jTYNRmL5wUZMhTIift6dIcF0TwAx3e0OfOyJYDy/snfvmRIEoqiPFg4rhjOMMLay7D0rs1xsWW5akLWIYitT0VOBdekkm5LirJfQs2dwrCFvZf9eAaMpqkC+dvQ0dxMcvNjwgSpCnl0min5t379EeAqmuzdtb1MLb/A7//4+/4fTo53254yZoxA1GetAdAgsTb0pUz9Zfxm1e0aH8q79df8fe//zqXqBmaN7zZEGbbtjzdjudyXrXL55xGH1GSWl4/0KDhMBddOy2hUY4Fv7IGbe5+pS7rwQ0Cv76m6u5ibgGyOlEqioN2Nj0Zf6O2JdsI4wqO28M//vgD//zfv+Cf/9vH7qsISd+AdKN2AOi9GO9qF174K77/9gv++tsv8PuHCOIQzuDO82IRbniERhI3BHVnyfhEaSu8RrnojohPxrYJzttOb2xHXY0nCOXpnr7tP6Y6+apENd1yxwIGG1deB3NpL91dJESy4LS3sz+Qxj6ilPdYHRiOddn1fKn4xSckjPuaarrTrVDWgwJzp7rItIm8EmlcDEYjZh9R34FlmtDVSWc0SXuLrfNq6OB53gbVwNuD9+DXapCkYZptvPrI2neu8PeujL5N6oKP2UYMmvHNBtc11YlfavYkL2b4XZph6sQkr3DwDqdTdg3s44sauHcetu0ZDphtx1NSr9usq8kFwrcHjpZPiA9yjuq6aR3o4Fi18KK6XJMki4NRDuc5dRktzjHSuOjszduWZHiIixKfPxzjxS4fAn7Hb3910ecPkdyoHXDWKuwgRVl+xNujfWwJwPkfv8DrxnM3JItsvfoYOYmr+dz92fFw8yvifjBcldOgykKE7VIJDaYxiB38HvaHD0LVyPwQGe8LBQOGzhvrpNP8kcVoszYlIj9GG7W4ZUn4HVL7qUuU7VXZ3ODi4TlEGK4NHmD5noRIuBGbJhzz2u5xqHDyM7KhKctBKKAd0oswrEFI6zwL4A+XlVRJgLi97d6EYY7GN3xFGJd3jqoo29EF71TbUcaofM1wxNXkiMJBGGtiwW23viL2o3aVVFNGCJLBrf2mpg3DJlfIVU0MolN/IOIyppJWeYKs7S8lqPpgPet5GqA/XA5TxcGA91Sei5sStFHeLEA/GXbAdYEkiDFaALWYvQTdHIRXzhMfwWQZDtCUSNNiMHqdbtujMtQ5wug2fM+RRwFSbmaTIwjSwR2/oqONzIh8ZRov5TmyOBncQFUJ/DAfpLsIYOERRRuEnfAjge9ngw62qZDHIZZdKDRix4dVrb9Z1LaqHGnO26IE1fQQxn3s84Ew+M0OgBu1gwYFD5M1gCjrcPwEoTsIbTb8JnFhSZc4uHiq4uqjy058XCVtlbKu0vN4z51NJkpHK46GqzR2RxO8n99cvrrp1Wh1E2PjiUguR+gMVkkIm2yznTBesLppvGJjQGe0QmJm9dF4Yo3LHKzk2GuX1kwmyy6fzP3EXu0MJmt5PW+OJ2wv1sZV7YBPzg5WfPEVLh0mCDvs1Sc+R/uRvRqu6OL5x6tz+ITkaHVTq2pia5uuIzBh8yXja8A+jSapIbDN4SokYXNrsKqo84IN1jJN8l9e1qkyjZkJTOB1OVoh09YLt300mziaBJ2aYJ4S8+XdwXAVGpiwud2uytre5IsYNtmL0QK2L9OrmwQmdATGV6IN6nxK7sim6Tr/9o4dbE7qZ8xvc1Ruxq5kP15Zxldw7bCd4cocYe94OMF8xk6mVze1dQe2uTmcdF5y4rplOV79x+3usEFb5NBO2bvRZHbbFjptmxE2Nwcr2xasbsJC/Z/Zm73hQpG2vkarDbcHbW68Im2KLVf/4XCoZ7RK6oZt6+Rl29ba+t3dZTtbw9VmnYPhghTGrm8Hw/Y5XEm3u7vNNts+BGx7uFJuqlm1K7um96/bppHEEg71bpKK0PsJkuMX2NveREc4xzk2sb1nt/HxVqfqIsne49XhLrbbQUUHWzv7ePk2Q9LXxyEVxQ0Rv9rHzqbQDpkl7RDHSQrfaGfGbme+0UP4ah/bm3z8ymO/PI5709GABsfZHU5SbsFyjLGtyxijugH6hzsYm6Bq0LgJoo5+kuHt0QF2tgZl7Gzt4uDVO2SJi8kzYzKcIMCL3S102rs0fgc+uGPUeiGCF7vYFM7xvSh5cBdJHsHZXsbCS9IKOnrhaxzy8JXQwebOAV7FMfraaPhySb7hYcWOkZ4c48XeDqSmxO+/88lqGXuHDsZz/4qDKD7G4c4mBAGQFBOvkwzh9TPXgGwjSt/h1cEutjoCzs+BztYODhx7PMd0Jft0wH53S0T1++8oyhqSug/bNoYhRRFGP0b4cg/bHQGCKEF33iJJu9hr6+Hq8s+eFWD23+PVvgJJEMDr+fA4RuSOJhUk2EGE14eDsvAYlHrwCnEawr52En9akwo3TvH25X7bpoQBFOweujBHqqaTX7F9o7alGLD3dyDz+v3tNxS1jJ39l3iThHCGUx7XtwMJmmVhTxFRF7/hN75qQNnF4av3bf9whYk3OrXBvciNUk4lWuX7iFcpa8pE2nwkBEpfh/qX33C+dYSPpQ/9ErueVDvgD9P9n//FV2EXx0UGb8nO5RJEz/Qwf5juz/jlXMD+2wqJc9MblGeK6wbFXvZao5HEDaBSktsRqPMAXv+3dgCyYzuXOojbSX/AXE0Eu306ls91zH6V8WPtQ/uunfx8wHI8CtUlAmPwpPs8S3H8VPyjMPTZGkFLYJ9t1d9hwfMuVP2v+GO4qkrYeoF+dzSJfId670u0aMHPC/QX6eNrT/No0Rk6tpCAAifKYS5ypvzfz2DqX8wszE8H75oAOYm7Jvws5fPnA3gMWoZmuuj1u7jFoqZHTE6ErFAMaVUVJMrK9au9VqWM5CxNgOYklkZGGe6CwLJx0ruwgWQSgedAYNlrjeYknkOroDISASJABG5JgJzELcFRNiJABIjAcyBATuI51DKVkQgQASJwSwK3nrjmca1VfVYpa1U2kZz7J0Dt4P6Zk0YicB2BWzuJWzyDt9CWZSdRFgqhg2tPgNrB2lchFWBNCCx7M0bhpjWpWDKTCBABIvAQBMhJPAR10kkEiAARWBMC5CTWpKLITCJABIjAQxAgJ/EQ1EknESACRGBNCJCTWJOKIjOJABEgAg9BgJzEQ1AnnUSACBCBNSFATmJNKorMJAJEgAg8BIHVO4kyQdfSofD/ty/x/wLqISoW/R/ga4pbRzBFGc4l/ymYv3xEtKIlX/Kdo6vJMMPpNwZfY8eSp5vIgii7V/6D4zoL4Joa5PadBDIUVYflBph+VfCSap9w8hp51IWtq5D5uxskBbrVv/i+4TpD4BjDdqdAt/uD9yFPk6lzBK4BVZ60zTBvX9w9nYq2iQARmCKwWidRp3BNC3/9x2/4+uMc5z++4/d//g3/aTqIf/pt3FNW33pTgqbxF6dPvd2q9GGYwc+/LPymNpUBLNNDKtnw4xRpEqLvWZBq/hbzkZAMnmYjvo1vDS3o3XwkaO1/69iF1c0g2X1EWY486cOofVhWF9mYT4nQNtEtVPTiDFniw6oDWFYfExIFfMtAr9DQizLkaQRPzdA1bQR3d8+w9vypAEQA170Ee9H5y15a/+3N3uCF9Z09dvzpjJ19e8cOtwYvWt95zd9cf/FzmSx2+o7tC1MvfJ/L+uFFhwkH79jp3PFld78c77HO3hv2bdmMl6Q/e3fAhM2XbPSe+vlkX453mbD1kp2czZ+Z7J99esV2Ogfs/RVpJqmnt07Zu4MO23m1mPV0yse2fWk7YGfsdL6SvxyzXWGLjd/x/vGIbQu77PjzVKlO37PDzU12+H6Y+eMR2xL22JuZij5l7w832dbLE7Y06ilVtEkE1onA5dfa4lKscCRRI02y9lWVguHC0USIsg3P2mpdcRGnKO7QKSeODK2bIPUdGOrgdYiyasANC4xvOJGhq4owAj6sqZG4KrS//Iofv/43/nVjAxsbCsZvn2xyhKPQRPvynC7i+TvOKkXf1oYhDhWGEyBrxsOBq0t7SbIqstu3uv3+4x/485+4TRvQ+kNyPKTiWtBVBZIoQpI1WN1kOArK0NcU/Oc/fuD3v/5bm29DtBGPrLiuPE2B2LOgKUN2igbD9h9BCEyENDXwa4sjyZDRgA+++KdIM5SqBVMd7Ld/JQOW3iCNB2OJuihQKRq04cvlByklmLaBOo2nRhxTMmiTCBABrNBJlCjLwfsqFUXB6LpWNBUCgPMix3wfu1r+DX73HXQLE35WoWkqpD0ZiWuhN4k5TKmUYPoZkqNtCHvH+Hx2hrOzAoHBk5QILRNepqAb5SjyCK4Uw+ZhopHHaXL0TRP90kA/yVFkITw1httNpnRc3FRMC1oVoevFKEeyppLJdog8eoFN4QDvTrlNZ8i6o96vQlGrcP0IWZEj6WsofBtuxOPqOrwsw/GugO1XH3HKy1OHsFrZ15eHy7ETCV6YoeCywy4sTcF0ZG7KzAfdbPIUOTQYQyxlUQCKOvd2MwmKKqMui7bdiZIEsa7HjmVUgKZpgLJEtaAuRmnolwg8awKLBxhXH108XPnIjtrQksB2Xk/G/W34BWAQDti7+bDB4L8ELla2ZLiJh59wIYzzmb3eEdju8Zehjo/s1bbA9qZiDp9ebTNhLtx0dvKSbQk7bKoYjPHwRafDDt4OCnH24QXbFPbYWHSrgYcvOgxXhJt4si/vX7LdTTBhc4cdHL1hH77MBTtOuOybhJu+sTd7Atsax12+sOM94UK46Sbl4fw2D98/WNhlcZta1DQ+s+O9Dtt68WEYajxj7w8E1nnx4ULiz693mbDzmrWt8ds7drDZYbuvTti3FvcZ+3JyzA62O4O2OVcFF4TRASLwRAjc/FobFHiFI4mH97WCqkObCeNIbaiirpZbwVJmGSrFnAtfaNDVBnk2GJYUaY5aNWHOvOpYgm5o7cjpKhqKFSArPyPuGUDaxX+oKsx+tuRKLa5BhiwD7d3wFQpvUh7dcSDHLgynjzh/FKsMFpSoRura6FU2Qt8cj1YXJLx4SLYRRl1IsYV/Ha4qM/oVHNeAIPJ3cl/MQkeIABHAKsNN0jA0cY5mqlOu+XCef3gMfckLsU1+TRhgRiQPKaygVquqxvkfPnS+5HL8VdH97Ryj8tR1De6BRmG1kVrpQgB9dGbuV1Rhuj7ivMSnvoq8Z6M7jmXNpR3uNmWMvmO2cxKyzB2EDCcehPgW5xgcvUl5JMNHmgewEMPTFci604btrpJ7v+dqZH0TVqzAjwMYY/B8OauEpm6m5p4Glo3qaNQmJKOLpKhxVpWo6hpl0ofaVAtCVfdbMtJGBB4zgVu/T+JioRSoagf4/QfKskQNve1Ay7xoJ7OhaFBGV+vFzBeP8A5YrFG3s5PzGQfH2zjzxZw/fUQSJQg7NpLYnYtzA5AGM58S93g8xt3ez09UjpzI5Mh1WxI0rwc7MJBmJcaB9vlsdQzXsJEbIcLUgiZzJg0iS4I3n3Zu/ybl4Vkk1UI3tND1c0RdF65hocn5ZP+cwHvfbZD7FixfQi+J4MzZo2oKEA7mHianapRFBVFRMDNXze9XJHl4M1EhTXLIev9iPd97GUkhEXicBFYYbhKhmzo6fJI6DRDyB+iqGH78tS35tmFgcgHfBIYGQxeRRtHFZxiqGGEqwjD1mwi6Jo3I4zUzd6GqqUMuc5SiAj4JP/MdDodUXYNYpHMPbDXI03zgFK/ROnO64U4PkMezxAOnOBqEtWlbXRqcnj10EPxogXxmNYDYdn6zpQFuUp4ZeyQNduDDUXKkD/6EX4MisGD2gW4Sw5uNJ7ZmK7xtFfHsA3Z1ijhD20bmbzFGZa3THvxMhe0aKxmBjuTSLxF4SgRWOJIAZLsH10/x199/xV/+3z/hLyNSm/voest26DLsfheB4cGwKnT5clQJqMsUQa+HTOsjs8Yxh5GmpX8VXYXoh/ATs+2ARFGBbHTR1XV4po2658JQeDijQpnngNmFrQKi6cFVDfTsLmTfhSbVKOI+vLiGcFmvBCDt24hFE4bKVw6JaOoCid9DJNqIrOE9r6pBRRdBkEJ3+KSHDEXmq3dCRH4Cw9MgNQWSfm/uIUUJqiqjjANEtgyDx94VGTzMcl158rCLTBqGsqQGReIjKVU42s8zXrpSpjKUoQ3Ty6H1Aqh1hnT6CXxRga4rEDUPXTOEa3uDuhBLxD0PseQgnWojfKVTLfJVTiWyJECvF0PyEnS1KYW0SQSIwCyB20zYXzk7/u2EvT7cZVsdgQnCJtvee8neflqwrGmo+EpZjLHTT2/Z0cFInsA2t3fZ4av37PPcapT24boLq3MGq3+2xw+XXVzdxNgX9u7lLtsSBCZ0ttnR6Cm4s8/s3dEB29nqtA8ICp0ttntwxN6PFkpx+798YK8Odthmm3eL7R6+Zh/eH7FtvsrqErCf375geztbbR5AYJ3Nbbb34vXcCqcz9unNIdvZ5Aw7bLd9EPGMfX73ku1td5ggCKyzvcdevP3EPh3vtQ+DjdV9+8CO9rZYh9u09YKNniVj15SntWt7k3UEvhKtw7Z2D9ir91/ubbXT4nZwyt7uC4yfW/QVdo/ZuDpOP7G3L/fYNm93nU22c/Bqtq4YYx9f7QzrkrfLQ/bq3ed7K9+4fmiDCDwwgcXX2uVGbfBTs27j+r1Vvo94lbKut5xSPFYC1A4ea82QXU+NwLLX2grnJJ4aSioPESACRIAIkJOgNkAEiAARIAKXEiAncSkaOkEEiAARIALkJKgNEAEiQASIwKUEyElcioZOEAEiQASIADkJagNEgAgQASJwKQFyEpeioRNEgAgQASJw6yeu+VrbVX1WKWtVNpGc+ydA7eD+mZNGInAdgVs7iVs8g7fQlmUf7FgohA6uPQFqB2tfhVSANSGw7M0YhZvWpGLJTCJABIjAQxAgJ/EQ1EknESACRGBNCJCTWJOKIjOJABEgAg9BgJzEQ1AnnUSACBCBNSFATmJNKorMJAJEgAg8BAFyEg9BnXQSASJABNaEADmJNakoMpMIEAEi8BAE7shJ1Mh8E/LGBjZEA8HMe5ivL2YTWRB53ku/Krr59XJ4ijqyoage0uZm6SnVIyVQpQhcE5oiQRQ3ICoupt9k+kitJrOIwNoTuPXDdJeWvCkRuSacv/+B80sTXX1CNH1kH7sY9Os1Ys9CKPuIRy8jFiUo6tUyRmdFWYOmSZCveO/0KC39PlICZQjL8FAaPfQiv3UUqBs87Nu3HykrMosIrJjAap1EnaJr2fjrr98hdDoQfvy4naOQFGi6MixqjYL3BrIKXdeXLr5odBEbS2ejDI+GQIXQ9VBYMTLfmDgG+dEYSIYQgSdNYKXhpqaIkWTf0dk9QhRYkwv6zhBWSPsOTF2FLIkQJQW67SOrJwprHroahiaqwBhvj1Lw89KGBCuayoQUrizCDKs2WZOH8CxjGOoQIasmvGgqhlb60CULYRbBM7WxLZrVRzoQMVJHv8sSKCMEmQavO+UglpVB6YkAEbg1gZU6CVHvI4rfI0t9WBKG4aJb23aDjA3KEjC8AElWII89yFkXdjddqFvWTahVhqwYiW6QxhnETRFZPJUnT5DVGkxjeLtaV6gUG70oQ1FkCMwagePMzrU0CTwngtKNUdYN6iKEWfdhuRHIT4x4L/9bZykKRYdS+HAMDYqiQNVt9JMpJ728WMpBBIjADQms1EkAIlTTgnpv8X8FThCiaxvQVAWq4aHnqqiyDM1dWlYAACAASURBVAu7EE2HLhdIs2G33aSIUwm2Z0LMEmTDye0yy1AoBoxhxIuHrCLfhaWrUBQNVr8LS8yR5rOz4ZoXwDMU8OKLsoGeZwJpghvOsd+wyp5Xsqos0VQRur0CRi9CmiYIHCC0TLi0GuF5NQYq7YMQWLGTeJAyzCiVZRlo6oUjCUCHqYvIkqw932QxUn7MsaDXCeK2N6+RJTkkw8Slc+OiBFlq0Mz4CAWaNhsoFyUJYlPzOVb63JJAXdU4bzR0owCOwZ20CsMN4ds1Ij/GdJDwliooGxEgAlcQWG8nUeeIujZMTYUiy+AOQvPSKybLReimjiZP27v7PE7QGBYM2YCp10haL8FHCIBhau2IgLOrUh+upUNVBjpk2ULwdZ6qCJmW28xD+fl9UYSgmdBn/K8ITVfRlPniEePPayUJRIAIDAmssZOoENoG3FSGy+cKqgpVVSHr6xCuqF4+L6GVfF4iQ5zUMGwDIiSYloYySZDnGbKKjzgGPX6TeTBMH7XpIykGOqoqhrN5hRI6tTICiiIDVXlhXqdph3HS2JGvTCEJIgJEYIbA+jqJJkOSNjC8Hix11Fk0KPOFsxGTQqs6dKVAGsZIKwOWMXAGsmlBKxJEUYJCM8Z3rmWaolRseK4OZTTXUhYoKM4xYXqHW7JhQStjRKMJo1ZXhTQtIGkaRgul79AEEk0EnjWB9XUSogJNBbIwQMrv8Mscie+gm1w3AaAN5iXCEIVuYegjAMWEpeUIwxyKboznI2RVhVgmCKMcZVWiSEN4jo9y5DCedfO5h8KrDnoOENh8RVOOosgRd210UxUeX3BwDyaQCiLwnAmsr5OABi/0YdYBLE2BotvwSxth5FyzumowL1F/r6FZJiahbrVd8vr9Oz+vjduEZPmIPBmpx+ckNJjdBEo/Qd+g7mkM6U43JJhBgtgGIkeHphnwUhndOMboAfw7VU/CicAzJ7DBbvGy6lW+j3iVsp55Xa518akdrHX1kfFrRGDZa22NRxJrVCtkKhEgAkRgTQmQk1jTiiOziQARIAL3QYCcxH1QJh1EgAgQgTUlQE5iTSuOzCYCRIAI3AcBchL3QZl0EAEiQATWlAA5iTWtODKbCBABInAfBMhJ3Adl0kEEiAARWFMCt34zHV9ru6rPKmWtyiaSc/8EqB3cP3PSSASuI3BrJ3GLZ/AW2rLsgx0LhdDBtSdA7WDtq5AKsCYElr0Zo3DTmlQsmUkEiAAReAgC5CQegjrpJAJEgAisCQFyEmtSUWQmESACROAhCJCTeAjqpJMIEAEisCYEyEmsSUWRmUSACBCBhyBATuIhqJNOIkAEiMCaECAnsSYVRWYSASJABB6CwIqdRIMi7sI2VMiSCFGU2jfGdeMS171U9NLCN2X7WlJTUyCJG9gQJciqDsuLUNxa6KXabnkiR1cVYQTXvF/7ltIp2xSBMoQpbUBykqmDtEkEiMBdEbj1w3QXDarbV3yaf/sD5+OT5/j62y/4658zVB9yhKY0PnOjjTqFZ1gIKhW210OkqxBRocwTJCUg0RtEb4Tx6SQqEbg9FFLn6RSJSkIEHjmBFY4kJOi2Ba2zhf3X7/Hp2ylOv7zHi21O4CsiP0a9FIwasWvjb7WBMMsQdh2Yhg7DsOB4ASLfnno/9VKCKfGaEigDF73aRXfZm401LS+ZTQQeA4EVOglA1PtIygJJ14ImS5AUC7a+OShnUy/nJMoQftxgvxfAVq5C1aBsQ1waFHkQ4lINB2E+FYsqfeiShTCL4JnaIBQmKdCsPtJqWnaFtO/A1IfhMkmBbvvIZrxbgzx0YahyG06TNQvduALmRzV1hsC1oKs8TCZCkjVY3QQz6qZV0/bVBMoATq+GF3hQbx+8vFoHnSUCROACgZU6CS5dmokBFcjzQQ8rqdpSd/51liKDDtuULxg9e0BEXVWQrC7CpECRR3AQw3V6yKcTNgk8J4LSjVHWDeoihFn3YbnRVMfdoCwBwwuQZAXy2IOcdWF303G3VMUOTDeB5IbIihyJb6HuuwgvTEdUKGoVrh8N0vU1FL4NN5rxONMW0valBAoETg+NF8DT5r3xpZnoBBEgAqsgwG7xAXCjXJ/f7LEOwCDsstefFme5TNbn1ztM2HzJThZnu/royUu2Jeyzt9+Gyb4cs11BYHtvRgcGx8/eH7JO5wX7cIW0T9yOndfsc5vmCzveFdjWiw/sbDrPp9dsB1z+l+mjc9vf2Js9gW0dfZw7TrucwGXtgJ/7fLzHNndfs1ETOnm5yTovrqo1YkoEiMBlBK661hblWflIYuS4qsSF5f2KH+hgr8/vAEdn7uFXViChQTMVcQIUaNrsqESUJIg8DDaTbtY+WZaBph6MJJocaS5Ct4zZ6JKmYxRVm809vSejFTVr1HQC2l5EoPDh9ht0wy7uswktMoWOEYHnSGCFq5sm+Oq0C8v+X/xxLmDnKEbsabOd6iTppVtt51yXKHl05spFUTWysAc/TJGV1dAxNKgvdCki5CvlAKhzRP0+wiRHUY0cQ41zedg91fwYlzMf8pAgzcluyhh+L0CcFW14ixe0qc8hOpcWmU5cIFDAd/tovASuOjo5dP5N0zru+ZoYpaJfIkAEVkNg5SOJJu/Dsv6K3350sHuUIPWNq/v4S8ohaQZUZIiTq2P4Rd+E0S2g9WLkZYWqqsBHMVfOdS/UWSG0DbipDDfKUHA5VYWsr0MYpefPfqBBfWHoMTdqqWO4hg0+OxKkxcCmqkRgjiWNJNLvVQSKGGH2Hb/9z7/hTxsb4P8Hf2PjT/iPv3/Hj1/+jD9tiLDjqwTQOSJABH6WwEqdRFMEsMz/wa8/BGwfBgi6KpphZ1uN7sxvarFmw9UbJD0PyaVLgipkaQ7R9NA1eIhp8KmLYmoy+oYKmwxJ2sDwerBUaTjyaVDmUzPSogZdbZCl2Xgiu5VeZsimbSxSpJUGp2dDk0f3ugWmRd3QquedTHEQZZ/w6dP09yPeHHTQ2T/Gx08Z+sbzRkSlJwJ3TWCF4aYCvuPhn9+5yef445f/xL/9MmW+sIvjIoN341t8BW4QIDFdWHoJx3Nh8aeu0aAqcxSiga6tQlFkNEmIIFNhKQ3KNESvn0NcdiwhKtBUwA8DpJoDVayQx330kmZqeasKxzPhuy5cNUDXVIAqQ9Dttyup9FFxZRUKQkR+AsPTIDUFkn4PfKUsfZYgIMpQ5+aReO6aO95Gha7RLMUSNCkpEbgVgRWOJHgYZvKs9a2smc+kOoizFL4lIQ882Oa/499NC24/Gj67IMLoh+hpBXqGCkU14EaAFwe4duXsvC5o8EIfZh20zkjRbfiljTDiDmOSWHZCJL6O0regqSoMJ0DjxPDNqUSKgyC0ISZ2+5yEZvWQGT6irr703MxEM20RASJABO6fwAZf8rSs2lW+j3iVspYtB6V/PASoHTyeuiBLnjaBZa+1FY4knjZYKh0RIAJE4DkSICfxHGudykwEiAARuCEBchI3BEXJiAARIALPkQA5iedY61RmIkAEiMANCZCTuCEoSkYEiAAReI4EyEk8x1qnMhMBIkAEbkiAnMQNQVEyIkAEiMBzJHDrJ675WttVfVYpa1U2kZz7J0Dt4P6Zk0YicB2BWzuJWzyDt9CWZR/sWCiEDq49AWoHa1+FVIA1IbDszRiFm9akYslMIkAEiMBDECAn8RDUSScRIAJEYE0IkJNYk4oiM4kAESACD0GAnMRDUCedRIAIEIE1IUBOYk0qiswkAkSACDwEAXISD0GddBIBIkAE1oQAOYk1qSgykwgQASLwEARW6iSaMkXgWdBVGZK4AZG/ftKw0Y/L2XdCX1PSJrIgjl98vwG+rnf2q6KbXyPkJqdLH7qooV/cJDGleRgCNfKoC1tXIYsiREmBbvWRTL16/GHsIq1E4HkQWOGb6Wokjob/+PvXBeS28OJDjtCULpxb+BBVXSIvqqFjqRF7FkLZR9wdvtNYlKCovNO4IG65A9xJqCGsPEdXXS4rpV4tgYXtgL/POraheRVMz4NtqJCbHGHXg187SLM+9J9tA6stBkkjAo+ewGXX2mWG3/qJ64sCJZh+gFfIobs2DF2BWEZwjP/EL1+/Ig4zNKZ5s3c8Swo0XRmqqFFw3yKr0HX9olo68qQJSFaI3BAhje8vVPTDCqnqI8r7oCbxpKufCvcICKw03ATJRD/swtIV8GtaVEyYqtAWU5TEmzmIJaCUvg5R62M+8pS6MkQrQj2UlTgy9H6BKu3D0mSIogovW6SoQd43ICk2oqlwRpX0YfMyiSIkRYcTZEPZJXxdhOKmF8JpeVeDqHYv2LZIKx27isC0gximk2TIaFA3V+Wjc0SACKyCwGqdxLRFTYUi7iHIzgFhF577sKOAMvFguSkUL0SShPCGkatpk8vQhuUDvTiEPRzINKkHwwpQWwHSPEfi6yi6JuyQexEFtmugjkOkMx1WjiguoDoOFqiZVknbtyDQ5ClyaDAoRHgLepSFCCxHYIXhpqHiNs7/F/x2Ptjf3H2BN74PV3vI4HGD71kNL88unXuoEhemV8KKU3hjWyuEPe4gIkRdsx0dQfURdlNofR+Z40O3HBiehzBpYFrDMuYR4lKDY1EvtlxzvEnqAkEvAuwIlnyT9JSGCBCBnyFwByMJCbKyha3NDnig6ftvEXq8Ey1mbrV/xuZb5RV0B87CPltEnfdh2wm0MIFvjIPfQJMhzQHdMgYOYqhZ1TRIZY68AiBZcEwgCeNxeCuLYpSaDXuhvluZT5laAjVS10avshH6Q6dNZIgAEbhTAqt3EoqDuChRVjXqbx9wtMMdxd/hOj4edKWpLM909BOqBUKPz2vUKMcrqoZn6xp1c45/OHweQ5x8rQjf0aBp/Z4I07UgpSFi7jSQIYpL6I6N0dT7RBdt3Z5AjaxvwooV+HGAaV9+e5mUkwgQgesIrN5JTGkUZRO2Megqz/Mc9zOY4J33MqMWEXo/Rx6aqHoOutlU3nayvYODIEdRFDPfL0UMZ+gFRMOBJWeIkgpNFiGpDDgUC5lqCT+72SD3LVi+hF4SXTIi/FkdlJ8IEIFFBFboJErEQYi0qMZhl6aIEYyeelIUKCuelhD5ush6om9QwAJ5/mNRWS85JkPXFShWgMCuETge0tGyKFGHqTco8goyt3/mOz0y0eE6CniYKYkSVK3TuEQdHV6SQIMisGD2gW4ST80XLSmGkhMBInArAiucuK6Q9v8Lf/tvbocAQQDOz4ez19jCYc9b+UofWTegVQH80IXuqBCbEqnvISgEvvBoyY8EMwjhaiYc10QWWZD56qWeC990YKEHz9Ygiw3qskBWKXDdyVyFajvtZHa3qGH2KV6+JPxLk/MVZ6aXQ+sFUOsMaTqVVFRaB7/ie48pBbRJBIgA2C0+wKJs39jJ8Qu2v7vNNjsCAwQmbG6x3f2X7M3Jt0u1LJY1nfyUvd0X2ObLk+mDw+0z9vndEdvf3mQdocM6Wzvs4NV7dvJ6l3UO3rHTYaoPLzpMOHzPzuYlfDlmu8IOe/15cuLs4yu2I2yyg3cTm7+dHLMXe9tsUxAYhA7b3N5jL958nJP3rbUTm4fs/QVFE/m0tZjA4nYwqHt+btFX2D1mXxaLo6NEgAhcQmDxtXZJYsbYCv8tx+087rKPiN9Oy33kqhFZCjwpQhne8Mny+zBrTXQ8nXawJsDJzGdLYNlrbYXhpmfLfFDwMkKQyrATY+VPlj9zslR8IkAEHpAAOYmfgt+grirUVYHA6yHXewjpP879FFHKTASIwOMisMLVTY+rYPdjTYHA0qAaDhLJQxy6y8+X34+hpIUIEAEicCsCNCdxK2yUadUElo2Trlo/ySMCz4XAstcajSSeS8ugchIBIkAEbkGAnMQtoFEWIkAEiMBzIUBO4rnUNJWTCBABInALArde3cTjWqv6rFLWqmwiOfdPgNrB/TMnjUTgOgK3dhKM8Ydgf/6z7CTKz2skCY+RALWDx1grZNNTJLDszRiFm55iK6AyEQEiQARWRICcxIpAkhgiQASIwFMkQE7iKdYqlYkIEAEisCIC5CRWBJLEEAEiQASeIgFyEk+xVqlMRIAIEIEVESAnsSKQJIYIEAEi8BQJkJN4irVKZSICRIAIrIjAHTqJBnlXg7ixgQ3RQtwsa3EKVxFhhtWyGRenLwMYooZuPjzN92Ud/dH+4lx09MEJ1MijLmxdhSyKECUFutXH6NXpD24eGUAEnjiBu3MSRQDX/x2jt1w/Oo6iAk3XoEiPzjIyaIpAHbuwuhkku48oy5EnfRi1D8vqIlv6xmNKMG0SASJwIwK3fuL6auklQq+H3x6thwAgm/Bj8+pi0NkHJyBZIXJDhDR25ir6YYVU9RHlfej6g5tIBhCBJ03gTkYSVdRF958/IGx2IKwMX4auqsCNM4SuAVUWIYoSFN1BkNWzWpoSsWdCa9PIUE0PUTl321n60EUN/WKUtUEZd2EbGpShbP4yoTCfyzdKTr/3RGDaQQxVSjJkNKipau6pDkjNcyaweidRJ+h2f8F3YQeeZ674fc9fETouEr2PtGzQ1DkCLYdne0jGHUaD1DNhR4AdZMiLFKEDBG4fV08/iO2rSCWrizApUOQRHMRwnd41+Z5z83mYsjd5ihwaDPVh9JNWIvCcCKw43NQg7Xn4+1cBO68CdFUf/oppimYPgaNjEH1QYPZc6KGPJAdMHnqoIvSjCmaQoWsNYxSKj6jOofz33IhjzjbNDRGMjyno9mwEZo68AjR5fII2HpRAgaDH7wAiWFQnD1oTpPx5EFjpSKLJfXjBHxB2XAQ9fcWjCF4hAlRdGzqIYQVJMiTUk9BDkSFvNJjGOIjdJpR1HeqysS9ZgYQGzXiU8jwaxeMtZY3UtdGrbIS+OdsOHq/RZBkRWGsCKxxJFAi8Hn7HNo78PnQRuIu+VRTFK4E3dY0aMuRZHwG0zuSqrDWysAc/TJGV1dAxNKihXZWJzt0bgRpZ34QVK/DTAHP3APdmBSkiAs+NwOpGEnmI4Ndz4PwP/O3//An8f5b/6c+/DJbAnv8Df/4Tf+bh6nDPKuCLkjQYWcyraniHf/mn6JswugW0Xoy8rFBVFarEhXJ5FjpzbwQa5L4Fy5fQSyI4NBdxb+RJERFY4UhCgry1NTt6aCp8/c7XwQrobMlTyxjvELyqQ0OMJKvhjOYkANRZhvJStRWyNIdoxugaE7dQFwVW9CjfpZrpxHUEGhSBBbMPdJMYnnb1SPI6aXSeCBCB5QiszkloXaRld0Z7E9uQ+GhCMBEWMaz7uL5lC57dg+U58MUeLFVCnUfo9hI0uOwWVIKiyGiSEEGmwlIalGmIXj+HSGOJmTq9750ytGF6ObReALXOkKZTFogKdF25g7mvKR20SQSeOYHVOYlHA1KCGSQIux56jo5uLULWLXTDELLdv8RKEUY/RK/y0DNUeKIE/oxEPw4QGZfluUQUHV4hgRpplODr+Tm+/s+f8c85ycLuMYrMIzc+x4V2icAqCWywW7ysepXvI16lrFWCIVn3S4Dawf3yJm3Pl8Cy19rqJq6fL3MqOREgAkTgyRIgJ/Fkq5YKRgSIABH4eQLkJH6eIUkgAkSACDxZAuQknmzVUsGIABEgAj9PgJzEzzMkCUSACBCBJ0uAnMSTrVoqGBEgAkTg5wmQk/h5hiSBCBABIvBkCdz6YTq+1nZVn1XKWpVNJOf+CVA7uH/mpJEIXEfg1k7iFs/gLbRl2Qc7Fgqhg2tPgNrB2lchFWBNCCx7M0bhpjWpWDKTCBABIvAQBMhJPAR10kkEiAARWBMC5CTWpKLITCJABIjAQxAgJ/EQ1EknESACRGBNCJCTWJOKIjOJABEgAg9BgJzEQ1AnnUSACBCBNSFATmJNKorMJAJEgAg8BIHVOokqgCFugK/DnfmKOvxiyeI1/HWnEuxkyXyU/IkRqJFHXdi6ClkUIUoKdKuP5PIXlj+x8lNxiMDDElitk6hr1OcPWyDS/rQI1LELq5tBsvuIshx50odR+7CsLrLmaZWVSkMEHiOBWz9xvbAwVYmanxAO8LYMYYmjVPwOcLRNv0Tg5gQkK0RuiJDG7UdFP6yQqj6ivA9dv7ksSkkEiMDyBFY6kmj4SILbIMtQZAmSNPqKGPuL5W0c52jyEJ5lQFMkiKIIWTXhRVNxh9KHLtkIsxCuMQxPyCoMN0Q+c9dZIe07MHkIQxqGMGwfWWv8QF0dWZAMH2nSh60rkHioQ9ZgejGmNI5to427IjDtIIY6JBkyGtQzdXpX+kkuEXjeBFbuJNrrtopgt05Chqrb6K8qgFxXqBQbvShDUWQIzBqB4yCY7rWbGJ4TQ+unKJsGVdqDmrkwnQjVuK4blCVgeAGSrEAee5CzLuxuiul+p8l6cPo1nDBHzWUlDhDZcPxphWOhtHFPBJo8RQ4NhnpPCkkNEXjOBNgtPgAW5vr2dp91AMbPz3632MsPpwvzXCaLnb1nB0KHHX5YmG1w8Ow9O+x02OH7s8H+l2O2Kwhs/+23mUxnJ0dsS9hlx19mDs/sfHq9w4Sd1+zz8OjpuwMmYIe9/jSTjJ283GLC/lu2uDSzaWnv5gQubQcXRHxmx3sdtvXiA9XBBTZ0gAhcT+Dm19pA1kpHErITI//8GV9Oz8DYKb6cvMbeJnfBXxH68dSd/IrcsihBlho007f/UKCq8owCUTegiznS2ZjTTBpZloGmnhlJoKNBm7tb5SE0rnAqMjUjh3bukkCN1LXRq2yEvonxNMVdqiTZROCZE1ipkwBEKKoKReIzEBIUo4uevdUiPi/yn47lV6kP19KhKjJ4py7LFoKv8zUoQp6fABElcJP4nEn7qXNEXRumpkJp5cjQvBQXFmbx+Yp5Wa2AGa80bwDt3wmBGlnfhBUr8OMABnmIO6FMQonAPIEVO4l58cD41px3uAtO3/RQk3kwTB+16SMpKlQV/8Zw2pHKtJQa1fxtflO1x9pRACqEtgE3leHyuY1WToWsr0OYFkPbj4hAg9y3YPkSekkEZ25094gMJVOIwJMjsEIn0SD1uwiTHFV7o80njfvox4Nb/U3NwM9c22WaolRseK4OZeRtygLFvENAhSybfXKvTmJk0KBrfDiRIUkbGF4PlioNHVeDMqfJ6MfZuhsUgQWzD3STGB6vQ/oQASJwbwRW+JxEgzLx8V9/+etF4zf30e+ZPzWSkFUVYpkgjGzIhoSmSBH0fJQioM1oFFEEDjzFh6vLaIoYPS8GrAi2whMq7TyDHwZINQeqWCGP++glDY+W0eeREShDG6aXQ+sFUOsMaTploKhA1xWqtikktEkEVk1ghU5ChG472K9T5HmJ7+dAZ0uFZtjo9jyYbQd9e/Mly0fkOfA8HWEtQtZMeH6Cfl9DNCNWRdf3UAUODKdE3f4bhwCJb2Ewna3BC30Ubh+W1kMjKTDsPsJIge3OCKKdBydQI40SfD0/x9f/+TP+OWePsHuMIvPwk01rTirtEgEiME1ggy9ymj5wk+1Vvo/4Ull1CFPuQkkqBMZNrALAH6ZTQ1h5ju7PxLZuqI6SrY7Ape1gdSpIEhEgAkD7f/WW6fZXOCexGv58BVLTVMiCEJmow5iNJa1GCUkhAkSACBCBGxFYYbjpRvquSVQhshT816/ngLCNwzCETUsdr2FGp4kAESACd0fgkTkJGU5cQK8aSAr/30t3V3CSTASIABEgAtcTeLxzEtfbTimeEAGak3hClUlFedQElr3WHt2cxKOmS8YRASJABJ4ZAXISz6zCqbhEgAgQgWUIkJNYhhalJQJEgAg8MwK3nrjmca1VfVYpa1U2kZz7J0Dt4P6Zk0YicB2BWzuJZR7GuMqIZSdRrpJF59aXALWD9a07sny9CCx7M0bhpvWqX7KWCBABInCvBMhJ3CtuUkYEiAARWC8C5CTWq77IWiJABIjAvRIgJ3GvuEkZESACRGC9CJCTWK/6ImuJABEgAvdKgJzEveImZUSACBCB9SJATmK96ousJQJEgAjcK4E7cRL8laF9x4SmSBA3NrAhynCSZcuVwlVEmGG1bMbF6csAhqihmy8+/eBHuX2yjv5jte/hASF2NUiigWBFTeLBi0QGEIE1IHDrh+kuK1uVuDCs/8Uf5zyFAKGziU7ToGkuy0HHWwKiAk3XoND7My42iCpF37bhVxK9z/oiHTpCBO6UwGpHElUE1+EOooPdo3f49K1GU1eomxqRdaflWH/hsgk/DmDTC5vn6rKAb1kI5T7SyKH3Wc/RoV0icNcEVuokyshH8h3o7PuIfRvaSt8alKGrKnDjDKFrQJVFiKIERXcQZPUsp6ZE7JmtflGUoZoeonLBUKbJEbbppFaWrJnwogLTKevIgmT4SJM+bF2BJIoQZQ2mF6Oc1YpqKo2k6HCCDNOW1ZkPx+AvUxIhSjJU3YIXDaXw93OLGvrFSGiDMu7CNjQow7KqhoMwn7ZulPYp/6pwoxxZ5EAVMVM3T7nUVDYi8FgIrNBJ1EiTHOcQoJkK0q4FQ1Oh6iZcP8VqwshfETouEr2PtGzQ1DkCLYdne0jGfWeD1DNhR4AdZMiLFKEDBG4fs+H+EoFlwEsVeFGKPE8RujJS14AVznb/TdaD06/hhDnqpkGVOEBkw/En6ZrUg2EFqK0AaZ4j8XUUXRP2SFYdw7X6KPU+krxAnsbouzrUS+NLIuqqgmR1ESYFijyCgxiu05srx2NpSndnh6gooCjc3fElyUTgSgLsFh8AC3J9Yq+2wQCBbW1tMZ5m8hXY7utPC/KwNs3CE+yEvdwS2P7bb8PTH1v5ncP37HQ6w7c3bE/YZkcfhwe/vWX7nQ47eDeTin17s8cE7LBXQzPOTl6yLWGXHX+ZFsbY5+NdJmy9ZCdng+On7w7afPPmn7zcYsL+26Et39ibPYFtztn2+fUOE7aPWGval2O2K+yy159n9Y332vM7l5/nCVub99kYyTjz+m8sblNz5fr8mu0ISnKVQgAAHAlJREFUe+zNqEnMnaZdIkAEridwo2ttSsxKRxJ1G1s5x1doePPpFGdnX/DucAvAOX7zA6RXuqubnBSg6trsXaUkQ0KNejSSKDLkjQbTmL33lHUdqjDRUWQZKtWCOTcHoJoW1CpDNg77AOho0NRJXr4lSRL4bHxb5CZDmgO6ZczYpmoapDJHzodRigXXKNEzTXhhikXRr1kNC/ZkfkdNiwAWkKFDRIAI3BGBFToJPkcwsHLH7cHVeJxfge2a4G4CdYFiBTEncaTkEiBNXaOGDHnWRwCtM5lkqsua9/QznXp7tj1Wg58ef6RJ2cbH2o2hZ+I6m3P8w5HB7Rt/rQjfx526AifJkXRVFH0LqqzC7MYoRs5tVjAHhiz0BnMSigxZliEbfUz7rgtZ6AARIAJEYMUEVugkZKjK4Fa97YAvGCrey/JFcdjJD0Y1U0aM7vqHhyQ+F9A6lKk0fLM9Ji23FJU7EXRwEOQoimLm+6WI4YxHKzIM10dSVCgiF2Jsw3DimcntkTVF34TRLaD1YuRlhaqqwJcXj0WNEtIvESACROAOCazQSSgwLA3cTXyNevD5iqOmRBQk+MoLoGjQ5DssyUi0qkNDjmRuxVOdZTOrkVRdh1zESCZzz62EMklQyDr0ufDSSPzCX1GHqTco8gqyokCZ+fJw2PxHhGJ6CLsG6jxdMDqokKU5RNND15hM2tZFsaIFAPP20D4RIAJEYDGBFToJQHX6cHcE4Mev+Mu//ws2/vT/4D9/4S5iEwc9D9piG1Z7VLbg2SJiz4Gf5CjLEnnch91LZpZPikYXPT5HYLsI0wJlWSANXdi9Aka3C2MYOruZcQrsngsEDiwvRJLlyPMMaRyiH6SDkUKVwO/zcwXKqkKZx+iHOSTNwEV/JEFRZDRpiCArUVUFsqgLu5/fy2jsZmWmVESACDwHAit1EpAM+EmCNy/3sL3ZgSB0sLVzgKN3KSL7PoYRvMokmEGC0GoQODpUVYPlF7DCEPbMLb0CJ04RGBX8Np0O2y+h+wlid/mgzuBZCg9y3odj6Pg33YTdDVFgGGYTRTSZD9fU8P/8qwLV7CJTeogDa+FIw+iH6GkFeoYKRTXgRoAXBzDvC+NzaP1URiJABK4lsMFXOl2bai7BKt9HvEpZc2bS7hoRoHawRpVFpq41gWWvtdWOJNYaHRlPBIgAESAC8wTIScwToX0iQASIABEYEyAnMUZBG0SACBABIjBPgJzEPBHaJwJEgAgQgTEBchJjFLRBBIgAESAC8wTIScwToX0iQASIABEYEyAnMUZBG0SACBABIjBP4NavL+VrbVf1WaWsVdlEcu6fALWD+2dOGonAdQRu7SRu8QzeQluWfbBjoRA6uPYEqB2sfRVSAdaEwLI3YxRuWpOKJTOJABEgAg9BgJzEQ1AnnUSACBCBNSFATmJNKorMJAJEgAg8BAFyEg9BnXQSASJABNaEADmJNakoMpMIEAEi8BAEyEk8BHXSSQSIABFYEwLkJNakoshMIkAEiMBDEFidk6hDmOIG+BrchV9Rhz/3PukrC1xHMEUZTro4VeJIEK1o8GrQxUkWHM3R1WSY4TKGLBBzxaEmsiDKLi4xG0AKVxFhhtWslCZDV5egWGH7Lu46sqGoHtJmNtnd7eXoqiKM4O7Y/JztJWJXgyQaCObQ/Zxcyk0EiMBVBFbnJK7S0p6TIC313uhrBd4igQRN06HJU+8xLX0YZoCH7XdKhLaFAF1EkQP+8lRR1qBpKuQHZ3YLzKvOUqXoGzrctKF3fK+aLckjAtcQWJ2TkBzE9SlOT6e/3/DucLM1oWPYj+D9zArsMEbfnDiJMo6R39vd+qLaqJG4JrzCRBR3oQ+dgmh0EUcu1EVZntWxAr5lIZT7SIcO9FkVnwpLBB6YwOqcBL/7FSVI0tS3SRAm3wFswnQtyHdY2MSRoXUTpL4DQ5UgiiJk1YAbFpj4gGwYUuHjBt45q9D+8it+/Prf+Nc2TKbAHcWJmhyha0CVRYiiDM3sIp6PxPA7XFuDIokQJRWGEyBrlrn1b5D7FpxYgR+HM0605mErZRK24vuS4SNN+rB1BZIotqMN04vb8NQEbY3Ut6ErnMFs6E9ykmGyBnnowlDlts5kzUI3rnDxNr1GFnCePJ0ISdFhdZNZfaUPXbIQZiFcg498uF0qWrvqApFntiM33jZUw0VUTGpjYvNVWyrcKEcWOVBFTNXlVXnoHBEgAqsisFInMW9UEQZIfwDYtuFN3b3Pp1vNfoPffQfdwoSfVWiaCmlPRuJa6OWLNEgw/QzJ0TaEvWN8PjvD2VmBwOBpS4SWCS9T0I1yFHkEV4phm1NzBE2OvmmiXxroJzmKLISnxnC7o454kc7ZY2XswOo1cOIYzg2GDE3Wg9Ov4YQ56qZBlThAZMOZmuypQhtWn8ss0TRn+HZyhN3OFl68+4IyNFsDqtiB6SaQ3BBZkSPxLdR9F7NTNQ3yvgmzV0LrRchyns4GYguGE8+G55oEnpNA9zOUTY0yslAHNgyNjwC4c63RVBk8KYbjBrNOZhbJwj1RUTAZ+y1MQgeJABG4KwLsFh8A1+c6O2Evt8AAge28/nxp+ktlnb5j+8Ime3GyOOuHFx0mHLxjp8PTfB9bL9nJ2XT6z+z1jsB2j78MD35kr7YFtvfm2zjRp1fbTNh7wyZHGDs7ecm2hB02Y/bpe3bY6bCDtwONZx9esE1hj41FtxJP2fvDDsPmS3aJ2YwxzkVgu4cv2I4AJuwes0V0Tt8dMIGXZ2hpu48d9vrT2PR24+TlFhP23w45nLJ3BwLbOhrl4klO2dt9gW0ffRxm/MKOdwW29eIDm0H16TXbAWczZHX6jh3w8r6bJsPY2ccjts3ZjOz4csx2BYHtv51ON9CJndezZTt5yTaFA/bu/2/v7KHcNq4F/KkiUi1SCamEVEIqQZXgapHKeJWRynhV8CojlZgqTLedkMpIZXZGKuNVhqvgVYaqwJWgynAVqApcGaqErfgOuMsVSe0fKUhL7l6cw0P8zNy58w04d+beAbFotKWqXHgfLKWZ/fhs9mh0OFtqvuWrsi8EhMA1CFzrt7Yk54PNJNp0SvIKGNmMrzNMHsAKjgwLc8Xb07u+oG3ajaTXRUGjOzjLo3vVxDI6yuJkWlLlJa3h4PRR5rNNxbJNRmfHF+0c80NWYh19gVEeEUTVRQlXzx+YmMs6wdy9R9edrfLq5t6cFQhzGWdOnq4kLxUs1171LpkW1kn46KTMMqfoTBx71UmoWC62VpEVy6F+HcNYTqfMuR8YxjwIf1aJ3hVJS3umzNkV2RECQmBHCXwgI1ETT1N6T9N9N8Bd7j82ADHv6q7oUFa6Q1Vd7fg2KGs5adO0HP8UYfX+9bOPweSH47mbp0/btm3fQ7/jBuljMldvIw6PUqaTKUloUk58wutEz/vYx0qFFyUtIKnYrkWbhsTViWFs8pBpoeO65knitqVfI6S+s9TsxKCeSWxbWlSWF4KdXFPRe8Pb1/9sU85JNw9SDdIeZ8XIjhAQAh+dwNbvk7hU02LK9Pkx8AA3cN7pSC/Nu7jYd8BKSzsfdq73jCfnlYGMwqLIxbeqqIweeWRpsDoS7hOoJxZv3snOO1JWAvJ9rOA6m3LaSRvjmDAzGftH2EV4trrpOjLOS6MHCXFu4Zk640WwOc4I7VOGvaGhO4dr109IzraerUrFfBK2YuRb6rl9vI4xPBMnO0JACOwpgQ8wk2jJpjE/9UAeBQSLzmljQCa2pZAnyWqQtJfTpMS5gu1YG0t9N0O/ZKZbWTVjOBZaXVIrOrq+9ll07paJUuXky14XOsq8pDeP1990gniK00T4k3xFj+vLWEpZZ0wLg2nVG9KGukyJXP3tiF45cZsVebFaVl2w4kEyHWylJMtWKghlRt4YWNaK5VhSQHaFgBC4TQSGNxJNSpT2y15HHAYep06OLZhpeOEEIx9juyFxVlAUBVkS4toBhXlE6L7/aFa3DJQyJsoq6qaej5z7ZxQmVsnY8YjSnLIsKfKMJApJTsMHijMmMHKOvAlpWVPX/eofn3HaXiMmsYZD84inHt00YJwtu3HW0l3nsC7oV5k2VTHXuywrqmZpioCBP3bmZQXTnKquqYqEsR+ysghMdZkcGeQTj0lanKTLp3heROceMd6+Ya9TC0kjBITAjhAY3EhUcXSy7PXAIfBWorobV1kxJ2R5hEPKkWdj2zb+UTr/O44iG8/XzW8sdC2D6oZMfYXUNTEMh3DeU+oEac7U7ojHLtbjx9huQJQ3b2MCikXYL11VMwLLwDBdjgqTKA7Q171ja2Wed6i6EbEPcTAmfQ870ek2lpLz1//6hMePH/P48e/43W9UNDukOJWr+TFZZFFHLqZx8nxH56dEzqri5jgjDw3KIxfLMLD8mM5NyOMP+8zLeXzknBAQAjdD4F6/0mnTood8H/GQsjatx61LX8c4VoQ+TQhd4zQW1NFWKYHj00wq8uD9DPeHYib3wYciK3KFwCqBTX9rg88kVtWRo49JoMkTcs0jODMQfekKqmFh6X3oZdnt9DE1k7KEgBDYVwJiJPa15c7RW+ufS6gSpklJ0/arldp5bCIZ90tsLfyVBz/OESCnhIAQEAJrBMTdtAZkvw87qmTCJErJy1e8ZsSBZmBaDsHREV7/50c7um06Bd7RaohaQmDnCWz6WxMjsfNNejcU3PTGvRtUpJZCYHgCm/7WxN00fBuIRCEgBITArSEgRuLWNKVURAgIASEwPAExEsMzFYlCQAgIgVtDYOv/bur9WkNtQ8oaSieR8/EJyH3w8ZlLiULgKgJbG4ktnsE7V5dNgyjnCpGTe09A7oO9b0KpwJ4Q2HQwJu6mPWlYUVMICAEhcBMExEjcBHUpUwgIASGwJwTESOxJQ4maQkAICIGbICBG4iaoS5lCQAgIgT0hIEZiTxpK1BQCQkAI3AQBMRI3QV3KFAJCQAjsCQExEnvSUKKmEBACQuAmCAxuJJpiim8baKqCoqjolsskqVbfp7xRTVvKeIJnm+hzmQqabmA5PmH6PnI3UkIS3ziBmjQwURWb6dprt29cNVFACNxiAls/THcek66c4Nh/4+UxjB48xKDh5Q/f8bf/LqgoST3tvGwXn+tKItdhUqg4/phwYsxfDdo0FUWaUDb9K3Vku/UEmpzQ84gaVdr71je2VHDnCPSvL910A87N8uIvD/tXoc5GT57NXrzpk/xn9s1nByfnPvtmNj+1lvMiWbPZL7N/fvFgNrr/6eyrH8/LuSZIDveawMX3wY+zL58czB5+/vXsxxfPZk9Gh7Ov/rPXVRXlhcCNErj4t3a+WoO6mxRVZdSbwf4tmfMh/ttxvqqqmxnIJiGMW+wwJrjyZTktsaOgBflaGSWhqWBFNbQJrqripe1ampqpraD52YlLrC2YBi6WoaMqCqpm4k4y3no4CiaGTpAWxIGNoS3caj7TYlV2V8aMXRtTV1EUBc1wGCf1WvlyeDkBgyApKRKf/jaQF7BeTkuuCoGhCQxqJAw/wLkPxy+PcJ0xE98h+O41HDxhPLY3chW0eUaBheds6KK6iJDq4DsKWZyx0pXXGUmh4foL/Rqq1iCIEoqqJAtNqsgjSJZzvSL2AzIrJK87urZkapaMvTHZci/WNjS6x1FSUFUFU6dl6vtMxU5c1Ernnld0nQ2HGOfKkZNCQAhsQeD8CcblZy+brrx58Wx2eMDcxdSn4+Bw9uzE93Su0Itk/fjs0Wz04IvZ9+fmWj/5y+zrT0ez+1+sp34xe/ZoNHvy5b/nGd58/8XswcGns6+X3BX//vJwNnr4dPavdZFnx/+ZfXU4mj14ukjxr9lfHjI7+Pzb2S9naXrP2lezw9HD2Vmy5WuL/Tffzj4/OJh9/q24zxZIFt8X3QeL6/PvH5/NHom7aQWJHAiBTQlc67e2JHTQmQRtztE44vlr4OAB9w+A188JgwnZW3/NFqZskaVgrN+j/xfD+Uf1SBeXrvGt2D6ulhOni6F8TZoU6K6PdWF+DU2DrlueIowwLHN1dKtqqLS0y8nWZSoqmtqxImo9jRwLASEgBHaIwIBGoiMb+/zt+c+Mnjzl+6qmKf/J0ycHvP7h73h+vOTXv5qA1vfMTUOz7OXBZJK94MWLF/zry8OT+MfVopZSWPi+QRGnzM1EnZKUBr5nnqXp6pTQd+YxiV6H/uOnx2fXFzt9jOGqrckjAtfC0E/kaJrL9NVVueS6EBACQmB3CAxoJEqyvO8BR7iTELsPJegOUeTzsJ9Q5Cn5Sod/OQTVsjHJSbLlTH3w18Q0TUz9OrGKbs3IgOn5mGVMUkHVL6M1PdyFjWhTAtsjwWeaVzS9kWpqps48HH+5wmtXu2KM7US0TkRW9XL6T4p/fy2hHAoBISAEdpjAgEaiX+XT1/SYKi/PVqHUVXUyg1BU1KsH329RGT6BDdkkIL3SVaWgqgpd256VOxfUlPNnKd4K7Q2Xh2/VpGlKlpSYnoexSFDl5I2Jf+RhagtlK8qFd2qR7hrfdZ5T6x7jwJo/2zHPUldUyzbvGnIkiRAQAkLgJgkMaCRM/OAJfRji5d9tNN3ENDSM//k/XjPiURBgL/rda9VYw49jPCXFMy38MCbNC4qyoMhTkqxakqJgORZkEdFiGWrTL2WNKJZSnexqeIFNFU+YVha+q79NoRnoVCRRRlk31FXO1B9fw0i9FbHY0wwDpc6Ik5K6qanymLEfUW/EYCFNvoWAEBACN0NgQCMBxjgj//opnz3p4wkVL+sO7dGnfPF1Th5aGy2BnePQXOKiJBkb1MkRvvMJnzy2cbwxUWXgT3wWniLNj0kClcTV6Z/X0OwjSndK5CjvlKu6Pk77E7Xls2wj0H2msYeSefOYhOkeUdgRyWRz3VU3Ihlr5OM+JmHiTDL0MCPczFLezF0hpQoBISAETgnc61c6bUpjyPcRDynr2vXoMnzdo41qUk9W4F+b2wdMeCP3wQesj4gWArtKYNPf2qAziV2Fsq5Xm8Zk9A/XiYFYZyPHQkAICIFlAoP+wd+y4N3bb2nqlrZOmfSun3GOKzZi95pJNBICQmCnCNwdI1Gn+FZAjo7txSSTRTRjp9pDlBECQkAI7BSBuxmT2KkmEGV6Apv6SYWaEBAC2xHY9Ld2J2MS26GVXEJACAiBu0dAjMTda3OpsRAQAkLg2gTESFwblSQUAkJACNw9AlsHrnu/1lDbkLKG0knkfHwCch98fOZSohC4isDWRmKLZ/DO1WXTIMq5QuTk3hOQ+2Dvm1AqsCcENh2MibtpTxpW1BQCQkAI3AQBMRI3QV3KFAJCQAjsCQExEnvSUKKmEBACQuAmCIiRuAnqUqYQEAJCYE8IiJHYk4YSNYWAEBACN0FAjMRNUJcyhYAQEAJ7QkCMxJ40lKgpBISAELgJAoMbiSaP8G0DTVFQNAPLC0nr7v3qVoWYioaX7tcLojNfRfHS0/dud+SBju6l7Fct3q/phstdkwYmqmIzvfKd58OVKpKEwF0nMKiR6IoxjvNn/vH8J34+Pub455/44X//yh8sj6TeHnUxjamVjizOPlwHW0fYzpQP1/8oqKaFZWnvvE51ezJ3JGeTE9oWQd4JuzvS5FLN3SEwoJFoSI6mvDyG0ZO/8P0vM978+xv++BD4+TsmYX46ot6w8l1OnLY4kwA9j0k/UC9epynle054rqqZGSQk483fl32V3Nt9vSJyXWItJE989NtdWamdENg5AgMaiYqiPAZGWP4YWwVF9wjHh4yAV1lKuUX1u94wdA5+4OMZOfH6lKQYY5zjguhSD0XzyRZlNhmhZ6GrCoqiohkW3iSjoSULDMw/P+f18z/xm3v3uHdPJ8iBOsJSPdK2IgnseV7ViU9nGw156ONYBlovU9WxvIjiEl/SqvupV2xzGYvq3J1vgyApKRIfQ2G7gcbdgSU1FQKDExjQSHR0pyNxRVHOFFXV03eENjX1JR3oWYaVnZYsTlEcD1s18DyTIk6oVtJc56Ah9j2mncc0r6jKnCT0MQ0NFRUnKsiePmR0+CU/vnnDmzcVU/tUblcx9VzC1iVKM9LIQZtf6qhrsMdTsqKiTMdoxQRvssmMaQgZ16n/fqdRdB150+x+t6Fov78Etv6Dv3erbGAaI/7xwzFFPKVwxxhNxiTM6OcX/RhwY29OkzLNVJzUnvuiddfHmkTE5YRwo7eP1pR1hzHxcMyTLl43TBZ2AEXlxK4pqH3AfaVyL6nUbykTd62j0vGn8duUxpijIMZKCmpsjLdXLtkbQsYl4uWSEBACQuA9CQw4k9Dxxg73gdfP/8onv/4Vv/7dH0habX6Ofsy+2vteqXqdxuSqi2edZtQdPKsmiYsr864mMPF9k2Js404SimYTc3UfJ1g3EKvSF0eapkHXbm4MFwKAIWQsiZNdISAEhMB7ERjQSIDmJeTfPOWzw0c8fPSET//4JWnonIzMdR19IyNRkcYFx6/+zu9/1ccJ+s9v+dPzY171xuPKfn45gYI5ySmTYO4ScnQN0w3JrrXiSkM/mXysgm5LkvnMxEDXtHnnbo7z01nTatILj4aQcaFwuSAEhIAQeH8CgxoJUDC8iDQvqcqCLA6gyHkFPLCda7pgTitVxsSlwdN/vuDFi6XP9884bHs31LIReBdE165fV9CdMdO8pi5jnC7CdcYU68neFXXOmYbYswlyjSApqJqGpmkoQmsepD8nwzmnhpBxjlg5JQSEgBAYkMCAMYk1rbqafDrGn/4Eo0cEwUlcYS3VhYdFnFJZY1LHXFv2qBPYIUGc0roeqto/d9DS9kHxsxF/R1lUHL89sVKOariE05rc6F1PYM3XVfZLZ64ZN+kKsrzDjo9wjUVItaMu+6mJtVLWhQdDyLhQuFwQAkJACAxDYNiZRDnB7JeXairKr37L7//8Ha+O7/NpGDPeJNA8fzaiwfbdNQPRV1rFDVyUxTMTho2tV8RhysmD3R1VOmGy8kBFRRJGJP0Mp25oqoIkjKk0k9M4NrploJQxUVZRNzXNZSuxFB3TYB6gz6uGpi7JIp/JFbOblSYbQsaKQDkQAkJACAxPYFgj0a8S4jU//9zB/Yc8+ewpX31fko3NtRVDl1dk/mxEa+O7Z1ODlQyK7eOq/UN2JyP3MJli1RNMVUHVDPxE42ga0D/Hd7KpKP1zEr6N+dvfoFsuYW0TpRH2aZxEdUOmvkLqmhiGQ3jpQx0m4zjCaae4po5ueUS1R3y6ln9R6uXfQ8i4vAS5KgSEgBB4XwL3Zlu8rHrI9xEPKet9YUj+myMg98HNsZeS7xaBTX9rw84k7hZrqa0QEAJC4NYTECNx65tYKigEhIAQ2J6AGInt2UlOISAEhMCtJyBG4tY3sVRQCAgBIbA9ATES27OTnEJACAiBW09AjMStb2KpoBAQAkJgewJiJLZnJzmFgBAQAreewNZ/y9GvtR1qG1LWUDqJnI9PQO6Dj89cShQCVxHYykhs8fzdVXrIdSEgBISAENhBAuJu2sFGEZWEgBAQArtCQIzErrSE6CEEhIAQ2EECYiR2sFFEJSEgBITArhAQI7ErLSF6CAEhIAR2kIAYiR1sFFFJCAgBIbArBP4fQt5OYCI39j0AAAAASUVORK5CYII=" - } - }, + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -299,7 +289,7 @@ "results should look like the following. Because model training is not\n", "deterministic, your results may differ.\n", "\n", - "![image.png](attachment:image.png)" + "![Model predictions table](./resources/transaction-predictions.png)" ] }, { @@ -341,17 +331,14 @@ ] }, { - "attachments": { - "image.png": { - "image/png": "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" - } - }, + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "When the query is complete, the results appear below the query. The\n", "results should look like the following:\n", - "![image.png](attachment:image.png)" + "\n", + "![Purchase predictions table](./resources/purchase-predictions.png)" ] }, { diff --git a/notebooks/tutorials/bigquery/resources/model-evaluation.png b/notebooks/tutorials/bigquery/resources/model-evaluation.png new file mode 100644 index 0000000000000000000000000000000000000000..814e8175f3de4d301df8bd2fc25f69eb63398fb9 GIT binary patch literal 11193 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 literal 0 HcmV?d00001 diff --git a/notebooks/tutorials/bigquery/resources/purchase-predictions.png b/notebooks/tutorials/bigquery/resources/purchase-predictions.png new file mode 100644 index 0000000000000000000000000000000000000000..b48aae714c8e51e9eda87deaa7f9532adc5883c1 GIT binary patch literal 41932 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 z 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�z}eg>I#_S?6ayPmmq23p(dBY)I568}jXrAD$Ll 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 Z@@`tA+&GXg{0r!xytIl`g@j4a{{YsY?9KoH literal 0 HcmV?d00001 diff --git a/notebooks/tutorials/bigquery/resources/transaction-predictions.png b/notebooks/tutorials/bigquery/resources/transaction-predictions.png new file mode 100644 index 0000000000000000000000000000000000000000..877500ed83075d13b2dd40a10b379e216fc7ff9e GIT binary patch literal 23642 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 literal 0 HcmV?d00001 From 89274a411401f36b6cf0af939ad516566e30d4be Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Fri, 8 Feb 2019 18:24:45 -0800 Subject: [PATCH 22/24] fixes broken image link --- notebooks/rendered/getting-started-with-bigquery-ml.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/rendered/getting-started-with-bigquery-ml.md b/notebooks/rendered/getting-started-with-bigquery-ml.md index b59f5f9b0b5..be92acf0b8a 100644 --- a/notebooks/rendered/getting-started-with-bigquery-ml.md +++ b/notebooks/rendered/getting-started-with-bigquery-ml.md @@ -193,7 +193,7 @@ When the query is complete, the results appear below the query. The results should look like the following. Because model training is not deterministic, your results may differ. -![Model predictions table](../tutorials/bigquery/resources/model-predictions.png) +![Model predictions table](../tutorials/bigquery/resources/transaction-predictions.png) In the next example, you try to predict the number of transactions each website visitor will make. This query is identical to the previous query except for the From b3b35ffef060a8e3ebd7f3a8ac3512fd0cce030e Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Sun, 10 Feb 2019 13:36:07 -0800 Subject: [PATCH 23/24] add readme with set up steps --- notebooks/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 notebooks/README.md diff --git a/notebooks/README.md b/notebooks/README.md new file mode 100644 index 00000000000..5979c8bfc4b --- /dev/null +++ b/notebooks/README.md @@ -0,0 +1,31 @@ +# Notebook Tutorials + +This directory contains Jupyter notebook tutorials for Google Cloud Platform. +The tutorials assume you have registered the `google-cloud-bigquery` magic +commands and set `matplotlib` to render inline. You can either perform these +set up steps in a single notebook, or add the steps to your IPython +configuration file to apply to all notebooks. + +Run the following commands in a notebook to register the BigQuery magic +commands and set `matplotlib` to render inline: +```python +%load_ext google.cloud.bigquery +%matplotlib inline +``` + +Alternatively, add the following code to your `ipython_config.py` file to +perform the set up steps for all notebooks: +```python +c = get_config() + +# Register magic commands +c.InteractiveShellApp.extensions = [ + 'google.cloud.bigquery', +] + +# Enable matplotlib renderings to render inline in the notebook. +c.InteractiveShellApp.matplotlib = 'inline' +``` +See +[IPython documentation](https://ipython.readthedocs.io/en/stable/config/intro.html) +for more information about configuration. From f99437622593b08157e25f1b4f1050b4c4195dc3 Mon Sep 17 00:00:00 2001 From: Alix Hamilton Date: Sun, 10 Feb 2019 13:50:58 -0800 Subject: [PATCH 24/24] add installation instructions to readme --- notebooks/README.md | 37 ++++++++++++++++++++++++++++--------- notebooks/requirements.txt | 3 +++ 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 notebooks/requirements.txt diff --git a/notebooks/README.md b/notebooks/README.md index 5979c8bfc4b..4ae67189085 100644 --- a/notebooks/README.md +++ b/notebooks/README.md @@ -1,20 +1,39 @@ # Notebook Tutorials This directory contains Jupyter notebook tutorials for Google Cloud Platform. -The tutorials assume you have registered the `google-cloud-bigquery` magic -commands and set `matplotlib` to render inline. You can either perform these -set up steps in a single notebook, or add the steps to your IPython -configuration file to apply to all notebooks. +The tutorials assume you have performed the following steps: -Run the following commands in a notebook to register the BigQuery magic -commands and set `matplotlib` to render inline: +1. Install Jupyter notebooks ([instructions](https://jupyter.org/install)) +1. Install the dependencies in the [requirements.txt](./requirements.txt) file ([instructions below](#install-the-dependencies)) +1. Registered the `google-cloud-bigquery` magic commands ([instructions below](#register-magics-and-configure-matplotlib)) +1. Set `matplotlib` to render inline ([instructions below](#register-magics-and-configure-matplotlib)) + +## Install the dependencies + +Install the dependencies with the following command: + + pip install --upgrade -r requirements.txt + +## Register magics and configure matplotlib + +You can either perform these set up steps in a single notebook, or add the +steps to your IPython configuration file to apply to all notebooks. + +### Perform set up steps within a notebook + +To perform the set up steps for a single notebook, run the following commands +in your notebook to register the BigQuery magic commands and set `matplotlib` +to render inline: ```python %load_ext google.cloud.bigquery %matplotlib inline ``` -Alternatively, add the following code to your `ipython_config.py` file to -perform the set up steps for all notebooks: +### Perform set up steps in your IPython configuration file + +To perform the set up steps implicitly for all of your notebooks, add the +following code to your `ipython_config.py` file to register the BigQuery magic +commands and set `matplotlib` to render inline: ```python c = get_config() @@ -28,4 +47,4 @@ c.InteractiveShellApp.matplotlib = 'inline' ``` See [IPython documentation](https://ipython.readthedocs.io/en/stable/config/intro.html) -for more information about configuration. +for more information about IPython configuration. diff --git a/notebooks/requirements.txt b/notebooks/requirements.txt new file mode 100644 index 00000000000..d13f3e9f733 --- /dev/null +++ b/notebooks/requirements.txt @@ -0,0 +1,3 @@ +google-cloud-storage==1.14.0 +google-cloud-bigquery[pandas,pyarrow]==1.9.0 +matplotlib