From 456fb32b1799aef467506487c5c4808a8a9d7db2 Mon Sep 17 00:00:00 2001 From: Garrett Wu <6505921+GarrettWu@users.noreply.github.com> Date: Thu, 14 Mar 2024 13:22:52 -0700 Subject: [PATCH 01/27] chore: add deferred exec code samples (#439) * chore: add deferred exec code samples * fix tests * fix tests --- bigframes/_config/compute_options.py | 11 ++++++++++ .../pandas/core/config_init.py | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/bigframes/_config/compute_options.py b/bigframes/_config/compute_options.py index 20c31d3906..fb708b844c 100644 --- a/bigframes/_config/compute_options.py +++ b/bigframes/_config/compute_options.py @@ -23,6 +23,17 @@ class ComputeOptions: """ Encapsulates configuration for compute options. + **Examples:** + + >>> import bigframes.pandas as bpd + >>> df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins") + + >>> bpd.options.compute.maximum_bytes_billed = 500 + >>> # df.to_pandas() # this should fail + google.api_core.exceptions.InternalServerError: 500 Query exceeded limit for bytes billed: 500. 10485760 or higher required. + + >>> bpd.options.compute.maximum_bytes_billed = None # reset option + Attributes: maximum_bytes_billed (int, Options): Limits the bytes billed for query jobs. Queries that will have diff --git a/third_party/bigframes_vendored/pandas/core/config_init.py b/third_party/bigframes_vendored/pandas/core/config_init.py index dfb91dfeb8..33c6b3e093 100644 --- a/third_party/bigframes_vendored/pandas/core/config_init.py +++ b/third_party/bigframes_vendored/pandas/core/config_init.py @@ -15,6 +15,26 @@ display_options_doc = """ Encapsulates configuration for displaying objects. +**Examples:** + +Define Repr mode to "deferred" will prevent job execution in repr. + >>> import bigframes.pandas as bpd + >>> df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins") + + >>> bpd.options.display.repr_mode = "deferred" + >>> df.head(20) # will no longer run the job + Computation deferred. Computation will process 28.9 kB + +Users can also get a dry run of the job by accessing the query_job property before they've run the job. This will return a dry run instance of the job they can inspect. + >>> df.query_job.total_bytes_processed + 28947 + +User can execute the job by calling .to_pandas() + >>> # df.to_pandas() + +Reset option + >>> bpd.options.display.repr_mode = "head" + Attributes: max_columns (int, default 20): If `max_columns` is exceeded, switch to truncate view. From 95f5a6e749468743af65062e559bc35ac56f3c24 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Thu, 14 Mar 2024 15:14:29 -0700 Subject: [PATCH 02/27] feat: add DataFrame.pipe() method (#421) --- tests/system/small/test_dataframe.py | 25 +++++ tests/system/small/test_series.py | 25 +++++ .../bigframes_vendored/pandas/core/common.py | 42 +++++++ .../bigframes_vendored/pandas/core/generic.py | 105 +++++++++++++++++- 4 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 third_party/bigframes_vendored/pandas/core/common.py diff --git a/tests/system/small/test_dataframe.py b/tests/system/small/test_dataframe.py index 61dcd778ef..be4211a2fc 100644 --- a/tests/system/small/test_dataframe.py +++ b/tests/system/small/test_dataframe.py @@ -1000,6 +1000,31 @@ def test_apply_series_scalar_callable( pandas.testing.assert_series_equal(bf_result, pd_result) +def test_df_pipe( + scalars_df_index, + scalars_pandas_df_index, +): + columns = ["int64_too", "int64_col"] + + def foo(x: int, y: int, df): + return (df + x) % y + + bf_result = ( + scalars_df_index[columns] + .pipe((foo, "df"), x=7, y=9) + .pipe(lambda x: x**2) + .to_pandas() + ) + + pd_result = ( + scalars_pandas_df_index[columns] + .pipe((foo, "df"), x=7, y=9) + .pipe(lambda x: x**2) + ) + + pandas.testing.assert_frame_equal(bf_result, pd_result) + + def test_df_keys( scalars_df_index, scalars_pandas_df_index, diff --git a/tests/system/small/test_series.py b/tests/system/small/test_series.py index 37b4f8c1de..f5c5b1c216 100644 --- a/tests/system/small/test_series.py +++ b/tests/system/small/test_series.py @@ -3203,3 +3203,28 @@ def test_apply_not_supported(scalars_dfs, col, lambda_, exception): bf_col = scalars_df[col] with pytest.raises(exception): bf_col.apply(lambda_, by_row=False) + + +def test_series_pipe( + scalars_df_index, + scalars_pandas_df_index, +): + column = "int64_too" + + def foo(x: int, y: int, df): + return (df + x) % y + + bf_result = ( + scalars_df_index[column] + .pipe((foo, "df"), x=7, y=9) + .pipe(lambda x: x**2) + .to_pandas() + ) + + pd_result = ( + scalars_pandas_df_index[column] + .pipe((foo, "df"), x=7, y=9) + .pipe(lambda x: x**2) + ) + + assert_series_equal(bf_result, pd_result) diff --git a/third_party/bigframes_vendored/pandas/core/common.py b/third_party/bigframes_vendored/pandas/core/common.py new file mode 100644 index 0000000000..ded5a22b8f --- /dev/null +++ b/third_party/bigframes_vendored/pandas/core/common.py @@ -0,0 +1,42 @@ +# Contains code from https://github.com/pandas-dev/pandas/blob/main/pandas/core/common.py +from __future__ import annotations + +from typing import Callable, TYPE_CHECKING + +if TYPE_CHECKING: + from bigframes_vendored.pandas.pandas._typing import T + + +def pipe( + obj, func: Callable[..., T] | tuple[Callable[..., T], str], *args, **kwargs +) -> T: + """ + Apply a function ``func`` to object ``obj`` either by passing obj as the + first argument to the function or, in the case that the func is a tuple, + interpret the first element of the tuple as a function and pass the obj to + that function as a keyword argument whose key is the value of the second + element of the tuple. + + Args: + func (callable or tuple of (callable, str)): + Function to apply to this object or, alternatively, a + ``(callable, data_keyword)`` tuple where ``data_keyword`` is a + string indicating the keyword of ``callable`` that expects the + object. + args (iterable, optional): + Positional arguments passed into ``func``. + kwargs (dict, optional): + A dictionary of keyword arguments passed into ``func``. + + Returns: + object: the return type of ``func``. + """ + if isinstance(func, tuple): + func, target = func + if target in kwargs: + msg = f"{target} is both the pipe target and a keyword argument" + raise ValueError(msg) + kwargs[target] = obj + return func(*args, **kwargs) + else: + return func(obj, *args, **kwargs) diff --git a/third_party/bigframes_vendored/pandas/core/generic.py b/third_party/bigframes_vendored/pandas/core/generic.py index 01d8f7a174..7f8e1f7b53 100644 --- a/third_party/bigframes_vendored/pandas/core/generic.py +++ b/third_party/bigframes_vendored/pandas/core/generic.py @@ -1,12 +1,16 @@ # Contains code from https://github.com/pandas-dev/pandas/blob/main/pandas/core/generic.py from __future__ import annotations -from typing import Iterator, Literal, Optional +from typing import Callable, Iterator, Literal, Optional, TYPE_CHECKING from bigframes_vendored.pandas.core import indexing +import bigframes_vendored.pandas.core.common as common from bigframes import constants +if TYPE_CHECKING: + from bigframes_vendored.pandas.pandas._typing import T + class NDFrame(indexing.IndexingMixin): """ @@ -963,6 +967,105 @@ def expanding(self, min_periods=1): """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) + def pipe( + self, + func: Callable[..., T] | tuple[Callable[..., T], str], + *args, + **kwargs, + ) -> T: + """ + Apply chainable functions that expect Series or DataFrames. + + **Examples:** + + Constructing a income DataFrame from a dictionary. + + >>> import bigframes.pandas as bpd + >>> import numpy as np + >>> bpd.options.display.progress_bar = None + + >>> data = [[8000, 1000], [9500, np.nan], [5000, 2000]] + >>> df = bpd.DataFrame(data, columns=['Salary', 'Others']) + >>> df + Salary Others + 0 8000 1000.0 + 1 9500 + 2 5000 2000.0 + + [3 rows x 2 columns] + + Functions that perform tax reductions on an income DataFrame. + + >>> def subtract_federal_tax(df): + ... return df * 0.9 + >>> def subtract_state_tax(df, rate): + ... return df * (1 - rate) + >>> def subtract_national_insurance(df, rate, rate_increase): + ... new_rate = rate + rate_increase + ... return df * (1 - new_rate) + + Instead of writing + + >>> subtract_national_insurance( + ... subtract_state_tax(subtract_federal_tax(df), rate=0.12), + ... rate=0.05, + ... rate_increase=0.02) # doctest: +SKIP + + You can write + + >>> ( + ... df.pipe(subtract_federal_tax) + ... .pipe(subtract_state_tax, rate=0.12) + ... .pipe(subtract_national_insurance, rate=0.05, rate_increase=0.02) + ... ) + Salary Others + 0 5892.48 736.56 + 1 6997.32 + 2 3682.8 1473.12 + + [3 rows x 2 columns] + + If you have a function that takes the data as (say) the second + argument, pass a tuple indicating which keyword expects the + data. For example, suppose ``national_insurance`` takes its data as ``df`` + in the second argument: + + >>> def subtract_national_insurance(rate, df, rate_increase): + ... new_rate = rate + rate_increase + ... return df * (1 - new_rate) + >>> ( + ... df.pipe(subtract_federal_tax) + ... .pipe(subtract_state_tax, rate=0.12) + ... .pipe( + ... (subtract_national_insurance, 'df'), + ... rate=0.05, + ... rate_increase=0.02 + ... ) + ... ) + Salary Others + 0 5892.48 736.56 + 1 6997.32 + 2 3682.8 1473.12 + + [3 rows x 2 columns] + + Args: + func (function): + Function to apply to this object. + ``args``, and ``kwargs`` are passed into ``func``. + Alternatively a ``(callable, data_keyword)`` tuple where + ``data_keyword`` is a string indicating the keyword of + ``callable`` that expects this object. + args (iterable, optional): + Positional arguments passed into ``func``. + kwargs (mapping, optional): + A dictionary of keyword arguments passed into ``func``. + + Returns: + same type as caller + """ + return common.pipe(self, func, *args, **kwargs) + def __nonzero__(self): raise ValueError( f"The truth value of a {type(self).__name__} is ambiguous. " From fde339b71c754e617c61052940215b77890b59e4 Mon Sep 17 00:00:00 2001 From: Lily Zhang <32233490+junyazhang@users.noreply.github.com> Date: Thu, 14 Mar 2024 22:06:09 -0700 Subject: [PATCH 03/27] feat: support datetime related casting in (Series|DataFrame|Index).astype (#442) * feat: support datetime related casting in (Series|DataFrame|Index).astype * chore: add deferred exec code samples (#439) * chore: add deferred exec code samples * fix tests * fix tests * feat: add DataFrame.pipe() method (#421) * addressed comments --------- Co-authored-by: Garrett Wu <6505921+GarrettWu@users.noreply.github.com> Co-authored-by: TrevorBergeron --- bigframes/core/compile/scalar_op_compiler.py | 59 +++++++++--- bigframes/dtypes.py | 48 ++++++++-- tests/system/small/test_series.py | 98 ++++++++++++++++++++ 3 files changed, 183 insertions(+), 22 deletions(-) diff --git a/bigframes/core/compile/scalar_op_compiler.py b/bigframes/core/compile/scalar_op_compiler.py index 3bcdd70581..67761c0330 100644 --- a/bigframes/core/compile/scalar_op_compiler.py +++ b/bigframes/core/compile/scalar_op_compiler.py @@ -634,11 +634,56 @@ def struct_field_op_impl(x: ibis_types.Value, op: ops.StructFieldOp): return struct_value[name].name(name) +def numeric_to_datatime(x: ibis_types.Value, unit: str) -> ibis_types.TimestampValue: + if not isinstance(x, ibis_types.IntegerValue) and not isinstance( + x, ibis_types.FloatingValue + ): + raise TypeError("Non-numerical types are not supposed to reach this function.") + + if unit not in UNIT_TO_US_CONVERSION_FACTORS: + raise ValueError(f"Cannot convert input with unit '{unit}'.") + x_converted = x * UNIT_TO_US_CONVERSION_FACTORS[unit] + x_converted = x_converted.cast(ibis_dtypes.int64) + + # Note: Due to an issue where casting directly to a timestamp + # without a timezone does not work, we first cast to UTC. This + # approach appears to bypass a potential bug in Ibis's cast function, + # allowing for subsequent casting to a timestamp type without timezone + # information. Further investigation is needed to confirm this behavior. + return x_converted.to_timestamp(unit="us").cast( + ibis_dtypes.Timestamp(timezone="UTC") + ) + + @scalar_op_compiler.register_unary_op(ops.AsTypeOp, pass_op=True) def astype_op_impl(x: ibis_types.Value, op: ops.AsTypeOp): to_type = bigframes.dtypes.bigframes_dtype_to_ibis_dtype(op.to_type) if isinstance(x, ibis_types.NullScalar): return ibis_types.null().cast(to_type) + + # When casting DATETIME column into INT column, we need to convert the column into TIMESTAMP first. + if to_type == ibis_dtypes.int64 and x.type() == ibis_dtypes.timestamp: + x_converted = x.cast(ibis_dtypes.Timestamp(timezone="UTC")) + return bigframes.dtypes.cast_ibis_value(x_converted, to_type) + + if to_type == ibis_dtypes.int64 and x.type() == ibis_dtypes.time: + # The conversion unit is set to "us" (microseconds) for consistency + # with pandas converting time64[us][pyarrow] to int64[pyarrow]. + return x.delta(ibis.time("00:00:00"), part="microsecond") + + if x.type() == ibis_dtypes.int64: + # The conversion unit is set to "us" (microseconds) for consistency + # with pandas converting int64[pyarrow] to timestamp[us][pyarrow], + # timestamp[us, tz=UTC][pyarrow], and time64[us][pyarrow]. + unit = "us" + x_converted = numeric_to_datatime(x, unit) + if to_type == ibis_dtypes.timestamp: + return x_converted.cast(ibis_dtypes.Timestamp()) + elif to_type == ibis_dtypes.Timestamp(timezone="UTC"): + return x_converted + elif to_type == ibis_dtypes.time: + return x_converted.time() + return bigframes.dtypes.cast_ibis_value(x, to_type) @@ -677,19 +722,7 @@ def to_datetime_op_impl(x: ibis_types.Value, op: ops.ToDatetimeOp): # The default unit is set to "ns" (nanoseconds) for consistency # with pandas, where "ns" is the default unit for datetime operations. unit = op.unit or "ns" - if unit not in UNIT_TO_US_CONVERSION_FACTORS: - raise ValueError(f"Cannot convert input with unit '{unit}'.") - x_converted = x * UNIT_TO_US_CONVERSION_FACTORS[unit] - x_converted = x_converted.cast(ibis_dtypes.int64) - - # Note: Due to an issue where casting directly to a timestamp - # without a timezone does not work, we first cast to UTC. This - # approach appears to bypass a potential bug in Ibis's cast function, - # allowing for subsequent casting to a timestamp type without timezone - # information. Further investigation is needed to confirm this behavior. - x = x_converted.to_timestamp(unit="us").cast( - ibis_dtypes.Timestamp(timezone="UTC") - ) + x = numeric_to_datatime(x, unit) return x.cast(ibis_dtypes.Timestamp(timezone="UTC" if op.utc else None)) diff --git a/bigframes/dtypes.py b/bigframes/dtypes.py index 366820f9f6..d78a88dfeb 100644 --- a/bigframes/dtypes.py +++ b/bigframes/dtypes.py @@ -60,6 +60,7 @@ "boolean", "Float64", "Int64", + "int64[pyarrow]", "string", "string[pyarrow]", "timestamp[us, tz=UTC][pyarrow]", @@ -173,6 +174,9 @@ # "string" and "string[pyarrow]" are accepted BIGFRAMES_STRING_TO_BIGFRAMES["string[pyarrow]"] = pd.StringDtype(storage="pyarrow") +# special case - both "Int64" and "int64[pyarrow]" are accepted +BIGFRAMES_STRING_TO_BIGFRAMES["int64[pyarrow]"] = pd.Int64Dtype() + # For the purposes of dataframe.memory_usage # https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#data_type_sizes DTYPE_BYTE_SIZES = { @@ -310,11 +314,12 @@ def bigframes_dtype_to_ibis_dtype( textwrap.dedent( f""" Unexpected data type {bigframes_dtype}. The following - str dtypes are supppted: 'boolean','Float64','Int64', 'string', - 'string[pyarrow]','timestamp[us, tz=UTC][pyarrow]', - 'timestamp[us][pyarrow]','date32[day][pyarrow]', - 'time64[us][pyarrow]'. The following pandas.ExtensionDtype are - supported: pandas.BooleanDtype(), pandas.Float64Dtype(), + str dtypes are supppted: 'boolean','Float64','Int64', + 'int64[pyarrow]','string','string[pyarrow]', + 'timestamp[us, tz=UTC][pyarrow]','timestamp[us][pyarrow]', + 'date32[day][pyarrow]','time64[us][pyarrow]'. + The following pandas.ExtensionDtype are supported: + pandas.BooleanDtype(), pandas.Float64Dtype(), pandas.Int64Dtype(), pandas.StringDtype(storage="pyarrow"), pd.ArrowDtype(pa.date32()), pd.ArrowDtype(pa.time64("us")), pd.ArrowDtype(pa.timestamp("us")), @@ -434,6 +439,9 @@ def cast_ibis_value( ibis_dtypes.string, ibis_dtypes.Decimal(precision=38, scale=9), ibis_dtypes.Decimal(precision=76, scale=38), + ibis_dtypes.time, + ibis_dtypes.timestamp, + ibis_dtypes.Timestamp(timezone="UTC"), ), ibis_dtypes.float64: ( ibis_dtypes.string, @@ -447,8 +455,15 @@ def cast_ibis_value( ibis_dtypes.Decimal(precision=38, scale=9), ibis_dtypes.Decimal(precision=76, scale=38), ibis_dtypes.binary, + ibis_dtypes.date, + ibis_dtypes.timestamp, + ibis_dtypes.Timestamp(timezone="UTC"), + ), + ibis_dtypes.date: ( + ibis_dtypes.string, + ibis_dtypes.timestamp, + ibis_dtypes.Timestamp(timezone="UTC"), ), - ibis_dtypes.date: (ibis_dtypes.string,), ibis_dtypes.Decimal(precision=38, scale=9): ( ibis_dtypes.float64, ibis_dtypes.Decimal(precision=76, scale=38), @@ -457,9 +472,24 @@ def cast_ibis_value( ibis_dtypes.float64, ibis_dtypes.Decimal(precision=38, scale=9), ), - ibis_dtypes.time: (), - ibis_dtypes.timestamp: (ibis_dtypes.Timestamp(timezone="UTC"),), - ibis_dtypes.Timestamp(timezone="UTC"): (ibis_dtypes.timestamp,), + ibis_dtypes.time: ( + ibis_dtypes.int64, + ibis_dtypes.string, + ), + ibis_dtypes.timestamp: ( + ibis_dtypes.date, + ibis_dtypes.int64, + ibis_dtypes.string, + ibis_dtypes.time, + ibis_dtypes.Timestamp(timezone="UTC"), + ), + ibis_dtypes.Timestamp(timezone="UTC"): ( + ibis_dtypes.date, + ibis_dtypes.int64, + ibis_dtypes.string, + ibis_dtypes.time, + ibis_dtypes.timestamp, + ), ibis_dtypes.binary: (ibis_dtypes.string,), } diff --git a/tests/system/small/test_series.py b/tests/system/small/test_series.py index f5c5b1c216..e22037a1ce 100644 --- a/tests/system/small/test_series.py +++ b/tests/system/small/test_series.py @@ -2625,6 +2625,9 @@ def foo(x): ("int64_col", "boolean"), ("int64_col", pd.ArrowDtype(pa.decimal128(38, 9))), ("int64_col", pd.ArrowDtype(pa.decimal256(76, 38))), + ("int64_col", pd.ArrowDtype(pa.timestamp("us"))), + ("int64_col", pd.ArrowDtype(pa.timestamp("us", tz="UTC"))), + ("int64_col", "time64[us][pyarrow]"), ("bool_col", "Int64"), ("bool_col", "string[pyarrow]"), ("string_col", "binary[pyarrow]"), @@ -2633,9 +2636,17 @@ def foo(x): # raises a deprecation warning to use tz_localize/tz_convert instead, # but BigQuery always stores values as UTC and doesn't have to deal # with timezone conversions, so we'll allow it. + ("timestamp_col", "date32[day][pyarrow]"), + ("timestamp_col", "time64[us][pyarrow]"), ("timestamp_col", pd.ArrowDtype(pa.timestamp("us"))), + ("datetime_col", "date32[day][pyarrow]"), + ("datetime_col", "string[pyarrow]"), + ("datetime_col", "time64[us][pyarrow]"), ("datetime_col", pd.ArrowDtype(pa.timestamp("us", tz="UTC"))), ("date_col", "string[pyarrow]"), + ("date_col", pd.ArrowDtype(pa.timestamp("us"))), + ("date_col", pd.ArrowDtype(pa.timestamp("us", tz="UTC"))), + ("time_col", "string[pyarrow]"), # TODO(bmil): fix Ibis bug: BigQuery backend rounds to nearest int # ("float64_col", "Int64"), # TODO(bmil): decide whether to fix Ibis bug: BigQuery backend @@ -2653,6 +2664,24 @@ def test_astype(scalars_df_index, scalars_pandas_df_index, column, to_type): pd.testing.assert_series_equal(bf_result, pd_result) +@pytest.mark.parametrize( + ("column", "to_type"), + [ + ("timestamp_col", "int64[pyarrow]"), + ("datetime_col", "int64[pyarrow]"), + ("time_col", "int64[pyarrow]"), + ], +) +@skip_legacy_pandas +def test_date_time_astype_int( + scalars_df_index, scalars_pandas_df_index, column, to_type +): + bf_result = scalars_df_index[column].astype(to_type).to_pandas() + pd_result = scalars_pandas_df_index[column].astype(to_type) + pd.testing.assert_series_equal(bf_result, pd_result, check_dtype=False) + assert bf_result.dtype == "Int64" + + def test_string_astype_int(): pd_series = pd.Series(["4", "-7", "0", " -03"]) bf_series = series.Series(pd_series) @@ -2676,6 +2705,75 @@ def test_string_astype_float(): pd.testing.assert_series_equal(bf_result, pd_result, check_index_type=False) +def test_string_astype_date(): + pd_series = pd.Series(["2014-08-15", "2215-08-15", "2016-02-29"]).astype( + pd.ArrowDtype(pa.string()) + ) + + bf_series = series.Series(pd_series) + + pd_result = pd_series.astype("date32[day][pyarrow]") + bf_result = bf_series.astype("date32[day][pyarrow]").to_pandas() + + pd.testing.assert_series_equal(bf_result, pd_result, check_index_type=False) + + +def test_string_astype_datetime(): + pd_series = pd.Series( + ["2014-08-15 08:15:12", "2015-08-15 08:15:12.654754", "2016-02-29 00:00:00"] + ).astype(pd.ArrowDtype(pa.string())) + + bf_series = series.Series(pd_series) + + pd_result = pd_series.astype(pd.ArrowDtype(pa.timestamp("us"))) + bf_result = bf_series.astype(pd.ArrowDtype(pa.timestamp("us"))).to_pandas() + + pd.testing.assert_series_equal(bf_result, pd_result, check_index_type=False) + + +def test_string_astype_timestamp(): + pd_series = pd.Series( + [ + "2014-08-15 08:15:12+00:00", + "2015-08-15 08:15:12.654754+05:00", + "2016-02-29 00:00:00+08:00", + ] + ).astype(pd.ArrowDtype(pa.string())) + + bf_series = series.Series(pd_series) + + pd_result = pd_series.astype(pd.ArrowDtype(pa.timestamp("us", tz="UTC"))) + bf_result = bf_series.astype( + pd.ArrowDtype(pa.timestamp("us", tz="UTC")) + ).to_pandas() + + pd.testing.assert_series_equal(bf_result, pd_result, check_index_type=False) + + +def test_timestamp_astype_string(): + bf_series = series.Series( + [ + "2014-08-15 08:15:12+00:00", + "2015-08-15 08:15:12.654754+05:00", + "2016-02-29 00:00:00+08:00", + ] + ).astype(pd.ArrowDtype(pa.timestamp("us", tz="UTC"))) + + expected_result = pd.Series( + [ + "2014-08-15 08:15:12+00", + "2015-08-15 03:15:12.654754+00", + "2016-02-28 16:00:00+00", + ] + ) + bf_result = bf_series.astype(pa.string()).to_pandas() + + pd.testing.assert_series_equal( + bf_result, expected_result, check_index_type=False, check_dtype=False + ) + assert bf_result.dtype == "string[pyarrow]" + + @pytest.mark.parametrize( "index", [0, 5, -2], From e16a8c0a6fb46cf1a7be12eec9471ae95d6f2c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Fri, 15 Mar 2024 09:53:18 -0500 Subject: [PATCH 04/27] fix: warn when `read_gbq` / `read_gbq_table` uses the snapshot time cache (#441) --- bigframes/session/__init__.py | 18 ++++++++++++++++++ tests/unit/resources.py | 12 ++++++++++++ tests/unit/session/test_session.py | 19 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/bigframes/session/__init__.py b/bigframes/session/__init__.py index 656c62ef19..2bc612bdbe 100644 --- a/bigframes/session/__init__.py +++ b/bigframes/session/__init__.py @@ -629,6 +629,24 @@ def _get_snapshot_sql_and_primary_key( job_config.labels["bigframes-api"] = api_name if use_cache and table_ref in self._df_snapshot.keys(): snapshot_timestamp = self._df_snapshot[table_ref] + + # Cache hit could be unexpected. See internal issue 329545805. + # Raise a warning with more information about how to avoid the + # problems with the cache. + warnings.warn( + f"Reading cached table from {snapshot_timestamp} to avoid " + "incompatibilies with previous reads of this table. To read " + "the latest version, set `use_cache=False` or close the " + "current session with Session.close() or " + "bigframes.pandas.close_session().", + # There are many layers before we get to (possibly) the user's code: + # pandas.read_gbq_table + # -> with_default_session + # -> Session.read_gbq_table + # -> _read_gbq_table + # -> _get_snapshot_sql_and_primary_key + stacklevel=6, + ) else: snapshot_timestamp = list( self.bqclient.query( diff --git a/tests/unit/resources.py b/tests/unit/resources.py index 967e42548f..b57cd85360 100644 --- a/tests/unit/resources.py +++ b/tests/unit/resources.py @@ -31,6 +31,9 @@ """Utilities for creating test resources.""" +TEST_SCHEMA = (google.cloud.bigquery.SchemaField("col", "INTEGER"),) + + def create_bigquery_session( bqclient: Optional[mock.Mock] = None, session_id: str = "abcxyz", @@ -44,6 +47,13 @@ def create_bigquery_session( bqclient = mock.create_autospec(google.cloud.bigquery.Client, instance=True) bqclient.project = "test-project" + # Mock the location. + table = mock.create_autospec(google.cloud.bigquery.Table, instance=True) + table._properties = {} + type(table).location = mock.PropertyMock(return_value="test-region") + type(table).schema = mock.PropertyMock(return_value=TEST_SCHEMA) + bqclient.get_table.return_value = table + if anonymous_dataset is None: anonymous_dataset = google.cloud.bigquery.DatasetReference( "test-project", @@ -61,6 +71,8 @@ def query_mock(query, *args, **kwargs): if query.startswith("SELECT CURRENT_TIMESTAMP()"): query_job.result = mock.MagicMock(return_value=[[datetime.datetime.now()]]) + else: + type(query_job).schema = mock.PropertyMock(return_value=TEST_SCHEMA) return query_job diff --git a/tests/unit/session/test_session.py b/tests/unit/session/test_session.py index b474c9f63e..3e2b28c200 100644 --- a/tests/unit/session/test_session.py +++ b/tests/unit/session/test_session.py @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import datetime import os +import re from unittest import mock import google.api_core.exceptions +import google.cloud.bigquery import pytest import bigframes @@ -31,6 +34,22 @@ def test_read_gbq_missing_parts(missing_parts_table_id): session.read_gbq(missing_parts_table_id) +def test_read_gbq_cached_table(): + session = resources.create_bigquery_session() + table_ref = google.cloud.bigquery.TableReference( + google.cloud.bigquery.DatasetReference("my-project", "my_dataset"), + "my_table", + ) + session._df_snapshot[table_ref] = datetime.datetime( + 1999, 1, 2, 3, 4, 5, 678901, tzinfo=datetime.timezone.utc + ) + + with pytest.warns(UserWarning, match=re.escape("use_cache=False")): + df = session.read_gbq("my-project.my_dataset.my_table") + + assert "1999-01-02T03:04:05.678901" in df.sql + + @pytest.mark.parametrize( "not_found_table_id", [("unknown.dataset.table"), ("project.unknown.table"), ("project.dataset.unknown")], From 91bd39e8b194ddad09d53fca96201eee58063bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Fri, 15 Mar 2024 09:54:06 -0500 Subject: [PATCH 05/27] docs: add version information to bug template (#437) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: add version information to bug template * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- .github/ISSUE_TEMPLATE/bug_report.md | 19 ++++++++++++++++++ owlbot.py | 30 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 7b0900728e..8bc1d5f787 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -22,6 +22,25 @@ If you are still having issues, please be sure to include as much information as - pip version: `pip --version` - `bigframes` version: `pip show bigframes` + +```python +import sys +import bigframes +import google.cloud.bigquery +import ibis +import pandas +import pyarrow +import sqlglot + +print(f"Python: {sys.version}") +print(f"bigframes=={bigframes.__version__}") +print(f"google-cloud-bigquery=={google.cloud.bigquery.__version__}") +print(f"ibis=={ibis.__version__}") +print(f"pandas=={pandas.__version__}") +print(f"pyarrow=={pyarrow.__version__}") +print(f"sqlglot=={sqlglot.__version__}") +``` + #### Steps to reproduce 1. ? diff --git a/owlbot.py b/owlbot.py index 4dc6d1aca3..77479401d5 100644 --- a/owlbot.py +++ b/owlbot.py @@ -16,6 +16,7 @@ import pathlib import re +import textwrap from synthtool import gcp import synthtool as s @@ -59,6 +60,35 @@ # Fixup files # ---------------------------------------------------------------------------- +# Encourage sharring all relevant versions in bug reports. +s.replace( + [".github/ISSUE_TEMPLATE/bug_report.md"], + re.escape("#### Steps to reproduce\n"), + textwrap.dedent( + """ + ```python + import sys + import bigframes + import google.cloud.bigquery + import ibis + import pandas + import pyarrow + import sqlglot + + print(f"Python: {sys.version}") + print(f"bigframes=={bigframes.__version__}") + print(f"google-cloud-bigquery=={google.cloud.bigquery.__version__}") + print(f"ibis=={ibis.__version__}") + print(f"pandas=={pandas.__version__}") + print(f"pyarrow=={pyarrow.__version__}") + print(f"sqlglot=={sqlglot.__version__}") + ``` + + #### Steps to reproduce + """, + ), +) + # Make sure build includes all necessary files. s.replace( ["MANIFEST.in"], From 1c3e668ceb26fd0f1377acbf6b95e8f4bcef40d6 Mon Sep 17 00:00:00 2001 From: Chelsea Lin <124939984+chelsea-lin@users.noreply.github.com> Date: Fri, 15 Mar 2024 09:38:54 -0700 Subject: [PATCH 06/27] feat: (Series|DataFrame).plot (#438) --- bigframes/operations/plotting.py | 57 +++++++++---------- .../system/small/operations/test_plotting.py | 28 +++++++++ .../pandas/plotting/_core.py | 38 ++++++++++++- 3 files changed, 93 insertions(+), 30 deletions(-) diff --git a/bigframes/operations/plotting.py b/bigframes/operations/plotting.py index cc9f71e5d1..ff74806993 100644 --- a/bigframes/operations/plotting.py +++ b/bigframes/operations/plotting.py @@ -23,17 +23,37 @@ class PlotAccessor(vendordt.PlotAccessor): __doc__ = vendordt.PlotAccessor.__doc__ + _common_kinds = ("line", "area", "hist") + _dataframe_kinds = ("scatter",) + _all_kinds = _common_kinds + _dataframe_kinds + + def __call__(self, **kwargs): + import bigframes.series as series + + if kwargs.pop("backend", None) is not None: + raise NotImplementedError( + f"Only support matplotlib backend for now. {constants.FEEDBACK_LINK}" + ) + + kind = kwargs.pop("kind", "line") + if kind not in self._all_kinds: + raise NotImplementedError( + f"{kind} is not a valid plot kind supported for now. {constants.FEEDBACK_LINK}" + ) + + data = self._parent.copy() + if kind in self._dataframe_kinds and isinstance(data, series.Series): + raise ValueError(f"plot kind {kind} can only be used for data frames") + + return bfplt.plot(data, kind=kind, **kwargs) + def __init__(self, data) -> None: self._parent = data def hist( self, by: typing.Optional[typing.Sequence[str]] = None, bins: int = 10, **kwargs ): - if kwargs.pop("backend", None) is not None: - raise NotImplementedError( - f"Only support matplotlib backend for now. {constants.FEEDBACK_LINK}" - ) - return bfplt.plot(self._parent.copy(), kind="hist", by=by, bins=bins, **kwargs) + return self(kind="hist", by=by, bins=bins, **kwargs) def line( self, @@ -41,13 +61,7 @@ def line( y: typing.Optional[typing.Hashable] = None, **kwargs, ): - return bfplt.plot( - self._parent.copy(), - kind="line", - x=x, - y=y, - **kwargs, - ) + return self(kind="line", x=x, y=y, **kwargs) def area( self, @@ -56,14 +70,7 @@ def area( stacked: bool = True, **kwargs, ): - return bfplt.plot( - self._parent.copy(), - kind="area", - x=x, - y=y, - stacked=stacked, - **kwargs, - ) + return self(kind="area", x=x, y=y, stacked=stacked, **kwargs) def scatter( self, @@ -73,12 +80,4 @@ def scatter( c: typing.Union[typing.Hashable, typing.Sequence[typing.Hashable]] = None, **kwargs, ): - return bfplt.plot( - self._parent.copy(), - kind="scatter", - x=x, - y=y, - s=s, - c=c, - **kwargs, - ) + return self(kind="scatter", x=x, y=y, s=s, c=c, **kwargs) diff --git a/tests/system/small/operations/test_plotting.py b/tests/system/small/operations/test_plotting.py index ce320b6f57..876c8f7d04 100644 --- a/tests/system/small/operations/test_plotting.py +++ b/tests/system/small/operations/test_plotting.py @@ -233,3 +233,31 @@ def test_sampling_plot_args_random_state(): msg = "numpy array are different" with pytest.raises(AssertionError, match=msg): tm.assert_almost_equal(ax_0.lines[0].get_data()[1], ax_2.lines[0].get_data()[1]) + + +@pytest.mark.parametrize( + ("kind", "col_names", "kwargs"), + [ + pytest.param("hist", ["int64_col", "int64_too"], {}), + pytest.param("line", ["int64_col", "int64_too"], {}), + pytest.param("area", ["int64_col", "int64_too"], {"stacked": False}), + pytest.param( + "scatter", ["int64_col", "int64_too"], {"x": "int64_col", "y": "int64_too"} + ), + pytest.param( + "scatter", + ["int64_col"], + {}, + marks=pytest.mark.xfail(raises=ValueError), + ), + pytest.param( + "uknown", + ["int64_col", "int64_too"], + {}, + marks=pytest.mark.xfail(raises=NotImplementedError), + ), + ], +) +def test_plot_call(scalars_dfs, kind, col_names, kwargs): + scalars_df, _ = scalars_dfs + scalars_df[col_names].plot(kind=kind, **kwargs) diff --git a/third_party/bigframes_vendored/pandas/plotting/_core.py b/third_party/bigframes_vendored/pandas/plotting/_core.py index 2b0f077695..d901f41ef8 100644 --- a/third_party/bigframes_vendored/pandas/plotting/_core.py +++ b/third_party/bigframes_vendored/pandas/plotting/_core.py @@ -4,7 +4,43 @@ class PlotAccessor: - """Make plots of Series or DataFrame with the `matplotlib` backend.""" + """ + Make plots of Series or DataFrame with the `matplotlib` backend. + + **Examples:** + For Series: + + >>> import bigframes.pandas as bpd + >>> ser = bpd.Series([1, 2, 3, 3]) + >>> plot = ser.plot(kind='hist', title="My plot") + + For DataFrame: + + >>> df = bpd.DataFrame({'length': [1.5, 0.5, 1.2, 0.9, 3], + ... 'width': [0.7, 0.2, 0.15, 0.2, 1.1]}, + ... index=['pig', 'rabbit', 'duck', 'chicken', 'horse']) + >>> plot = df.plot(title="DataFrame Plot") + + Args: + data (Series or DataFrame): + The object for which the method is called. + kind (str): + The kind of plot to produce: + + - 'line' : line plot (default) + - 'hist' : histogram + - 'area' : area plot + - 'scatter' : scatter plot (DataFrame only) + + **kwargs: + Options to pass to `pandas.DataFrame.plot` method. See pandas + documentation online for more on these arguments. + + Returns: + matplotlib.axes.Axes or np.ndarray of them: + An ndarray is returned with one :class:`matplotlib.axes.Axes` + per column when ``subplots=True``. + """ def hist( self, by: typing.Optional[typing.Sequence[str]] = None, bins: int = 10, **kwargs From 40ddb694b26d4dea4a05845a9007bc26c3991ff5 Mon Sep 17 00:00:00 2001 From: Shobhit Singh Date: Fri, 15 Mar 2024 18:04:18 +0000 Subject: [PATCH 07/27] test: enable BYOSA test for `remote_function` cloud function (#432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This support was added in [PR#407](https://togithub.com/googleapis/python-bigquery-dataframes/pull/407) but the test was only verified locally since the project `bigframes-load-testing` is latchkey managed and would require some extra configuration to set-up. This change does one step better by enabling the test in the automated pipelines by targeting it to a different project `bigframes-dev-perf` which is easier to set up through cloud console. Eventually it should be moved to run entirely in `bigframes-load-testing` after the necessary configuration is done through latchkey (created internal issue 329339908 to track the work). Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- tests/system/large/test_remote_function.py | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tests/system/large/test_remote_function.py b/tests/system/large/test_remote_function.py index f8c5e98f1d..c0a1f6c4ec 100644 --- a/tests/system/large/test_remote_function.py +++ b/tests/system/large/test_remote_function.py @@ -1281,19 +1281,29 @@ def square(x): ) -@pytest.mark.skip("This requires additional project config.") +@pytest.mark.flaky(retries=2, delay=120) def test_remote_function_via_session_custom_sa(scalars_dfs): - # Set these values to run the test locally - # TODO(shobs): Automate and enable this test - PROJECT = "" - GCF_SERVICE_ACCOUNT = "" + # TODO(shobs): Automate the following set-up during testing in the test project. + # + # For upfront convenience, the following set up has been statically created + # in the project bigfrmames-dev-perf via cloud console: + # + # 1. Create a service account as per + # https://cloud.google.com/iam/docs/service-accounts-create#iam-service-accounts-create-console + # 2. Give necessary roles as per + # https://cloud.google.com/functions/docs/reference/iam/roles#additional-configuration + # + project = "bigframes-dev-perf" + gcf_service_account = ( + "bigframes-dev-perf-1@bigframes-dev-perf.iam.gserviceaccount.com" + ) - rf_session = bigframes.Session(context=bigframes.BigQueryOptions(project=PROJECT)) + rf_session = bigframes.Session(context=bigframes.BigQueryOptions(project=project)) try: @rf_session.remote_function( - [int], int, reuse=False, cloud_function_service_account=GCF_SERVICE_ACCOUNT + [int], int, reuse=False, cloud_function_service_account=gcf_service_account ) def square_num(x): if x is None: @@ -1316,7 +1326,7 @@ def square_num(x): gcf = rf_session.cloudfunctionsclient.get_function( name=square_num.bigframes_cloud_function ) - assert gcf.service_config.service_account_email == GCF_SERVICE_ACCOUNT + assert gcf.service_config.service_account_email == gcf_service_account finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( From b28f9fdd9681b3c9783a6e52322b70093e0283ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Fri, 15 Mar 2024 16:11:38 -0500 Subject: [PATCH 08/27] fix: raise `ValueError` when `read_pandas()` receives a bigframes `DataFrame` (#447) * fix: raise `ValueError` when `read_pandas()` receives a bigframes `DataFrame` * make actually a unit test --- bigframes/session/__init__.py | 6 ++++++ tests/unit/session/test_io_pandas.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/bigframes/session/__init__.py b/bigframes/session/__init__.py index 2bc612bdbe..40831292de 100644 --- a/bigframes/session/__init__.py +++ b/bigframes/session/__init__.py @@ -916,6 +916,12 @@ def read_pandas(self, pandas_dataframe: pandas.DataFrame) -> dataframe.DataFrame def _read_pandas( self, pandas_dataframe: pandas.DataFrame, api_name: str ) -> dataframe.DataFrame: + if isinstance(pandas_dataframe, dataframe.DataFrame): + raise ValueError( + "read_pandas() expects a pandas.DataFrame, but got a " + "bigframes.pandas.DataFrame." + ) + if ( pandas_dataframe.size < MAX_INLINE_DF_SIZE # TODO(swast): Workaround data types limitation in inline data. diff --git a/tests/unit/session/test_io_pandas.py b/tests/unit/session/test_io_pandas.py index 959cccd80e..81d02466ef 100644 --- a/tests/unit/session/test_io_pandas.py +++ b/tests/unit/session/test_io_pandas.py @@ -13,7 +13,9 @@ # limitations under the License. import datetime +import re from typing import Dict, Union +import unittest.mock as mock import geopandas # type: ignore import numpy @@ -24,8 +26,11 @@ import pytest import bigframes.features +import bigframes.pandas import bigframes.session._io.pandas +from .. import resources + _LIST_OF_SCALARS = [ [1, 2, 3], [], @@ -475,3 +480,13 @@ def test_arrow_to_pandas_wrong_size_dtypes( ): with pytest.raises(ValueError, match=f"Number of types {len(dtypes)}"): bigframes.session._io.pandas.arrow_to_pandas(arrow_table, dtypes) + + +def test_read_pandas_with_bigframes_dataframe(): + session = resources.create_bigquery_session() + df = mock.create_autospec(bigframes.pandas.DataFrame, instance=True) + + with pytest.raises( + ValueError, match=re.escape("read_pandas() expects a pandas.DataFrame") + ): + session.read_pandas(df) From adadb0658c35142fed228abbd9baa42f9372f44b Mon Sep 17 00:00:00 2001 From: Henry Solberg Date: Fri, 15 Mar 2024 14:37:31 -0700 Subject: [PATCH 09/27] fix: fix broken link in covid notebook (#450) * fix: fix broken link in covid notebook * Update bq_dataframes_covid_line_graphs.ipynb --------- Co-authored-by: Henry J Solberg --- notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb b/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb index 8b18cc8967..cbbcc57aec 100644 --- a/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb +++ b/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb @@ -34,7 +34,7 @@ "\n", "\n", " \n", From 14ab8d834d793ac7644f066145912e6d50966881 Mon Sep 17 00:00:00 2001 From: Ashley Xu <139821907+ashleyxuu@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:58:16 -0700 Subject: [PATCH 10/27] docs: add the docs for loc and iloc indexers (#446) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- docs/reference/bigframes.pandas/index.rst | 1 + docs/reference/bigframes.pandas/indexers.rst | 32 +++++++++++++++++++ docs/templates/toc.yml | 12 +++++-- .../bigframes_vendored/pandas/core/frame.py | 15 ++++++++- .../bigframes_vendored/pandas/core/series.py | 15 ++++++++- 5 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 docs/reference/bigframes.pandas/indexers.rst diff --git a/docs/reference/bigframes.pandas/index.rst b/docs/reference/bigframes.pandas/index.rst index c7ff586884..3492f236ee 100644 --- a/docs/reference/bigframes.pandas/index.rst +++ b/docs/reference/bigframes.pandas/index.rst @@ -9,6 +9,7 @@ BigQuery DataFrames (pandas) general_functions series frame + indexers indexing window groupby diff --git a/docs/reference/bigframes.pandas/indexers.rst b/docs/reference/bigframes.pandas/indexers.rst new file mode 100644 index 0000000000..a7388bcb6b --- /dev/null +++ b/docs/reference/bigframes.pandas/indexers.rst @@ -0,0 +1,32 @@ + +========= +Indexers +========= + +ILocDataFrameIndexer +-------------------- +.. autoclass:: bigframes.core.indexers.ILocDataFrameIndexer + :members: + :inherited-members: + :undoc-members: + +IlocSeriesIndexer +----------------- +.. autoclass:: bigframes.core.indexers.IlocSeriesIndexer + :members: + :inherited-members: + :undoc-members: + +LocDataFrameIndexer +------------------- +.. autoclass:: bigframes.core.indexers.LocDataFrameIndexer + :members: + :inherited-members: + :undoc-members: + +LocSeriesIndexer +---------------- +.. autoclass:: bigframes.core.indexers.LocSeriesIndexer + :members: + :inherited-members: + :undoc-members: diff --git a/docs/templates/toc.yml b/docs/templates/toc.yml index 66973fc5a2..224b535416 100644 --- a/docs/templates/toc.yml +++ b/docs/templates/toc.yml @@ -40,8 +40,16 @@ - name: SeriesGroupBy uid: bigframes.core.groupby.SeriesGroupBy name: Groupby - - name: Indexes - uid: bigframes.core.indexes.index.Index + - items: + - name: ILocDataFrameIndexer + uid: bigframes.core.indexers.ILocDataFrameIndexer + - name: IlocSeriesIndexer + uid: bigframes.core.indexers.IlocSeriesIndexer + - name: LocDataFrameIndexer + uid: bigframes.core.indexers.LocDataFrameIndexer + - name: LocSeriesIndexer + uid: bigframes.core.indexers.LocSeriesIndexer + name: Indexers - name: pandas uid: bigframes.pandas - items: diff --git a/third_party/bigframes_vendored/pandas/core/frame.py b/third_party/bigframes_vendored/pandas/core/frame.py index 313c6663c8..7793b31a21 100644 --- a/third_party/bigframes_vendored/pandas/core/frame.py +++ b/third_party/bigframes_vendored/pandas/core/frame.py @@ -5111,7 +5111,20 @@ def replace( @property def iloc(self): - """Purely integer-location based indexing for selection by position.""" + """Purely integer-location based indexing for selection by position. + + Returns: + bigframes.core.indexers.ILocDataFrameIndexer: Purely integer-location Indexers. + """ + raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) + + @property + def loc(self): + """Access a group of rows and columns by label(s) or a boolean array. + + Returns: + bigframes.core.indexers.ILocDataFrameIndexer: Indexers object. + """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) @property diff --git a/third_party/bigframes_vendored/pandas/core/series.py b/third_party/bigframes_vendored/pandas/core/series.py index beaf8aedb1..ab96e731b9 100644 --- a/third_party/bigframes_vendored/pandas/core/series.py +++ b/third_party/bigframes_vendored/pandas/core/series.py @@ -3313,7 +3313,20 @@ def map( @property def iloc(self): - """Purely integer-location based indexing for selection by position.""" + """Purely integer-location based indexing for selection by position. + + Returns: + bigframes.core.indexers.IlocSeriesIndexer: Purely integer-location Indexers. + """ + raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) + + @property + def loc(self): + """Access a group of rows and columns by label(s) or a boolean array. + + Returns: + bigframes.core.indexers.LocSeriesIndexer: Indexers object. + """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) @property From 1df014010652e7827a2720a906d0afe482a30ca9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Mon, 18 Mar 2024 13:18:35 -0500 Subject: [PATCH 11/27] docs: indicate that project and location are optional in example notebooks (#451) --- notebooks/dataframes/dataframe.ipynb | 4442 +++++++++-------- .../bq_dataframes_llm_code_generation.ipynb | 152 +- .../bq_dataframes_llm_kmeans.ipynb | 462 +- ...q_dataframes_ml_drug_name_generation.ipynb | 7 + .../getting_started_bq_dataframes.ipynb | 906 +++- .../ml_fundamentals_bq_dataframes.ipynb | 3574 ++++++++++++- notebooks/location/regionalized.ipynb | 7 + .../bq_dataframes_ml_linear_regression.ipynb | 17 +- .../bq_dataframes_covid_line_graphs.ipynb | 174 +- 9 files changed, 7119 insertions(+), 2622 deletions(-) diff --git a/notebooks/dataframes/dataframe.ipynb b/notebooks/dataframes/dataframe.ipynb index c6b276af87..15da075552 100644 --- a/notebooks/dataframes/dataframe.ipynb +++ b/notebooks/dataframes/dataframe.ipynb @@ -12,56 +12,12 @@ { "cell_type": "code", "execution_count": 1, - "id": "72ebb083-f06b-4408-b24d-f349bd0851e3", + "id": "96757c59-fc22-420e-a42f-c6cb956110ec", "metadata": {}, "outputs": [], "source": [ - "# On the instance where you are running jupyter,\n", - "# authenticate with gcloud first:\n", - "#\n", - "# gcloud auth application-default login\n", - "\n", "import bigframes.pandas as bpd\n", "\n", - "bpd.options.bigquery.location = \"US\"" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "96757c59-fc22-420e-a42f-c6cb956110ec", - "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "11c27813da5c4d2e8108bf4bd9e7e55d", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "HTML(value='Query job ccb31707-38d2-4d93-8502-e39352f322a3 is RUNNING. " ] }, "metadata": {}, @@ -106,13 +60,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d1fce57541264fa1b61e1acbc99393d7", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 1280ea98-5503-4b32-899b-65ce4b4ad50f is DONE. 582.8 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job fdc644e2-c008-485a-90b2-dc64e5c81f3b is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -149,203 +101,203 @@ " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", + " \n", " \n", - " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", - " \n", + " \n", " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", " \n", " \n", "
\n", - " \n", + " \n", " \"Colab Run in Colab\n", " \n", "
0e14b6493-9e7f-404f-840a-8a680cc364bfd60c6036-0ce1-4c90-8dd9-de3b403c92a82016MarlinsCubs187NationalsBrewers167
11f32b347-cbcb-4c31-a145-0e685306d168af72a0b9-65f7-49fb-9b30-d505068bdf6d2016MarlinsCubs189RedsBrewers172
20c2292d1-7398-48be-bf8e-b41dad5e1a43f57e1271-d217-400a-aea6-2e2d7d6a59a02016BravesCubs165OriolesRays166
38fbec734-a15a-42ab-8d51-60790de7750b198f4eed-a29f-41e2-8623-cb261e5ab3702016BravesCubs222RockiesGiants182
489e514d5-fbf5-4b9d-bdac-6ca45bfd18ddcb3ef033-dd57-41fd-b206-cdd3bc12c74f2016PhilliesCubs164TwinsIndians204
56a83e76c-dc0d-4924-9d3d-a2e7e0ab5b524be9f735-a98e-4689-87ce-852cc3a1e79d2016DiamondbacksCubs201Blue JaysOrioles184
676ea8662-c7e6-4c38-8f2a-efe373e428ce0b2de8c3-11d9-4f0f-a186-25b59f34a5d82016AthleticsCubs173YankeesMets182
766fad23d-6e89-4f99-be29-d49b6e94f95d60d80663-6ced-44aa-aad9-0f4bf8d3b4d22016AthleticsCubs176Red SoxRays191
8d977367c-cf0c-4687-95a0-eb4542efcb017e1c2095-4fea-454c-8773-096ceb6fb05c2016RockiesCubs180CardinalsPirates201
9a87070ff-1084-43ca-a7ba-69278f93ecbaf7f24ce3-7f9d-4e8a-986e-095db847c4c12016CardinalsCubs157RaysTwins189
10ea6b350d-3c1d-4737-878d-4465f66999f65c26e7fc-c99f-48b4-92c1-4a7208c8cfe92016CardinalsCubs218RaysTwins177
1146463c50-0f5c-4dca-a661-dd194464e7916d2cab13-dd85-477a-8769-669069f858362016CardinalsCubs160RoyalsRays183
1259134e6d-9d13-49aa-978e-c3c2300eb90fbca90342-7ddc-468e-b189-d43fad7528ec2016PiratesCubs178AstrosRays194
13387630a3-a894-4327-baa1-b24ec1a654d9630f4f78-03cc-43c1-9e57-ababb9c114182016PiratesCubs205DodgersGiants178
145d084e13-94fd-4995-b95a-4801ea3ed556c0cf1376-1115-4a2f-b457-3f82bbc41a892016GiantsCubs197TigersWhite Sox193
1534444c94-03ec-4d12-96af-68b8f399a22f46463c50-0f5c-4dca-a661-dd194464e7912016RedsCardinalsCubs198160
169580bffe-22e1-4975-978b-1b13e7505193392ad56d-972e-4f77-98e2-5f8577931cf82016RedsCubs188GiantsCardinals169
17645e6a08-afd6-4677-a5c9-01ef446b0cf3307730fa-bbed-4221-b4e6-a2492f546fd52016RedsCubs188Red SoxTwins251
1808981bd8-d1d7-48e1-8668-9098b8f7fe901cbc558f-7615-4fa9-bf97-7ccd62040d6f2016RedsCubs194MetsBraves151
19303703bb-b55f-476d-8faf-bf582169fb1d723348ba-1645-43fc-9e22-92994f7a63bd2016PadresCubs175AthleticsTwins153
2071ab82a4-6e07-430a-b695-1af3bc42ea61ffbd6ecc-82e1-4e5d-9bd1-4ea210be59922016NationalsCubs257TwinsMarlins185
21d1a110c2-f6c8-4029-bcd8-2f8a01e1561cf2747230-7df5-4535-a475-a1c823d0d6542016BrewersCubs178TwinsYankees180
226d111b57-fa0b-4f24-82df-ff33a26f0252db3b6f35-a7a4-430a-8703-2b2f25103e172016BrewersCubs171White SoxOrioles199
23a97e9539-bbbd-4e03-bf15-f25ea2c1d9235fc8c6f0-a70e-4d1b-877f-eb1ec8e6f6362016BrewersCubs248DiamondbacksGiants175
24dc0c9218-505c-4725-8c0c-40b72cca095695d548b6-2da8-4644-812e-b277fec5b91f2016AstrosCubs174BravesMets201
\n", @@ -354,64 +306,64 @@ ], "text/plain": [ " gameId year homeTeamName awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[2431 rows x 5 columns]" ] }, - "execution_count": 4, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -423,7 +375,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "a6b8b3ac-1df8-46ff-ac4f-d6e7657fc80c", "metadata": {}, "outputs": [ @@ -433,7 +385,7 @@ "(2431, 5)" ] }, - "execution_count": 5, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -453,7 +405,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "34457cc7-e734-4e3f-9f2b-34cdd4e2aba4", "metadata": { "tags": [] @@ -470,7 +422,7 @@ "dtype: object" ] }, - "execution_count": 6, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -481,7 +433,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "b4f4383f-f596-41d8-aad2-2fd68d261cfd", "metadata": {}, "outputs": [ @@ -491,7 +443,7 @@ "Index(['gameId', 'year', 'homeTeamName', 'awayTeamName', 'duration_minutes'], dtype='object')" ] }, - "execution_count": 7, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -511,7 +463,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "c7017f3d-869d-42e3-bbd8-b3fbc408c2d0", "metadata": { "tags": [] @@ -519,13 +471,11 @@ "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "653525aaa4394009ae97f54ba868dcf8", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job e8a94ab7-7833-43ac-bf14-bfd4310260b9 is DONE. 582.8 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job c4b8deed-0c47-4ce7-b013-d8b24997851a is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -533,13 +483,23 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "298f5e9b7b094a4992ae304aba43a479", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 8b1e4a6c-9f93-4588-9c34-ae324a42fd57 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job e6830838-99ae-4162-a47f-2185bb9c1f27 is DONE. 193.8 kB processed. " + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 18db85e7-c94f-46ec-b981-5c582b5ce22a is DONE. 261.3 kB processed. Open Job" + ], + "text/plain": [ + "" ] }, "metadata": {}, @@ -577,228 +537,228 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", - " Marlins vs Cubs\n", + " Nationals\n", + " Brewers\n", + " 167\n", + " Nationals vs Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", - " Marlins vs Cubs\n", + " Reds\n", + " Brewers\n", + " 172\n", + " Reds vs Brewers\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", - " Braves vs Cubs\n", + " Orioles\n", + " Rays\n", + " 166\n", + " Orioles vs Rays\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", - " Braves vs Cubs\n", + " Rockies\n", + " Giants\n", + " 182\n", + " Rockies vs Giants\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", - " Phillies vs Cubs\n", + " Twins\n", + " Indians\n", + " 204\n", + " Twins vs Indians\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", - " Diamondbacks vs Cubs\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", + " Blue Jays vs Orioles\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", - " Athletics vs Cubs\n", + " Yankees\n", + " Mets\n", + " 182\n", + " Yankees vs Mets\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", - " Athletics vs Cubs\n", + " Red Sox\n", + " Rays\n", + " 191\n", + " Red Sox vs Rays\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", - " Rockies vs Cubs\n", + " Cardinals\n", + " Pirates\n", + " 201\n", + " Cardinals vs Pirates\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", - " Cardinals vs Cubs\n", + " Rays\n", + " Twins\n", + " 189\n", + " Rays vs Twins\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", - " Cardinals vs Cubs\n", + " Rays\n", + " Twins\n", + " 177\n", + " Rays vs Twins\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", - " Cardinals vs Cubs\n", + " Royals\n", + " Rays\n", + " 183\n", + " Royals vs Rays\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", - " Pirates vs Cubs\n", + " Astros\n", + " Rays\n", + " 194\n", + " Astros vs Rays\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", - " Pirates vs Cubs\n", + " Dodgers\n", + " Giants\n", + " 178\n", + " Dodgers vs Giants\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", - " Giants vs Cubs\n", + " Tigers\n", + " White Sox\n", + " 193\n", + " Tigers vs White Sox\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", - " Reds vs Cubs\n", + " 160\n", + " Cardinals vs Cubs\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", - " Reds vs Cubs\n", + " Giants\n", + " Cardinals\n", + " 169\n", + " Giants vs Cardinals\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", - " Reds vs Cubs\n", + " Red Sox\n", + " Twins\n", + " 251\n", + " Red Sox vs Twins\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", - " Reds vs Cubs\n", + " Mets\n", + " Braves\n", + " 151\n", + " Mets vs Braves\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", - " Padres vs Cubs\n", + " Athletics\n", + " Twins\n", + " 153\n", + " Athletics vs Twins\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", - " Nationals vs Cubs\n", + " Twins\n", + " Marlins\n", + " 185\n", + " Twins vs Marlins\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", - " Brewers vs Cubs\n", + " Twins\n", + " Yankees\n", + " 180\n", + " Twins vs Yankees\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", - " Brewers vs Cubs\n", + " White Sox\n", + " Orioles\n", + " 199\n", + " White Sox vs Orioles\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", - " Brewers vs Cubs\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", + " Diamondbacks vs Giants\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", - " Astros vs Cubs\n", + " Braves\n", + " Mets\n", + " 201\n", + " Braves vs Mets\n", " \n", " \n", "\n", @@ -807,64 +767,64 @@ ], "text/plain": [ " gameId year homeTeamName awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", - " duration_minutes title \n", - "0 187 Marlins vs Cubs \n", - "1 189 Marlins vs Cubs \n", - "2 165 Braves vs Cubs \n", - "3 222 Braves vs Cubs \n", - "4 164 Phillies vs Cubs \n", - "5 201 Diamondbacks vs Cubs \n", - "6 173 Athletics vs Cubs \n", - "7 176 Athletics vs Cubs \n", - "8 180 Rockies vs Cubs \n", - "9 157 Cardinals vs Cubs \n", - "10 218 Cardinals vs Cubs \n", - "11 160 Cardinals vs Cubs \n", - "12 178 Pirates vs Cubs \n", - "13 205 Pirates vs Cubs \n", - "14 197 Giants vs Cubs \n", - "15 198 Reds vs Cubs \n", - "16 188 Reds vs Cubs \n", - "17 188 Reds vs Cubs \n", - "18 194 Reds vs Cubs \n", - "19 175 Padres vs Cubs \n", - "20 257 Nationals vs Cubs \n", - "21 178 Brewers vs Cubs \n", - "22 171 Brewers vs Cubs \n", - "23 248 Brewers vs Cubs \n", - "24 174 Astros vs Cubs \n", + " duration_minutes title \n", + "0 167 Nationals vs Brewers \n", + "1 172 Reds vs Brewers \n", + "2 166 Orioles vs Rays \n", + "3 182 Rockies vs Giants \n", + "4 204 Twins vs Indians \n", + "5 184 Blue Jays vs Orioles \n", + "6 182 Yankees vs Mets \n", + "7 191 Red Sox vs Rays \n", + "8 201 Cardinals vs Pirates \n", + "9 189 Rays vs Twins \n", + "10 177 Rays vs Twins \n", + "11 183 Royals vs Rays \n", + "12 194 Astros vs Rays \n", + "13 178 Dodgers vs Giants \n", + "14 193 Tigers vs White Sox \n", + "15 160 Cardinals vs Cubs \n", + "16 169 Giants vs Cardinals \n", + "17 251 Red Sox vs Twins \n", + "18 151 Mets vs Braves \n", + "19 153 Athletics vs Twins \n", + "20 185 Twins vs Marlins \n", + "21 180 Twins vs Yankees \n", + "22 199 White Sox vs Orioles \n", + "23 175 Diamondbacks vs Giants \n", + "24 201 Braves vs Mets \n", "...\n", "\n", "[2431 rows x 6 columns]" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -885,19 +845,17 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "id": "8bbe000a-36f0-4b6f-b403-b9ec28dd608b", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "ea2f330fcba44a8ca8c9919641e6a881", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job ef76c434-c4bc-4b4c-bb06-61521fc85b15 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 2062db30-30ae-42cf-8afa-9b8f3493fd98 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -905,13 +863,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3f6c6bb6171c40129d023e08d73a75ad", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job d3e413ee-c0c3-49fe-a2ad-f61d671593eb is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 9c36c84f-e672-46e1-a134-7ef2c2e60b4e is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -949,228 +905,228 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", - " Marlins vs Cubs\n", + " Nationals\n", + " Brewers\n", + " 167\n", + " Nationals vs Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", - " Marlins vs Cubs\n", + " Reds\n", + " Brewers\n", + " 172\n", + " Reds vs Brewers\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", - " Braves vs Cubs\n", + " Orioles\n", + " Rays\n", + " 166\n", + " Orioles vs Rays\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", - " Braves vs Cubs\n", + " Rockies\n", + " Giants\n", + " 182\n", + " Rockies vs Giants\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", - " Phillies vs Cubs\n", + " Twins\n", + " Indians\n", + " 204\n", + " Twins vs Indians\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", - " Diamondbacks vs Cubs\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", + " Blue Jays vs Orioles\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", - " Athletics vs Cubs\n", + " Yankees\n", + " Mets\n", + " 182\n", + " Yankees vs Mets\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", - " Athletics vs Cubs\n", + " Red Sox\n", + " Rays\n", + " 191\n", + " Red Sox vs Rays\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", - " Rockies vs Cubs\n", + " Cardinals\n", + " Pirates\n", + " 201\n", + " Cardinals vs Pirates\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", - " Cardinals vs Cubs\n", + " Rays\n", + " Twins\n", + " 189\n", + " Rays vs Twins\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", - " Cardinals vs Cubs\n", + " Rays\n", + " Twins\n", + " 177\n", + " Rays vs Twins\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", - " Cardinals vs Cubs\n", + " Royals\n", + " Rays\n", + " 183\n", + " Royals vs Rays\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", - " Pirates vs Cubs\n", + " Astros\n", + " Rays\n", + " 194\n", + " Astros vs Rays\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", - " Pirates vs Cubs\n", + " Dodgers\n", + " Giants\n", + " 178\n", + " Dodgers vs Giants\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", - " Giants vs Cubs\n", + " Tigers\n", + " White Sox\n", + " 193\n", + " Tigers vs White Sox\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", - " Reds vs Cubs\n", + " 160\n", + " Cardinals vs Cubs\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", - " Reds vs Cubs\n", + " Giants\n", + " Cardinals\n", + " 169\n", + " Giants vs Cardinals\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", - " Reds vs Cubs\n", + " Red Sox\n", + " Twins\n", + " 251\n", + " Red Sox vs Twins\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", - " Reds vs Cubs\n", + " Mets\n", + " Braves\n", + " 151\n", + " Mets vs Braves\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", - " Padres vs Cubs\n", + " Athletics\n", + " Twins\n", + " 153\n", + " Athletics vs Twins\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", - " Nationals vs Cubs\n", + " Twins\n", + " Marlins\n", + " 185\n", + " Twins vs Marlins\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", - " Brewers vs Cubs\n", + " Twins\n", + " Yankees\n", + " 180\n", + " Twins vs Yankees\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", - " Brewers vs Cubs\n", + " White Sox\n", + " Orioles\n", + " 199\n", + " White Sox vs Orioles\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", - " Brewers vs Cubs\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", + " Diamondbacks vs Giants\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", - " Astros vs Cubs\n", + " Braves\n", + " Mets\n", + " 201\n", + " Braves vs Mets\n", " \n", " \n", "\n", @@ -1179,64 +1135,64 @@ ], "text/plain": [ " gameId year homeTeamName awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", - " duration_minutes headline \n", - "0 187 Marlins vs Cubs \n", - "1 189 Marlins vs Cubs \n", - "2 165 Braves vs Cubs \n", - "3 222 Braves vs Cubs \n", - "4 164 Phillies vs Cubs \n", - "5 201 Diamondbacks vs Cubs \n", - "6 173 Athletics vs Cubs \n", - "7 176 Athletics vs Cubs \n", - "8 180 Rockies vs Cubs \n", - "9 157 Cardinals vs Cubs \n", - "10 218 Cardinals vs Cubs \n", - "11 160 Cardinals vs Cubs \n", - "12 178 Pirates vs Cubs \n", - "13 205 Pirates vs Cubs \n", - "14 197 Giants vs Cubs \n", - "15 198 Reds vs Cubs \n", - "16 188 Reds vs Cubs \n", - "17 188 Reds vs Cubs \n", - "18 194 Reds vs Cubs \n", - "19 175 Padres vs Cubs \n", - "20 257 Nationals vs Cubs \n", - "21 178 Brewers vs Cubs \n", - "22 171 Brewers vs Cubs \n", - "23 248 Brewers vs Cubs \n", - "24 174 Astros vs Cubs \n", + " duration_minutes headline \n", + "0 167 Nationals vs Brewers \n", + "1 172 Reds vs Brewers \n", + "2 166 Orioles vs Rays \n", + "3 182 Rockies vs Giants \n", + "4 204 Twins vs Indians \n", + "5 184 Blue Jays vs Orioles \n", + "6 182 Yankees vs Mets \n", + "7 191 Red Sox vs Rays \n", + "8 201 Cardinals vs Pirates \n", + "9 189 Rays vs Twins \n", + "10 177 Rays vs Twins \n", + "11 183 Royals vs Rays \n", + "12 194 Astros vs Rays \n", + "13 178 Dodgers vs Giants \n", + "14 193 Tigers vs White Sox \n", + "15 160 Cardinals vs Cubs \n", + "16 169 Giants vs Cardinals \n", + "17 251 Red Sox vs Twins \n", + "18 151 Mets vs Braves \n", + "19 153 Athletics vs Twins \n", + "20 185 Twins vs Marlins \n", + "21 180 Twins vs Yankees \n", + "22 199 White Sox vs Orioles \n", + "23 175 Diamondbacks vs Giants \n", + "24 201 Braves vs Mets \n", "...\n", "\n", "[2431 rows x 6 columns]" ] }, - "execution_count": 9, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -1248,7 +1204,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "id": "87eee643-28ac-4f4b-ac61-1f3de9c08a9d", "metadata": {}, "outputs": [], @@ -1258,19 +1214,17 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "id": "fad6d3da-1f40-4c5f-94ec-0bdfe21ca5b6", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "fae17c24b2be4a47a72cc067e7b38e8c", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 051b3d23-5ab2-4022-adfc-f6553eb8532d is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job f0ed19be-b1f5-4333-a51f-3c7872a2bbc6 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -1278,13 +1232,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5b93b75abff04a36b186e3894bc9e957", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job f7356669-04f8-46f9-bf9b-f8cd997d6162 is DONE. 213.3 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 863e72d3-b421-4e53-98bb-9bf634fe9a71 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -1321,203 +1273,203 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", + " Nationals\n", + " Brewers\n", + " 167\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", + " Reds\n", + " Brewers\n", + " 172\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", + " Orioles\n", + " Rays\n", + " 166\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", + " Rockies\n", + " Giants\n", + " 182\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", + " Twins\n", + " Indians\n", + " 204\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", + " Yankees\n", + " Mets\n", + " 182\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", + " Red Sox\n", + " Rays\n", + " 191\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", + " Cardinals\n", + " Pirates\n", + " 201\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", + " Rays\n", + " Twins\n", + " 189\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", + " Rays\n", + " Twins\n", + " 177\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", + " Royals\n", + " Rays\n", + " 183\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", + " Astros\n", + " Rays\n", + " 194\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", + " Dodgers\n", + " Giants\n", + " 178\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", + " Tigers\n", + " White Sox\n", + " 193\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Giants\n", + " Cardinals\n", + " 169\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Red Sox\n", + " Twins\n", + " 251\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", + " Mets\n", + " Braves\n", + " 151\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", + " Athletics\n", + " Twins\n", + " 153\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", + " Twins\n", + " Marlins\n", + " 185\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", + " Twins\n", + " Yankees\n", + " 180\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", + " White Sox\n", + " Orioles\n", + " 199\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", + " Braves\n", + " Mets\n", + " 201\n", " \n", " \n", "\n", @@ -1526,64 +1478,64 @@ ], "text/plain": [ " gameId year homeTeamName awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[2431 rows x 5 columns]" ] }, - "execution_count": 11, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -1603,19 +1555,29 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "id": "67a7c35f-80cf-4482-80f9-7f01c7743807", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b5b2da9ef7864a51adfbc7d3c85c46b7", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job bd315bd7-1f10-4f1b-9997-10a294b1f464 is DONE. 232.7 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 972bf072-22c2-49ef-8764-1c1109dfc0a3 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job e387be31-99fc-46a9-9de7-3bb83ff1f4fe is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -1623,13 +1585,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "32a12de102694ac8bbf0dfa16d17be72", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 42c0cf8a-4276-479f-b8de-dcfce94ae42a is DONE. 213.3 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job af23a9a2-151d-469a-a5c7-588ea60d1602 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -1666,203 +1626,203 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", + " Nationals\n", + " Brewers\n", + " 167\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", + " Reds\n", + " Brewers\n", + " 172\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", + " Orioles\n", + " Rays\n", + " 166\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", + " Rockies\n", + " Giants\n", + " 182\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", + " Twins\n", + " Indians\n", + " 204\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", + " Yankees\n", + " Mets\n", + " 182\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", + " Red Sox\n", + " Rays\n", + " 191\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", + " Cardinals\n", + " Pirates\n", + " 201\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", + " Rays\n", + " Twins\n", + " 189\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", + " Rays\n", + " Twins\n", + " 177\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", + " Royals\n", + " Rays\n", + " 183\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", + " Astros\n", + " Rays\n", + " 194\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", + " Dodgers\n", + " Giants\n", + " 178\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", + " Tigers\n", + " White Sox\n", + " 193\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Giants\n", + " Cardinals\n", + " 169\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Red Sox\n", + " Twins\n", + " 251\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", + " Mets\n", + " Braves\n", + " 151\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", + " Athletics\n", + " Twins\n", + " 153\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", + " Twins\n", + " Marlins\n", + " 185\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", + " Twins\n", + " Yankees\n", + " 180\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", + " White Sox\n", + " Orioles\n", + " 199\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", + " Braves\n", + " Mets\n", + " 201\n", " \n", " \n", "\n", @@ -1871,64 +1831,64 @@ ], "text/plain": [ " gameId year homeTeamName awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[2431 rows x 5 columns]" ] }, - "execution_count": 12, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -1949,19 +1909,17 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "id": "3f09ff32-ef43-4fab-a86b-8868afc34363", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "30a9e3bd880a4c718ec3a581e0139e21", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 3c859587-582d-4b68-8b35-7072b9a42346 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job b14b9796-f94d-48c0-a477-13f6b865e11d is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -1969,13 +1927,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "7a1e5045b4ae4567b7be9f6f7bf39e3a", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 15bf1d87-152a-45a5-b000-e8e72ce6a982 is DONE. 152.8 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 20f025c3-4d84-49e9-9fbd-d77eeb2c6e04 is RUNNING. " ] }, "metadata": {}, @@ -2009,128 +1965,128 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", - " Marlins\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", + " Nationals\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", - " Marlins\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", + " Reds\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", - " Braves\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", + " Orioles\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", - " Braves\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", + " Rockies\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", - " Phillies\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", + " Twins\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", - " Diamondbacks\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", + " Blue Jays\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", - " Athletics\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", + " Yankees\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", - " Athletics\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", + " Red Sox\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", - " Rockies\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", + " Cardinals\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", - " Cardinals\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", + " Rays\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", - " Cardinals\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", + " Rays\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", - " Cardinals\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", + " Royals\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", - " Pirates\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", + " Astros\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", - " Pirates\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", + " Dodgers\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", - " Giants\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", + " Tigers\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", - " Reds\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " Cardinals\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", - " Reds\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", + " Giants\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", - " Reds\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", + " Red Sox\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", - " Reds\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", + " Mets\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", - " Padres\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", + " Athletics\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", - " Nationals\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", + " Twins\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", - " Brewers\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", + " Twins\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", - " Brewers\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", + " White Sox\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", - " Brewers\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", + " Diamondbacks\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", - " Astros\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", + " Braves\n", " \n", " \n", "\n", @@ -2139,37 +2095,37 @@ ], "text/plain": [ " gameId homeTeamName\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf Marlins\n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 Marlins\n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 Braves\n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b Braves\n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd Phillies\n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 Diamondbacks\n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce Athletics\n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d Athletics\n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 Rockies\n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba Cardinals\n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 Cardinals\n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 Cardinals\n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f Pirates\n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 Pirates\n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 Giants\n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f Reds\n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 Reds\n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 Reds\n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 Reds\n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d Padres\n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 Nationals\n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c Brewers\n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 Brewers\n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 Brewers\n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 Astros\n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 Nationals\n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d Reds\n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 Orioles\n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 Rockies\n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f Twins\n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d Blue Jays\n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 Yankees\n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 Red Sox\n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c Cardinals\n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 Rays\n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 Rays\n", + "11 6d2cab13-dd85-477a-8769-669069f85836 Royals\n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec Astros\n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 Dodgers\n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 Tigers\n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 Cardinals\n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 Giants\n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 Red Sox\n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f Mets\n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd Athletics\n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 Twins\n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 Twins\n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 White Sox\n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 Diamondbacks\n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f Braves\n", "...\n", "\n", "[2431 rows x 2 columns]" ] }, - "execution_count": 13, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -2181,19 +2137,29 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "id": "5331d2c8-7912-4d96-8da1-f64b57374df3", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2b06ade302254b7399d74edca095140c", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 262a8d65-8eb7-4769-b26d-4a1d93f19950 is DONE. 152.8 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job a18f6c86-dbff-4846-8d21-8f8c1d700a80 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job fbd5deef-4c7f-4345-ab6c-28c3e24bd918 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2201,13 +2167,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "e7413e47e1344d498851383a077917ed", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 9cc89303-be7a-4c34-b4c0-d1d75837a1e4 is DONE. 126 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job ba580b64-ca65-4245-b17f-12fd382b2e2b is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2241,13 +2205,13 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", - " Cubs\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", + " Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", - " Cubs\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", + " Brewers\n", " \n", " \n", "\n", @@ -2256,13 +2220,13 @@ ], "text/plain": [ " gameId awayTeamName\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf Cubs\n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 Cubs\n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 Brewers\n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d Brewers\n", "\n", "[2 rows x 2 columns]" ] }, - "execution_count": 14, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -2274,19 +2238,29 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "id": "a574ad3e-a219-454c-8bb5-c5ed6627f2c6", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0e076fa03b6b41878386abcaa9aeb757", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 1edf3455-802d-4b93-900b-9677cb43955a is DONE. 133.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 98cccaa5-e630-4edf-bc15-2823e89aecb6 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 3f54256f-7189-400b-8d47-5ce1f6fe92c0 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2294,13 +2268,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3a87a0d2d7cc4d429191b6e7ceeb8a0b", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 91af749e-6afa-488a-83da-1257667460f0 is DONE. 143 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 57211b59-73c2-42d6-88bd-a614a8baf779 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2335,15 +2307,15 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", - " Marlins\n", - " Cubs\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", + " Nationals\n", + " Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", - " Marlins\n", - " Cubs\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", + " Reds\n", + " Brewers\n", " \n", " \n", "\n", @@ -2352,13 +2324,13 @@ ], "text/plain": [ " gameId homeTeamName awayTeamName\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf Marlins Cubs\n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 Marlins Cubs\n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 Nationals Brewers\n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d Reds Brewers\n", "\n", "[2 rows x 3 columns]" ] }, - "execution_count": 15, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -2369,19 +2341,29 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "id": "288e7a95-a077-46c4-8fe6-802474c01f8b", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "e974466302964b7785881ed1ce96ec75", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job dfe4d1ec-9a3d-4877-ab39-bb6f1c38d070 is DONE. 133.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 6261a857-d256-4051-8af5-c6b04fb2795f is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 07ee6beb-b805-4ba9-8cb2-174d4e62ddfb is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2389,13 +2371,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4f07980adb1f4f9eb2e2f80de5f0a174", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job df400799-b054-4969-83a0-089fb2b25fdd is DONE. 152.9 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job ced45fc3-cfdb-4cd0-96ef-16a29d8d8f0b is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2430,152 +2410,152 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", - " Marlins\n", - " Cubs\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", + " Nationals\n", + " Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", - " Marlins\n", - " Cubs\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", + " Reds\n", + " Brewers\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", - " Braves\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", + " Orioles\n", " <NA>\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", - " Braves\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", + " Rockies\n", " <NA>\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", - " Phillies\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", + " Twins\n", " <NA>\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", - " Diamondbacks\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", + " Blue Jays\n", " <NA>\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", - " Athletics\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", + " Yankees\n", " <NA>\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", - " Athletics\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", + " Red Sox\n", " <NA>\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", - " Rockies\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", + " Cardinals\n", " <NA>\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", - " Cardinals\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", + " Rays\n", " <NA>\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", - " Cardinals\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", + " Rays\n", " <NA>\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", - " Cardinals\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", + " Royals\n", " <NA>\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", - " Pirates\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", + " Astros\n", " <NA>\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", - " Pirates\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", + " Dodgers\n", " <NA>\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", - " Giants\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", + " Tigers\n", " <NA>\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", - " Reds\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " Cardinals\n", " <NA>\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", - " Reds\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", + " Giants\n", " <NA>\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", - " Reds\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", + " Red Sox\n", " <NA>\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", - " Reds\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", + " Mets\n", " <NA>\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", - " Padres\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", + " Athletics\n", " <NA>\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", - " Nationals\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", + " Twins\n", " <NA>\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", - " Brewers\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", + " Twins\n", " <NA>\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", - " Brewers\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", + " White Sox\n", " <NA>\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", - " Brewers\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", + " Diamondbacks\n", " <NA>\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", - " Astros\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", + " Braves\n", " <NA>\n", " \n", " \n", @@ -2585,37 +2565,37 @@ ], "text/plain": [ " gameId homeTeamName awayTeamName\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf Marlins Cubs\n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 Marlins Cubs\n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 Braves \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b Braves \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd Phillies \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 Diamondbacks \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce Athletics \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d Athletics \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 Rockies \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba Cardinals \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 Cardinals \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 Cardinals \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f Pirates \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 Pirates \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 Giants \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f Reds \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 Reds \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 Reds \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 Reds \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d Padres \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 Nationals \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c Brewers \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 Brewers \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 Brewers \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 Astros \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 Nationals Brewers\n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d Reds Brewers\n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 Orioles \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 Rockies \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f Twins \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d Blue Jays \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 Yankees \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 Red Sox \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c Cardinals \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 Rays \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 Rays \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 Royals \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec Astros \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 Dodgers \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 Tigers \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 Cardinals \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 Giants \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 Red Sox \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f Mets \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd Athletics \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 Twins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 Twins \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 White Sox \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 Diamondbacks \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f Braves \n", "...\n", "\n", "[2431 rows x 3 columns]" ] }, - "execution_count": 16, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -2626,19 +2606,29 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "id": "7ee87a01-2ff5-4021-855d-44b71cf2a225", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "c83cdc3e86ff4b3694acb25b1eda845a", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 9ae1e55b-36d0-4aef-ae39-67a3ad5fdb4d is DONE. 133.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 7a1822eb-7db9-4c54-abd5-74cb1cde6121 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 60335c33-acc9-4a4a-9e08-190fe67ad60e is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2646,13 +2636,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "14f1635a78d5414b9533f31436096e6e", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 783d092c-5f79-4601-9365-633e48fac610 is DONE. 152.9 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 8c4e016f-429d-4591-8956-56fb18676334 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2687,152 +2675,152 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", - " Marlins\n", - " Cubs\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", + " Nationals\n", + " Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", - " Marlins\n", - " Cubs\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", + " Reds\n", + " Brewers\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", - " Braves\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", + " Orioles\n", " <NA>\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", - " Braves\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", + " Rockies\n", " <NA>\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", - " Phillies\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", + " Twins\n", " <NA>\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", - " Diamondbacks\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", + " Blue Jays\n", " <NA>\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", - " Athletics\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", + " Yankees\n", " <NA>\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", - " Athletics\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", + " Red Sox\n", " <NA>\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", - " Rockies\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", + " Cardinals\n", " <NA>\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", - " Cardinals\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", + " Rays\n", " <NA>\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", - " Cardinals\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", + " Rays\n", " <NA>\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", - " Cardinals\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", + " Royals\n", " <NA>\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", - " Pirates\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", + " Astros\n", " <NA>\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", - " Pirates\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", + " Dodgers\n", " <NA>\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", - " Giants\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", + " Tigers\n", " <NA>\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", - " Reds\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " Cardinals\n", " <NA>\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", - " Reds\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", + " Giants\n", " <NA>\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", - " Reds\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", + " Red Sox\n", " <NA>\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", - " Reds\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", + " Mets\n", " <NA>\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", - " Padres\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", + " Athletics\n", " <NA>\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", - " Nationals\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", + " Twins\n", " <NA>\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", - " Brewers\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", + " Twins\n", " <NA>\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", - " Brewers\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", + " White Sox\n", " <NA>\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", - " Brewers\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", + " Diamondbacks\n", " <NA>\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", - " Astros\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", + " Braves\n", " <NA>\n", " \n", " \n", @@ -2842,37 +2830,37 @@ ], "text/plain": [ " gameId homeTeamName awayTeamName\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf Marlins Cubs\n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 Marlins Cubs\n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 Braves \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b Braves \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd Phillies \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 Diamondbacks \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce Athletics \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d Athletics \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 Rockies \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba Cardinals \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 Cardinals \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 Cardinals \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f Pirates \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 Pirates \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 Giants \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f Reds \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 Reds \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 Reds \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 Reds \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d Padres \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 Nationals \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c Brewers \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 Brewers \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 Brewers \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 Astros \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 Nationals Brewers\n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d Reds Brewers\n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 Orioles \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 Rockies \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f Twins \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d Blue Jays \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 Yankees \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 Red Sox \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c Cardinals \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 Rays \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 Rays \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 Royals \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec Astros \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 Dodgers \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 Tigers \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 Cardinals \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 Giants \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 Red Sox \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f Mets \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd Athletics \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 Twins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 Twins \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 White Sox \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 Diamondbacks \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f Braves \n", "...\n", "\n", "[2431 rows x 3 columns]" ] }, - "execution_count": 17, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -2883,19 +2871,29 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "id": "330ed69c-f122-4af9-bf5e-96e309d3fa0c", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d97026197292402daa7176d5aac8c583", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job ec1c442e-6ea1-461c-ada7-e3dd0454b0ca is DONE. 133.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 4ababa83-ad57-4520-b49d-e613256ae2f3 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 948a3d0b-1c3d-479b-b54f-9a2b2062380e is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2903,13 +2901,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "9b987688bfdd49989e0dcae375a33740", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job f3db2d14-b877-46ea-8858-5cdb3706e26a is DONE. 143 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 20d2a8bb-a876-4729-a439-8c8bbf591051 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -2944,15 +2940,15 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", - " Marlins\n", - " Cubs\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", + " Nationals\n", + " Brewers\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", - " Marlins\n", - " Cubs\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", + " Reds\n", + " Brewers\n", " \n", " \n", "\n", @@ -2961,13 +2957,13 @@ ], "text/plain": [ " gameId homeTeamName awayTeamName\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf Marlins Cubs\n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 Marlins Cubs\n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 Nationals Brewers\n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d Reds Brewers\n", "\n", "[2 rows x 3 columns]" ] }, - "execution_count": 18, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -2987,19 +2983,17 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 18, "id": "5181231e-8a2a-4ac5-a379-6aa5ad4fee89", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "862fd15acf82434fb153121c74164b5f", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job f0e1bda5-34f5-46e2-a396-289340074f82 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job ea340371-7874-4590-bb5e-f747f81397de is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -3007,13 +3001,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6f9e64af012140619d1f4190b06862e6", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job e7195b4a-f1ea-4bef-a4db-fa817144d249 is DONE. 213.3 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 5c35116b-1c4a-4cc1-9ddd-172083d09490 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -3050,203 +3042,203 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", + " Nationals\n", + " Brewers\n", + " 167\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", + " Reds\n", + " Brewers\n", + " 172\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", + " Orioles\n", + " Rays\n", + " 166\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", + " Rockies\n", + " Giants\n", + " 182\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", + " Twins\n", + " Indians\n", + " 204\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", + " Yankees\n", + " Mets\n", + " 182\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", + " Red Sox\n", + " Rays\n", + " 191\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", + " Cardinals\n", + " Pirates\n", + " 201\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", + " Rays\n", + " Twins\n", + " 189\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", + " Rays\n", + " Twins\n", + " 177\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", + " Royals\n", + " Rays\n", + " 183\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", + " Astros\n", + " Rays\n", + " 194\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", + " Dodgers\n", + " Giants\n", + " 178\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", + " Tigers\n", + " White Sox\n", + " 193\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", - " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", + " 2016\n", + " Giants\n", + " Cardinals\n", + " 169\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Red Sox\n", + " Twins\n", + " 251\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", + " Mets\n", + " Braves\n", + " 151\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", + " Athletics\n", + " Twins\n", + " 153\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", + " Twins\n", + " Marlins\n", + " 185\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", + " Twins\n", + " Yankees\n", + " 180\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", + " White Sox\n", + " Orioles\n", + " 199\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", + " Braves\n", + " Mets\n", + " 201\n", " \n", " \n", "\n", @@ -3255,64 +3247,64 @@ ], "text/plain": [ " gameId year homeTeamName awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[4862 rows x 5 columns]" ] }, - "execution_count": 19, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -3332,19 +3324,29 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "id": "ad1f86f1-890b-462b-b408-b94c073371ff", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2d064a62c8424a93a0359eea715b4969", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 0745cde9-9175-4e11-9721-f0c58fae90a2 is DONE. 79.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 4c7a65d6-63b7-44b6-8249-171139f907f5 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 79bc2f65-5c7e-470d-b30e-a959838f0ed9 is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -3352,13 +3354,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "5136bbb1905d4d8d9d953d770f6dadf9", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job cee24fe1-cb33-4836-b158-90e293cbc057 is DONE. 60.5 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 9de0da3d-b43c-4381-8ecb-5b8c6d9d2c8b is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -3367,35 +3367,35 @@ { "data": { "text/plain": [ - "0 Marlins\n", - "1 Marlins\n", - "2 Braves\n", - "3 Braves\n", - "4 Phillies\n", - "5 Diamondbacks\n", - "6 Athletics\n", - "7 Athletics\n", - "8 Rockies\n", - "9 Cardinals\n", - "10 Cardinals\n", - "11 Cardinals\n", - "12 Pirates\n", - "13 Pirates\n", - "14 Giants\n", - "15 Reds\n", - "16 Reds\n", - "17 Reds\n", - "18 Reds\n", - "19 Padres\n", - "20 Nationals\n", - "21 Brewers\n", - "22 Brewers\n", - "23 Brewers\n", - "24 Astros\n", + "0 Nationals\n", + "1 Reds\n", + "2 Orioles\n", + "3 Rockies\n", + "4 Twins\n", + "5 Blue Jays\n", + "6 Yankees\n", + "7 Red Sox\n", + "8 Cardinals\n", + "9 Rays\n", + "10 Rays\n", + "11 Royals\n", + "12 Astros\n", + "13 Dodgers\n", + "14 Tigers\n", + "15 Cardinals\n", + "16 Giants\n", + "17 Red Sox\n", + "18 Mets\n", + "19 Athletics\n", + "20 Twins\n", + "21 Twins\n", + "22 White Sox\n", + "23 Diamondbacks\n", + "24 Braves\n", "Name: homeTeamName, dtype: string" ] }, - "execution_count": 20, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -3415,7 +3415,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 28, "id": "2ae4924b-37a9-4327-81d4-4f2afb66cb37", "metadata": {}, "outputs": [ @@ -3423,12 +3423,86 @@ "name": "stdout", "output_type": "stream", "text": [ - "W\n" + "WITH t0 AS (\n", + " SELECT\n", + " t9.`col_13`,\n", + " t9.`col_14`,\n", + " t9.`col_17`,\n", + " t9.`bigframes_ordering_id`\n", + " FROM `swast-scratch`._63cfa399614a54153cc386c27d6c0c6fdb249f9e.bqdf20240315_0f214503ed3e408abae057064ac2b4c2 AS t9\n", + "), t1 AS (\n", + " SELECT\n", + " t9.`col_13`,\n", + " t9.`col_14`,\n", + " t9.`col_16`,\n", + " t9.`hidden_l_0`,\n", + " t9.`hidden_r_0`\n", + " FROM `swast-scratch`._63cfa399614a54153cc386c27d6c0c6fdb249f9e.bqdf20240315_22c51834c2b94bbc93da3d0ff27f980f AS t9\n", + "), t2 AS (\n", + " SELECT\n", + " t0.`col_13`,\n", + " t0.`col_14`,\n", + " t0.`col_17`,\n", + " t0.`bigframes_ordering_id`\n", + " FROM t0\n", + "), t3 AS (\n", + " SELECT\n", + " t1.`col_13`,\n", + " t1.`col_14`,\n", + " t1.`col_16`,\n", + " t1.`hidden_l_0`,\n", + " t1.`hidden_r_0`\n", + " FROM t1\n", + "), t4 AS (\n", + " SELECT\n", + " t2.`col_13` AS `col_103`,\n", + " t2.`col_14` AS `col_104`,\n", + " t2.`col_17` AS `col_105`,\n", + " t2.`bigframes_ordering_id` AS `hidden_r_0`\n", + " FROM t2\n", + "), t5 AS (\n", + " SELECT\n", + " t3.`col_13` AS `col_100`,\n", + " t3.`col_14` AS `col_101`,\n", + " t3.`col_16` AS `col_102`,\n", + " t3.`hidden_l_0`,\n", + " t3.`hidden_r_0` AS `hidden_l_1`\n", + " FROM t3\n", + "), t6 AS (\n", + " SELECT\n", + " coalesce(`col_101`, `col_104`) AS `col_106`,\n", + " `col_102`,\n", + " `col_105`,\n", + " (\n", + " row_number() OVER (ORDER BY `hidden_l_0` IS NULL ASC, `hidden_l_0` ASC, `hidden_r_0` IS NULL ASC, `hidden_r_0` ASC) - 1\n", + " ) AS `bigframes_ordering_id`\n", + " FROM t5\n", + " INNER JOIN t4\n", + " ON coalesce(t5.`col_101`, '$NULL_SENTINEL$') = coalesce(t4.`col_104`, '$NULL_SENTINEL$')\n", + "), t7 AS (\n", + " SELECT\n", + " t6.`col_106`,\n", + " t6.`col_102`,\n", + " t6.`col_105`,\n", + " t6.`bigframes_ordering_id`\n", + " FROM t6\n", + ")\n", + "SELECT\n", + " t8.`col_106` AS `gameId`,\n", + " t8.`col_102` AS `homeTeamName`,\n", + " t8.`col_105` AS `awayTeamName`\n", + "FROM (\n", + " SELECT\n", + " t7.`col_106`,\n", + " t7.`col_102`,\n", + " t7.`col_105`\n", + " FROM t7\n", + ") AS t8\n" ] } ], "source": [ - "print(df1.merge(df2, on=\"gameId\", how=\"inner\").sql[0])" + "print(df1.merge(df2, on=\"gameId\", how=\"inner\").sql)" ] }, { @@ -3442,19 +3516,17 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 21, "id": "5adc7bbf-2c58-4924-964c-ed1b18dc9268", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "3823a6fb05e84f8986962d044559accb", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 9fcba646-219f-40ee-9792-d74af0ff7e22 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 15cdbf31-e68a-41f0-9c5b-ea4ce49345f0 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -3462,13 +3534,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6e3bbb5866d244cda7418890ca99766a", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 657cdf62-f71e-482c-97f7-b66e4ac20e10 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 1e56a960-3fcd-421a-8500-bc1c099ae7a1 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -3505,203 +3575,203 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", + " Nationals\n", + " Brewers\n", + " 167\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", + " Reds\n", + " Brewers\n", + " 172\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", + " Orioles\n", + " Rays\n", + " 166\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", + " Rockies\n", + " Giants\n", + " 182\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", + " Twins\n", + " Indians\n", + " 204\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", + " Yankees\n", + " Mets\n", + " 182\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", + " Red Sox\n", + " Rays\n", + " 191\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", + " Cardinals\n", + " Pirates\n", + " 201\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", + " Rays\n", + " Twins\n", + " 189\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", + " Rays\n", + " Twins\n", + " 177\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", + " Royals\n", + " Rays\n", + " 183\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", + " Astros\n", + " Rays\n", + " 194\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", + " Dodgers\n", + " Giants\n", + " 178\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", + " Tigers\n", + " White Sox\n", + " 193\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Giants\n", + " Cardinals\n", + " 169\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Red Sox\n", + " Twins\n", + " 251\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", + " Mets\n", + " Braves\n", + " 151\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", + " Athletics\n", + " Twins\n", + " 153\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", + " Twins\n", + " Marlins\n", + " 185\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", + " Twins\n", + " Yankees\n", + " 180\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", + " White Sox\n", + " Orioles\n", + " 199\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", + " Braves\n", + " Mets\n", + " 201\n", " \n", " \n", "\n", @@ -3710,64 +3780,64 @@ ], "text/plain": [ " gameId year HOME TEAM awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[2431 rows x 5 columns]" ] }, - "execution_count": 22, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -3778,19 +3848,17 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 22, "id": "ac3ceabe-4317-453c-9418-826de5094454", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0c8aa06c869446f09a41c5dff15dc682", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job c90e0cd4-30e5-427c-8f5f-a0a8c778bc62 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job f21ef830-99b1-4fce-ab9a-378e12a04587 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -3798,13 +3866,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "2c03c2a860c847b5a27d1c3f2188e323", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 23bfdb6d-9411-484c-9766-93f76dfc1adc is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 88f63cc1-9691-4e6c-8acf-650f31ab8560 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -3841,203 +3907,203 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", + " Nationals\n", + " Brewers\n", + " 167\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", + " Reds\n", + " Brewers\n", + " 172\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", + " Orioles\n", + " Rays\n", + " 166\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", + " Rockies\n", + " Giants\n", + " 182\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", + " Twins\n", + " Indians\n", + " 204\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", + " Yankees\n", + " Mets\n", + " 182\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", + " Red Sox\n", + " Rays\n", + " 191\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", + " Cardinals\n", + " Pirates\n", + " 201\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", + " Rays\n", + " Twins\n", + " 189\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", + " Rays\n", + " Twins\n", + " 177\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", + " Royals\n", + " Rays\n", + " 183\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", + " Astros\n", + " Rays\n", + " 194\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", + " Dodgers\n", + " Giants\n", + " 178\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", + " Tigers\n", + " White Sox\n", + " 193\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Giants\n", + " Cardinals\n", + " 169\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Red Sox\n", + " Twins\n", + " 251\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", + " Mets\n", + " Braves\n", + " 151\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", + " Athletics\n", + " Twins\n", + " 153\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", + " Twins\n", + " Marlins\n", + " 185\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", + " Twins\n", + " Yankees\n", + " 180\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", + " White Sox\n", + " Orioles\n", + " 199\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", + " Braves\n", + " Mets\n", + " 201\n", " \n", " \n", "\n", @@ -4046,64 +4112,64 @@ ], "text/plain": [ " gameId year homeTeam!@#$%col awayTeamName \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[2431 rows x 5 columns]" ] }, - "execution_count": 23, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -4114,19 +4180,17 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 23, "id": "e73704c9-7aa9-4f10-b414-3417c3ad9eb8", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "4eba676d1e7b4ead892828e33baa8534", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 63c2d27f-382c-4a43-8fc1-135d9fd66a54 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 6f6e1d12-4202-434a-908a-3d0b34e70656 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -4134,13 +4198,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6c1c07d67cc74b768664575511eb2a7f", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job cc64185b-98e7-40d8-bf8e-2a3ea355ef67 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 05ec231e-a7f0-4e41-ad60-5d8136a2e148 is DONE. 0 Bytes processed. " ] }, "metadata": {}, @@ -4177,203 +4239,203 @@ " \n", " \n", " 0\n", - " e14b6493-9e7f-404f-840a-8a680cc364bf\n", + " d60c6036-0ce1-4c90-8dd9-de3b403c92a8\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 187\n", + " Nationals\n", + " Brewers\n", + " 167\n", " \n", " \n", " 1\n", - " 1f32b347-cbcb-4c31-a145-0e685306d168\n", + " af72a0b9-65f7-49fb-9b30-d505068bdf6d\n", " 2016\n", - " Marlins\n", - " Cubs\n", - " 189\n", + " Reds\n", + " Brewers\n", + " 172\n", " \n", " \n", " 2\n", - " 0c2292d1-7398-48be-bf8e-b41dad5e1a43\n", + " f57e1271-d217-400a-aea6-2e2d7d6a59a0\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 165\n", + " Orioles\n", + " Rays\n", + " 166\n", " \n", " \n", " 3\n", - " 8fbec734-a15a-42ab-8d51-60790de7750b\n", + " 198f4eed-a29f-41e2-8623-cb261e5ab370\n", " 2016\n", - " Braves\n", - " Cubs\n", - " 222\n", + " Rockies\n", + " Giants\n", + " 182\n", " \n", " \n", " 4\n", - " 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd\n", + " cb3ef033-dd57-41fd-b206-cdd3bc12c74f\n", " 2016\n", - " Phillies\n", - " Cubs\n", - " 164\n", + " Twins\n", + " Indians\n", + " 204\n", " \n", " \n", " 5\n", - " 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52\n", + " 4be9f735-a98e-4689-87ce-852cc3a1e79d\n", " 2016\n", - " Diamondbacks\n", - " Cubs\n", - " 201\n", + " Blue Jays\n", + " Orioles\n", + " 184\n", " \n", " \n", " 6\n", - " 76ea8662-c7e6-4c38-8f2a-efe373e428ce\n", + " 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 173\n", + " Yankees\n", + " Mets\n", + " 182\n", " \n", " \n", " 7\n", - " 66fad23d-6e89-4f99-be29-d49b6e94f95d\n", + " 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2\n", " 2016\n", - " Athletics\n", - " Cubs\n", - " 176\n", + " Red Sox\n", + " Rays\n", + " 191\n", " \n", " \n", " 8\n", - " d977367c-cf0c-4687-95a0-eb4542efcb01\n", + " 7e1c2095-4fea-454c-8773-096ceb6fb05c\n", " 2016\n", - " Rockies\n", - " Cubs\n", - " 180\n", + " Cardinals\n", + " Pirates\n", + " 201\n", " \n", " \n", " 9\n", - " a87070ff-1084-43ca-a7ba-69278f93ecba\n", + " f7f24ce3-7f9d-4e8a-986e-095db847c4c1\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 157\n", + " Rays\n", + " Twins\n", + " 189\n", " \n", " \n", " 10\n", - " ea6b350d-3c1d-4737-878d-4465f66999f6\n", + " 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 218\n", + " Rays\n", + " Twins\n", + " 177\n", " \n", " \n", " 11\n", - " 46463c50-0f5c-4dca-a661-dd194464e791\n", + " 6d2cab13-dd85-477a-8769-669069f85836\n", " 2016\n", - " Cardinals\n", - " Cubs\n", - " 160\n", + " Royals\n", + " Rays\n", + " 183\n", " \n", " \n", " 12\n", - " 59134e6d-9d13-49aa-978e-c3c2300eb90f\n", + " bca90342-7ddc-468e-b189-d43fad7528ec\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 178\n", + " Astros\n", + " Rays\n", + " 194\n", " \n", " \n", " 13\n", - " 387630a3-a894-4327-baa1-b24ec1a654d9\n", + " 630f4f78-03cc-43c1-9e57-ababb9c11418\n", " 2016\n", - " Pirates\n", - " Cubs\n", - " 205\n", + " Dodgers\n", + " Giants\n", + " 178\n", " \n", " \n", " 14\n", - " 5d084e13-94fd-4995-b95a-4801ea3ed556\n", + " c0cf1376-1115-4a2f-b457-3f82bbc41a89\n", " 2016\n", - " Giants\n", - " Cubs\n", - " 197\n", + " Tigers\n", + " White Sox\n", + " 193\n", " \n", " \n", " 15\n", - " 34444c94-03ec-4d12-96af-68b8f399a22f\n", + " 46463c50-0f5c-4dca-a661-dd194464e791\n", " 2016\n", - " Reds\n", + " Cardinals\n", " Cubs\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", - " 9580bffe-22e1-4975-978b-1b13e7505193\n", + " 392ad56d-972e-4f77-98e2-5f8577931cf8\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Giants\n", + " Cardinals\n", + " 169\n", " \n", " \n", " 17\n", - " 645e6a08-afd6-4677-a5c9-01ef446b0cf3\n", + " 307730fa-bbed-4221-b4e6-a2492f546fd5\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 188\n", + " Red Sox\n", + " Twins\n", + " 251\n", " \n", " \n", " 18\n", - " 08981bd8-d1d7-48e1-8668-9098b8f7fe90\n", + " 1cbc558f-7615-4fa9-bf97-7ccd62040d6f\n", " 2016\n", - " Reds\n", - " Cubs\n", - " 194\n", + " Mets\n", + " Braves\n", + " 151\n", " \n", " \n", " 19\n", - " 303703bb-b55f-476d-8faf-bf582169fb1d\n", + " 723348ba-1645-43fc-9e22-92994f7a63bd\n", " 2016\n", - " Padres\n", - " Cubs\n", - " 175\n", + " Athletics\n", + " Twins\n", + " 153\n", " \n", " \n", " 20\n", - " 71ab82a4-6e07-430a-b695-1af3bc42ea61\n", + " ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992\n", " 2016\n", - " Nationals\n", - " Cubs\n", - " 257\n", + " Twins\n", + " Marlins\n", + " 185\n", " \n", " \n", " 21\n", - " d1a110c2-f6c8-4029-bcd8-2f8a01e1561c\n", + " f2747230-7df5-4535-a475-a1c823d0d654\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 178\n", + " Twins\n", + " Yankees\n", + " 180\n", " \n", " \n", " 22\n", - " 6d111b57-fa0b-4f24-82df-ff33a26f0252\n", + " db3b6f35-a7a4-430a-8703-2b2f25103e17\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 171\n", + " White Sox\n", + " Orioles\n", + " 199\n", " \n", " \n", " 23\n", - " a97e9539-bbbd-4e03-bf15-f25ea2c1d923\n", + " 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636\n", " 2016\n", - " Brewers\n", - " Cubs\n", - " 248\n", + " Diamondbacks\n", + " Giants\n", + " 175\n", " \n", " \n", " 24\n", - " dc0c9218-505c-4725-8c0c-40b72cca0956\n", + " 95d548b6-2da8-4644-812e-b277fec5b91f\n", " 2016\n", - " Astros\n", - " Cubs\n", - " 174\n", + " Braves\n", + " Mets\n", + " 201\n", " \n", " \n", "\n", @@ -4381,65 +4443,65 @@ "[2431 rows x 5 columns in total]" ], "text/plain": [ - " gameId year team team \\\n", - "0 e14b6493-9e7f-404f-840a-8a680cc364bf 2016 Marlins Cubs \n", - "1 1f32b347-cbcb-4c31-a145-0e685306d168 2016 Marlins Cubs \n", - "2 0c2292d1-7398-48be-bf8e-b41dad5e1a43 2016 Braves Cubs \n", - "3 8fbec734-a15a-42ab-8d51-60790de7750b 2016 Braves Cubs \n", - "4 89e514d5-fbf5-4b9d-bdac-6ca45bfd18dd 2016 Phillies Cubs \n", - "5 6a83e76c-dc0d-4924-9d3d-a2e7e0ab5b52 2016 Diamondbacks Cubs \n", - "6 76ea8662-c7e6-4c38-8f2a-efe373e428ce 2016 Athletics Cubs \n", - "7 66fad23d-6e89-4f99-be29-d49b6e94f95d 2016 Athletics Cubs \n", - "8 d977367c-cf0c-4687-95a0-eb4542efcb01 2016 Rockies Cubs \n", - "9 a87070ff-1084-43ca-a7ba-69278f93ecba 2016 Cardinals Cubs \n", - "10 ea6b350d-3c1d-4737-878d-4465f66999f6 2016 Cardinals Cubs \n", - "11 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", - "12 59134e6d-9d13-49aa-978e-c3c2300eb90f 2016 Pirates Cubs \n", - "13 387630a3-a894-4327-baa1-b24ec1a654d9 2016 Pirates Cubs \n", - "14 5d084e13-94fd-4995-b95a-4801ea3ed556 2016 Giants Cubs \n", - "15 34444c94-03ec-4d12-96af-68b8f399a22f 2016 Reds Cubs \n", - "16 9580bffe-22e1-4975-978b-1b13e7505193 2016 Reds Cubs \n", - "17 645e6a08-afd6-4677-a5c9-01ef446b0cf3 2016 Reds Cubs \n", - "18 08981bd8-d1d7-48e1-8668-9098b8f7fe90 2016 Reds Cubs \n", - "19 303703bb-b55f-476d-8faf-bf582169fb1d 2016 Padres Cubs \n", - "20 71ab82a4-6e07-430a-b695-1af3bc42ea61 2016 Nationals Cubs \n", - "21 d1a110c2-f6c8-4029-bcd8-2f8a01e1561c 2016 Brewers Cubs \n", - "22 6d111b57-fa0b-4f24-82df-ff33a26f0252 2016 Brewers Cubs \n", - "23 a97e9539-bbbd-4e03-bf15-f25ea2c1d923 2016 Brewers Cubs \n", - "24 dc0c9218-505c-4725-8c0c-40b72cca0956 2016 Astros Cubs \n", + " gameId year team team \\\n", + "0 d60c6036-0ce1-4c90-8dd9-de3b403c92a8 2016 Nationals Brewers \n", + "1 af72a0b9-65f7-49fb-9b30-d505068bdf6d 2016 Reds Brewers \n", + "2 f57e1271-d217-400a-aea6-2e2d7d6a59a0 2016 Orioles Rays \n", + "3 198f4eed-a29f-41e2-8623-cb261e5ab370 2016 Rockies Giants \n", + "4 cb3ef033-dd57-41fd-b206-cdd3bc12c74f 2016 Twins Indians \n", + "5 4be9f735-a98e-4689-87ce-852cc3a1e79d 2016 Blue Jays Orioles \n", + "6 0b2de8c3-11d9-4f0f-a186-25b59f34a5d8 2016 Yankees Mets \n", + "7 60d80663-6ced-44aa-aad9-0f4bf8d3b4d2 2016 Red Sox Rays \n", + "8 7e1c2095-4fea-454c-8773-096ceb6fb05c 2016 Cardinals Pirates \n", + "9 f7f24ce3-7f9d-4e8a-986e-095db847c4c1 2016 Rays Twins \n", + "10 5c26e7fc-c99f-48b4-92c1-4a7208c8cfe9 2016 Rays Twins \n", + "11 6d2cab13-dd85-477a-8769-669069f85836 2016 Royals Rays \n", + "12 bca90342-7ddc-468e-b189-d43fad7528ec 2016 Astros Rays \n", + "13 630f4f78-03cc-43c1-9e57-ababb9c11418 2016 Dodgers Giants \n", + "14 c0cf1376-1115-4a2f-b457-3f82bbc41a89 2016 Tigers White Sox \n", + "15 46463c50-0f5c-4dca-a661-dd194464e791 2016 Cardinals Cubs \n", + "16 392ad56d-972e-4f77-98e2-5f8577931cf8 2016 Giants Cardinals \n", + "17 307730fa-bbed-4221-b4e6-a2492f546fd5 2016 Red Sox Twins \n", + "18 1cbc558f-7615-4fa9-bf97-7ccd62040d6f 2016 Mets Braves \n", + "19 723348ba-1645-43fc-9e22-92994f7a63bd 2016 Athletics Twins \n", + "20 ffbd6ecc-82e1-4e5d-9bd1-4ea210be5992 2016 Twins Marlins \n", + "21 f2747230-7df5-4535-a475-a1c823d0d654 2016 Twins Yankees \n", + "22 db3b6f35-a7a4-430a-8703-2b2f25103e17 2016 White Sox Orioles \n", + "23 5fc8c6f0-a70e-4d1b-877f-eb1ec8e6f636 2016 Diamondbacks Giants \n", + "24 95d548b6-2da8-4644-812e-b277fec5b91f 2016 Braves Mets \n", "\n", " duration_minutes \n", - "0 187 \n", - "1 189 \n", - "2 165 \n", - "3 222 \n", - "4 164 \n", - "5 201 \n", - "6 173 \n", - "7 176 \n", - "8 180 \n", - "9 157 \n", - "10 218 \n", - "11 160 \n", - "12 178 \n", - "13 205 \n", - "14 197 \n", - "15 198 \n", - "16 188 \n", - "17 188 \n", - "18 194 \n", - "19 175 \n", - "20 257 \n", - "21 178 \n", - "22 171 \n", - "23 248 \n", - "24 174 \n", + "0 167 \n", + "1 172 \n", + "2 166 \n", + "3 182 \n", + "4 204 \n", + "5 184 \n", + "6 182 \n", + "7 191 \n", + "8 201 \n", + "9 189 \n", + "10 177 \n", + "11 183 \n", + "12 194 \n", + "13 178 \n", + "14 193 \n", + "15 160 \n", + "16 169 \n", + "17 251 \n", + "18 151 \n", + "19 153 \n", + "20 185 \n", + "21 180 \n", + "22 199 \n", + "23 175 \n", + "24 201 \n", "...\n", "\n", "[2431 rows x 5 columns]" ] }, - "execution_count": 24, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -4451,19 +4513,17 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 24, "id": "1a80f6f8-a172-4d7d-a2f5-e10871da7224", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "62abc80873ca4f96843de16b70ff0724", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 089a657b-e651-4b17-a4ce-4d7be682a49c is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job f4b90f3c-381e-470d-8416-54f31f1fbb3a is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -4471,13 +4531,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0a92c634fa774082a476c56ac0097adc", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job 740ad61e-cf14-41f1-ae4e-23d1fb8ed155 is DONE. 82.0 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 5cd5e48d-8b02-4500-94cd-cbd2ee91957e is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -4511,128 +4569,128 @@ " \n", " \n", " 0\n", - " Marlins\n", - " Cubs\n", + " Nationals\n", + " Brewers\n", " \n", " \n", " 1\n", - " Marlins\n", - " Cubs\n", + " Reds\n", + " Brewers\n", " \n", " \n", " 2\n", - " Braves\n", - " Cubs\n", + " Orioles\n", + " Rays\n", " \n", " \n", " 3\n", - " Braves\n", - " Cubs\n", + " Rockies\n", + " Giants\n", " \n", " \n", " 4\n", - " Phillies\n", - " Cubs\n", + " Twins\n", + " Indians\n", " \n", " \n", " 5\n", - " Diamondbacks\n", - " Cubs\n", + " Blue Jays\n", + " Orioles\n", " \n", " \n", " 6\n", - " Athletics\n", - " Cubs\n", + " Yankees\n", + " Mets\n", " \n", " \n", " 7\n", - " Athletics\n", - " Cubs\n", + " Red Sox\n", + " Rays\n", " \n", " \n", " 8\n", - " Rockies\n", - " Cubs\n", + " Cardinals\n", + " Pirates\n", " \n", " \n", " 9\n", - " Cardinals\n", - " Cubs\n", + " Rays\n", + " Twins\n", " \n", " \n", " 10\n", - " Cardinals\n", - " Cubs\n", + " Rays\n", + " Twins\n", " \n", " \n", " 11\n", - " Cardinals\n", - " Cubs\n", + " Royals\n", + " Rays\n", " \n", " \n", " 12\n", - " Pirates\n", - " Cubs\n", + " Astros\n", + " Rays\n", " \n", " \n", " 13\n", - " Pirates\n", - " Cubs\n", + " Dodgers\n", + " Giants\n", " \n", " \n", " 14\n", - " Giants\n", - " Cubs\n", + " Tigers\n", + " White Sox\n", " \n", " \n", " 15\n", - " Reds\n", + " Cardinals\n", " Cubs\n", " \n", " \n", " 16\n", - " Reds\n", - " Cubs\n", + " Giants\n", + " Cardinals\n", " \n", " \n", " 17\n", - " Reds\n", - " Cubs\n", + " Red Sox\n", + " Twins\n", " \n", " \n", " 18\n", - " Reds\n", - " Cubs\n", + " Mets\n", + " Braves\n", " \n", " \n", " 19\n", - " Padres\n", - " Cubs\n", + " Athletics\n", + " Twins\n", " \n", " \n", " 20\n", - " Nationals\n", - " Cubs\n", + " Twins\n", + " Marlins\n", " \n", " \n", " 21\n", - " Brewers\n", - " Cubs\n", + " Twins\n", + " Yankees\n", " \n", " \n", " 22\n", - " Brewers\n", - " Cubs\n", + " White Sox\n", + " Orioles\n", " \n", " \n", " 23\n", - " Brewers\n", - " Cubs\n", + " Diamondbacks\n", + " Giants\n", " \n", " \n", " 24\n", - " Astros\n", - " Cubs\n", + " Braves\n", + " Mets\n", " \n", " \n", "\n", @@ -4640,38 +4698,38 @@ "[2431 rows x 2 columns in total]" ], "text/plain": [ - " team team\n", - "0 Marlins Cubs\n", - "1 Marlins Cubs\n", - "2 Braves Cubs\n", - "3 Braves Cubs\n", - "4 Phillies Cubs\n", - "5 Diamondbacks Cubs\n", - "6 Athletics Cubs\n", - "7 Athletics Cubs\n", - "8 Rockies Cubs\n", - "9 Cardinals Cubs\n", - "10 Cardinals Cubs\n", - "11 Cardinals Cubs\n", - "12 Pirates Cubs\n", - "13 Pirates Cubs\n", - "14 Giants Cubs\n", - "15 Reds Cubs\n", - "16 Reds Cubs\n", - "17 Reds Cubs\n", - "18 Reds Cubs\n", - "19 Padres Cubs\n", - "20 Nationals Cubs\n", - "21 Brewers Cubs\n", - "22 Brewers Cubs\n", - "23 Brewers Cubs\n", - "24 Astros Cubs\n", + " team team\n", + "0 Nationals Brewers\n", + "1 Reds Brewers\n", + "2 Orioles Rays\n", + "3 Rockies Giants\n", + "4 Twins Indians\n", + "5 Blue Jays Orioles\n", + "6 Yankees Mets\n", + "7 Red Sox Rays\n", + "8 Cardinals Pirates\n", + "9 Rays Twins\n", + "10 Rays Twins\n", + "11 Royals Rays\n", + "12 Astros Rays\n", + "13 Dodgers Giants\n", + "14 Tigers White Sox\n", + "15 Cardinals Cubs\n", + "16 Giants Cardinals\n", + "17 Red Sox Twins\n", + "18 Mets Braves\n", + "19 Athletics Twins\n", + "20 Twins Marlins\n", + "21 Twins Yankees\n", + "22 White Sox Orioles\n", + "23 Diamondbacks Giants\n", + "24 Braves Mets\n", "...\n", "\n", "[2431 rows x 2 columns]" ] }, - "execution_count": 25, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -4691,19 +4749,17 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 25, "id": "2414a095-37df-4755-b86c-2031a6cb9d4a", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "27bab406ba024805b35effa7e01def3d", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job d3b3cd83-d9cf-4c5b-9015-e3979e0857f3 is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 6b1cf632-7764-49ba-bd5d-cdf31c47e430 is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -4711,13 +4767,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "fb3f85b83da34242963b478328db9662", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job e4d99a58-738d-42af-863e-d1262a32c93c is DONE. 77.8 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job baa31010-2426-4ea5-9527-8f55473a3f41 is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -4752,127 +4806,127 @@ " \n", " 0\n", " 2016\n", - " 187\n", + " 167\n", " \n", " \n", " 1\n", " 2016\n", - " 189\n", + " 172\n", " \n", " \n", " 2\n", " 2016\n", - " 165\n", + " 166\n", " \n", " \n", " 3\n", " 2016\n", - " 222\n", + " 182\n", " \n", " \n", " 4\n", " 2016\n", - " 164\n", + " 204\n", " \n", " \n", " 5\n", " 2016\n", - " 201\n", + " 184\n", " \n", " \n", " 6\n", " 2016\n", - " 173\n", + " 182\n", " \n", " \n", " 7\n", " 2016\n", - " 176\n", + " 191\n", " \n", " \n", " 8\n", " 2016\n", - " 180\n", + " 201\n", " \n", " \n", " 9\n", " 2016\n", - " 157\n", + " 189\n", " \n", " \n", " 10\n", " 2016\n", - " 218\n", + " 177\n", " \n", " \n", " 11\n", " 2016\n", - " 160\n", + " 183\n", " \n", " \n", " 12\n", " 2016\n", - " 178\n", + " 194\n", " \n", " \n", " 13\n", " 2016\n", - " 205\n", + " 178\n", " \n", " \n", " 14\n", " 2016\n", - " 197\n", + " 193\n", " \n", " \n", " 15\n", " 2016\n", - " 198\n", + " 160\n", " \n", " \n", " 16\n", " 2016\n", - " 188\n", + " 169\n", " \n", " \n", " 17\n", " 2016\n", - " 188\n", + " 251\n", " \n", " \n", " 18\n", " 2016\n", - " 194\n", + " 151\n", " \n", " \n", " 19\n", " 2016\n", - " 175\n", + " 153\n", " \n", " \n", " 20\n", " 2016\n", - " 257\n", + " 185\n", " \n", " \n", " 21\n", " 2016\n", - " 178\n", + " 180\n", " \n", " \n", " 22\n", " 2016\n", - " 171\n", + " 199\n", " \n", " \n", " 23\n", " 2016\n", - " 248\n", + " 175\n", " \n", " \n", " 24\n", " 2016\n", - " 174\n", + " 201\n", " \n", " \n", "\n", @@ -4881,37 +4935,37 @@ ], "text/plain": [ " year duration_minutes\n", - "0 2016 187\n", - "1 2016 189\n", - "2 2016 165\n", - "3 2016 222\n", - "4 2016 164\n", - "5 2016 201\n", - "6 2016 173\n", - "7 2016 176\n", - "8 2016 180\n", - "9 2016 157\n", - "10 2016 218\n", - "11 2016 160\n", - "12 2016 178\n", - "13 2016 205\n", - "14 2016 197\n", - "15 2016 198\n", - "16 2016 188\n", - "17 2016 188\n", - "18 2016 194\n", - "19 2016 175\n", - "20 2016 257\n", - "21 2016 178\n", - "22 2016 171\n", - "23 2016 248\n", - "24 2016 174\n", + "0 2016 167\n", + "1 2016 172\n", + "2 2016 166\n", + "3 2016 182\n", + "4 2016 204\n", + "5 2016 184\n", + "6 2016 182\n", + "7 2016 191\n", + "8 2016 201\n", + "9 2016 189\n", + "10 2016 177\n", + "11 2016 183\n", + "12 2016 194\n", + "13 2016 178\n", + "14 2016 193\n", + "15 2016 160\n", + "16 2016 169\n", + "17 2016 251\n", + "18 2016 151\n", + "19 2016 153\n", + "20 2016 185\n", + "21 2016 180\n", + "22 2016 199\n", + "23 2016 175\n", + "24 2016 201\n", "...\n", "\n", "[2431 rows x 2 columns]" ] }, - "execution_count": 26, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -4923,19 +4977,17 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 26, "id": "7d437c7c-ae74-4f0d-a4f8-10a133f4b61e", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "0836e9729f75465e8eb1e73c1071a22d", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job e5c2b908-c539-4349-8368-50e61d8e19cd is DONE. 0 Bytes processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 62ffb914-e1fb-4b12-adb5-09b431e06acf is DONE. 174.4 kB processed. " ] }, "metadata": {}, @@ -4943,13 +4995,11 @@ }, { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "69e853a1f0e44d39adacfefbfee86156", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job c5a563d2-9780-4c51-996b-bf0242b96e39 is DONE. 77.8 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job 2eaceff3-b00c-42d0-883f-fbe85a70f49b is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -4984,127 +5034,127 @@ " \n", " 0\n", " 2017\n", - " 188\n", + " 168\n", " \n", " \n", " 1\n", " 2017\n", - " 190\n", + " 173\n", " \n", " \n", " 2\n", " 2017\n", - " 166\n", + " 167\n", " \n", " \n", " 3\n", " 2017\n", - " 223\n", + " 183\n", " \n", " \n", " 4\n", " 2017\n", - " 165\n", + " 205\n", " \n", " \n", " 5\n", " 2017\n", - " 202\n", + " 185\n", " \n", " \n", " 6\n", " 2017\n", - " 174\n", + " 183\n", " \n", " \n", " 7\n", " 2017\n", - " 177\n", + " 192\n", " \n", " \n", " 8\n", " 2017\n", - " 181\n", + " 202\n", " \n", " \n", " 9\n", " 2017\n", - " 158\n", + " 190\n", " \n", " \n", " 10\n", " 2017\n", - " 219\n", + " 178\n", " \n", " \n", " 11\n", " 2017\n", - " 161\n", + " 184\n", " \n", " \n", " 12\n", " 2017\n", - " 179\n", + " 195\n", " \n", " \n", " 13\n", " 2017\n", - " 206\n", + " 179\n", " \n", " \n", " 14\n", " 2017\n", - " 198\n", + " 194\n", " \n", " \n", " 15\n", " 2017\n", - " 199\n", + " 161\n", " \n", " \n", " 16\n", " 2017\n", - " 189\n", + " 170\n", " \n", " \n", " 17\n", " 2017\n", - " 189\n", + " 252\n", " \n", " \n", " 18\n", " 2017\n", - " 195\n", + " 152\n", " \n", " \n", " 19\n", " 2017\n", - " 176\n", + " 154\n", " \n", " \n", " 20\n", " 2017\n", - " 258\n", + " 186\n", " \n", " \n", " 21\n", " 2017\n", - " 179\n", + " 181\n", " \n", " \n", " 22\n", " 2017\n", - " 172\n", + " 200\n", " \n", " \n", " 23\n", " 2017\n", - " 249\n", + " 176\n", " \n", " \n", " 24\n", " 2017\n", - " 175\n", + " 202\n", " \n", " \n", "\n", @@ -5113,37 +5163,37 @@ ], "text/plain": [ " year duration_minutes\n", - "0 2017 188\n", - "1 2017 190\n", - "2 2017 166\n", - "3 2017 223\n", - "4 2017 165\n", - "5 2017 202\n", - "6 2017 174\n", - "7 2017 177\n", - "8 2017 181\n", - "9 2017 158\n", - "10 2017 219\n", - "11 2017 161\n", - "12 2017 179\n", - "13 2017 206\n", - "14 2017 198\n", - "15 2017 199\n", - "16 2017 189\n", - "17 2017 189\n", - "18 2017 195\n", - "19 2017 176\n", - "20 2017 258\n", - "21 2017 179\n", - "22 2017 172\n", - "23 2017 249\n", - "24 2017 175\n", + "0 2017 168\n", + "1 2017 173\n", + "2 2017 167\n", + "3 2017 183\n", + "4 2017 205\n", + "5 2017 185\n", + "6 2017 183\n", + "7 2017 192\n", + "8 2017 202\n", + "9 2017 190\n", + "10 2017 178\n", + "11 2017 184\n", + "12 2017 195\n", + "13 2017 179\n", + "14 2017 194\n", + "15 2017 161\n", + "16 2017 170\n", + "17 2017 252\n", + "18 2017 152\n", + "19 2017 154\n", + "20 2017 186\n", + "21 2017 181\n", + "22 2017 200\n", + "23 2017 176\n", + "24 2017 202\n", "...\n", "\n", "[2431 rows x 2 columns]" ] }, - "execution_count": 27, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -5162,19 +5212,17 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 27, "id": "ab429fa5", "metadata": {}, "outputs": [ { "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "39eda5e2b7984f8f90a441c31b62a675", - "version_major": 2, - "version_minor": 0 - }, + "text/html": [ + "Query job b6495f3d-619c-429e-8904-5cdc4957d09f is DONE. 77.8 kB processed. Open Job" + ], "text/plain": [ - "HTML(value='Query job f3b7ff8a-ffdc-4f4c-91d3-6c2c702c373d is DONE. 193.8 kB processed. " ] }, "metadata": {}, @@ -5209,27 +5257,27 @@ " \n", " 0\n", " 2016\n", - " 187\n", + " 167\n", " \n", " \n", " 1\n", " 2016\n", - " 189\n", + " 172\n", " \n", " \n", " 2\n", " 2016\n", - " 165\n", + " 166\n", " \n", " \n", " 3\n", " 2016\n", - " 222\n", + " 182\n", " \n", " \n", " 4\n", " 2016\n", - " 164\n", + " 204\n", " \n", " \n", " ...\n", @@ -5239,27 +5287,27 @@ " \n", " 2426\n", " 2016\n", - " 156\n", + " 199\n", " \n", " \n", " 2427\n", " 2016\n", - " 185\n", + " 181\n", " \n", " \n", " 2428\n", " 2016\n", - " 243\n", + " 205\n", " \n", " \n", " 2429\n", " 2016\n", - " 184\n", + " 203\n", " \n", " \n", " 2430\n", " 2016\n", - " 185\n", + " 182\n", " \n", " \n", "\n", @@ -5268,22 +5316,22 @@ ], "text/plain": [ " year duration_minutes\n", - "0 2016 187\n", - "1 2016 189\n", - "2 2016 165\n", - "3 2016 222\n", - "4 2016 164\n", + "0 2016 167\n", + "1 2016 172\n", + "2 2016 166\n", + "3 2016 182\n", + "4 2016 204\n", "... ... ...\n", - "2426 2016 156\n", - "2427 2016 185\n", - "2428 2016 243\n", - "2429 2016 184\n", - "2430 2016 185\n", + "2426 2016 199\n", + "2427 2016 181\n", + "2428 2016 205\n", + "2429 2016 203\n", + "2430 2016 182\n", "\n", "[2431 rows x 2 columns]" ] }, - "execution_count": 28, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -5310,7 +5358,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.11.1" } }, "nbformat": 4, diff --git a/notebooks/generative_ai/bq_dataframes_llm_code_generation.ipynb b/notebooks/generative_ai/bq_dataframes_llm_code_generation.ipynb index 74a0d7b206..4ea766604d 100644 --- a/notebooks/generative_ai/bq_dataframes_llm_code_generation.ipynb +++ b/notebooks/generative_ai/bq_dataframes_llm_code_generation.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": { "id": "ur8xi4C7S06n" }, @@ -140,7 +140,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": { "id": "2b4ef9b72d43" }, @@ -204,7 +204,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 27, "metadata": { "id": "oM1iC_MfAts1" }, @@ -242,7 +242,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": { "id": "eF-Twtc4XGem" }, @@ -286,7 +286,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": { "id": "254614fa0c46" }, @@ -308,7 +308,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": { "id": "603adbbf0532" }, @@ -329,7 +329,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": { "id": "PyQmSRbKA8r-" }, @@ -351,13 +351,20 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": { "id": "NPPMuw2PXGeo" }, "outputs": [], "source": [ + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", "bf.options.bigquery.project = PROJECT_ID\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", "bf.options.bigquery.location = REGION" ] }, @@ -396,7 +403,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": { "id": "sdjeXFwcHfl7" }, @@ -404,7 +411,7 @@ { "data": { "text/html": [ - "Query job a3897125-4272-4817-a0e6-8e1a9e022b93 is DONE. 0 Bytes processed. Open Job" + "Query job 0ee1a08e-788e-4fc7-b061-52c23ab25d5a is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -440,7 +447,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": { "id": "SchiTkQGIJog" }, @@ -461,7 +468,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "metadata": { "id": "QCqgVCIsGGuv" }, @@ -469,7 +476,7 @@ { "data": { "text/html": [ - "Query job e186a7bf-813c-4c46-80c8-ae079c829841 is DONE. 0 Bytes processed. Open Job" + "Query job 48be241c-ee93-4dfa-a9e3-66b64c4b5150 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -481,7 +488,7 @@ { "data": { "text/html": [ - "Query job 868ef0e0-ef33-4f0c-8b47-401a82bfc288 is DONE. 0 Bytes processed. Open Job" + "Query job 6af9caa5-4f7a-48f0-a7df-d692ee063b7e is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -536,7 +543,7 @@ "[2 rows x 1 columns]" ] }, - "execution_count": 11, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -547,7 +554,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "metadata": { "id": "BGJnZbgEGS5-" }, @@ -555,7 +562,7 @@ { "data": { "text/html": [ - "Query job fcf9e1e9-cd3f-4a34-ba42-450c818bd6c7 is DONE. 0 Bytes processed. Open Job" + "Query job 41e4f2e7-689a-45d9-bf92-4416f5560b81 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -567,7 +574,7 @@ { "data": { "text/html": [ - "Query job c7b5f6a2-a5ca-4a4a-bcf3-9ddaa0a3777c is DONE. 0 Bytes processed. Open Job" + "Query job aae0b164-f786-4734-8c79-2af9805af0cf is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -622,7 +629,7 @@ "[2 rows x 1 columns]" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -657,7 +664,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 14, "metadata": { "id": "EDAaIwHpQCDZ" }, @@ -665,7 +672,7 @@ { "data": { "text/html": [ - "Query job 67d4d2d9-dd57-4886-8bcb-68e9eb6e11e2 is DONE. 0 Bytes processed. Open Job" + "Query job 17f50c10-aa81-4023-b206-4ba59ddf2269 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -677,7 +684,7 @@ { "data": { "text/html": [ - "Query job 26124cec-8753-4b48-b467-5e17c2c3591e is DONE. 0 Bytes processed. Open Job" + "Query job d6d217aa-a623-4ea4-83fb-8f1b8bfb8e68 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -689,7 +696,7 @@ { "data": { "text/html": [ - "Query job 9bdb0d90-60ec-4eec-96f4-990c3e1adef5 is DONE. 132 Bytes processed. Open Job" + "Query job a275a107-752e-46f8-be9f-9cb35eb6b0b9 is DONE. 132 Bytes processed. Open Job" ], "text/plain": [ "" @@ -706,7 +713,7 @@ "Name: API, dtype: string" ] }, - "execution_count": 13, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -736,7 +743,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 15, "metadata": { "id": "6i6HkFJZa8na" }, @@ -744,7 +751,7 @@ { "data": { "text/html": [ - "Query job f0199b1e-5524-48ba-81ec-89d70c28b5d0 is DONE. 0 Bytes processed. Open Job" + "Query job 01f95d2d-901d-4edf-bd3a-245d17c31ef6 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -756,7 +763,7 @@ { "data": { "text/html": [ - "Query job f1816195-25fa-4180-96ce-7917e9729428 is DONE. 584 Bytes processed. Open Job" + "Query job 55927a6f-b023-479a-b9bf-826abde77111 is DONE. 584 Bytes processed. Open Job" ], "text/plain": [ "" @@ -768,7 +775,7 @@ { "data": { "text/html": [ - "Query job ce1ad8d4-3fcd-4ca9-9f9b-4be0cfdabde5 is DONE. 146 Bytes processed. Open Job" + "Query job 445eb0af-f643-40c5-9c1e-25aa3db8374a is DONE. 146 Bytes processed. Open Job" ], "text/plain": [ "" @@ -780,7 +787,7 @@ { "data": { "text/html": [ - "Query job 3b245a41-a86e-4773-aa14-8edaa821c6b7 is DONE. 0 Bytes processed. Open Job" + "Query job ddee268c-773a-4dcc-b14c-ebdd90c2c347 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -792,7 +799,7 @@ { "data": { "text/html": [ - "Query job d3ceafe9-888d-4f5e-b7f3-c2218dae0736 is DONE. 904 Bytes processed. Open Job" + "Query job d7f1eb26-28b2-44ba-8858-5cd4df8621bd is DONE. 904 Bytes processed. Open Job" ], "text/plain": [ "" @@ -804,7 +811,7 @@ { "data": { "text/html": [ - "Query job 930c2334-60ac-4ec1-8a06-2a4cf2d9dc1e is DONE. 226 Bytes processed. Open Job" + "Query job f24d27a5-0e36-4fb5-953b-d09298f83af6 is DONE. 226 Bytes processed. Open Job" ], "text/plain": [ "" @@ -830,7 +837,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 16, "metadata": { "id": "9A2gw6hP_2nX" }, @@ -838,7 +845,7 @@ { "data": { "text/html": [ - "Query job 10a766a8-7368-4a82-b239-764e1c13ed64 is DONE. 21.0 kB processed. Open Job" + "Query job 65599c98-72ad-4088-8b09-f29bf05c164b is DONE. 21.8 kB processed. Open Job" ], "text/plain": [ "" @@ -855,11 +862,7 @@ "import pandas as pd\n", "\n", "# Create a DataFrame\n", - "df = pd.DataFrame({\n", - " \"Name\": [\"John\", \"Mary\", \"Peter\"],\n", - " \"Age\": [20, 25, 30],\n", - " \"City\": [\"New York\", \"London\", \"Paris\"]\n", - "})\n", + "df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "\n", "# Get the values as a NumPy array\n", "values = df.values\n", @@ -899,7 +902,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 17, "metadata": { "id": "GskyyUQPowBT" }, @@ -928,7 +931,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 18, "metadata": { "id": "PBlp-C-DOHRO" }, @@ -937,8 +940,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "Cloud Function Name projects/bigframes-dev/locations/us-central1/functions/bigframes-3a8781216c4ccdded9eecfdbd72c63f2\n", - "Remote Function Name bigframes-dev._76f0f906c2e04e83c3496619541347a5922c80ee.bigframes_3a8781216c4ccdded9eecfdbd72c63f2\n" + "Cloud Function Name projects/swast-scratch/locations/us-central1/functions/bigframes-6e7606963c3f06b8181b3cb9449a4363\n", + "Remote Function Name swast-scratch._63cfa399614a54153cc386c27d6c0c6fdb249f9e.bigframes_6e7606963c3f06b8181b3cb9449a4363\n" ] } ], @@ -960,11 +963,36 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 19, "metadata": { "id": "bsQ9cmoWo0Ps" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 047903f8-ea67-430a-8281-8fb5a119b779 is DONE. 21.8 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 793df956-0b1a-46ba-bb5e-e428171f3bd0 is DONE. 26.3 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "df_code = df_pred.assign(code=df_pred['ml_generate_text_llm_result'].apply(extract_code))\n", "series_code = series_pred.assign(code=series_pred['ml_generate_text_llm_result'].apply(extract_code))" @@ -981,7 +1009,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 20, "metadata": { "id": "7yWzjhGy_zcy" }, @@ -989,7 +1017,7 @@ { "data": { "text/html": [ - "Query job 96bea1ea-9c98-42e9-8f6d-a2b6cdeaf17a is DONE. 21.0 kB processed. Open Job" + "Query job 6974c2b7-2ed9-4564-a80b-57aef6959e19 is DONE. 22.8 kB processed. Open Job" ], "text/plain": [ "" @@ -1005,11 +1033,7 @@ "import bigframes.pandas as bf\n", "\n", "# Create a DataFrame\n", - "df = pd.DataFrame({\n", - " \"Name\": [\"John\", \"Mary\", \"Peter\"],\n", - " \"Age\": [20, 25, 30],\n", - " \"City\": [\"New York\", \"London\", \"Paris\"]\n", - "})\n", + "df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]])\n", "\n", "# Get the values as a NumPy array\n", "values = df.values\n", @@ -1046,7 +1070,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "metadata": { "id": "-J5LHgS6LLZ0" }, @@ -1055,7 +1079,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Creating gs://code-samples-d1d466b7-dfe6-11ee-b86e-4201c0a82d52/...\n" + "Creating gs://code-samples-773ee0f2-e302-11ee-8298-4201c0a8181f/...\n" ] } ], @@ -1077,7 +1101,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "metadata": { "id": "Zs_b5L-4IvER" }, @@ -1085,7 +1109,7 @@ { "data": { "text/html": [ - "Query job 72fe0ca6-2f37-457f-9705-ce89b2a4c324 is DONE. 21.0 kB processed. Open Job" + "Query job 81277037-032f-4557-a46e-1d39702f33d5 is DONE. 22.8 kB processed. Open Job" ], "text/plain": [ "" @@ -1097,7 +1121,7 @@ { "data": { "text/html": [ - "Query job 1b21be65-8761-4694-932e-8fa634569e56 is DONE. 0 Bytes processed. Open Job" + "Query job 8dc5a38c-ac16-44e7-83dd-4187380f780f is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1109,7 +1133,7 @@ { "data": { "text/html": [ - "Query job 510566f8-05f2-4455-8daa-f24feea0344e is DONE. 27.0 kB processed. Open Job" + "Query job 9087a758-b1f9-4be7-889b-7761ef0ad966 is DONE. 27.7 kB processed. Open Job" ], "text/plain": [ "" @@ -1121,7 +1145,7 @@ { "data": { "text/html": [ - "Query job 82c0e7f6-ce99-462c-a7d3-e760391f6677 is DONE. 0 Bytes processed. Open Job" + "Query job 6126ea72-c6f7-43f0-8888-e1c2a464a8a4 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1149,7 +1173,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "metadata": { "id": "PspCXu-qu_ND" }, @@ -1158,7 +1182,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "https://console.developers.google.com/storage/browser/code-samples-d1d466b7-dfe6-11ee-b86e-4201c0a82d52/\n" + "https://console.developers.google.com/storage/browser/code-samples-773ee0f2-e302-11ee-8298-4201c0a8181f/\n" ] } ], @@ -1195,7 +1219,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "metadata": { "id": "yw7A461XLjvW" }, @@ -1211,7 +1235,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "metadata": { "id": "sx_vKniMq9ZX" }, @@ -1226,7 +1250,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "metadata": { "id": "iQFo6OUBLmi3" }, @@ -1257,7 +1281,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.11.1" } }, "nbformat": 4, diff --git a/notebooks/generative_ai/bq_dataframes_llm_kmeans.ipynb b/notebooks/generative_ai/bq_dataframes_llm_kmeans.ipynb index 221933c2f8..d6d819f9e3 100644 --- a/notebooks/generative_ai/bq_dataframes_llm_kmeans.ipynb +++ b/notebooks/generative_ai/bq_dataframes_llm_kmeans.ipynb @@ -139,7 +139,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -147,26 +147,7 @@ "PROJECT_ID = \"\" # @param {type:\"string\"}\n", "\n", "# Set the project id in gcloud\n", - "! gcloud config set project {PROJECT_ID}" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Set the region\n", - "\n", - "You can also change the `REGION` variable used by BigQuery. Learn more about [BigQuery regions](https://cloud.google.com/bigquery/docs/locations#supported_locations)." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "REGION = \"US\" # @param {type: \"string\"}" + "#! gcloud config set project {PROJECT_ID}" ] }, { @@ -201,7 +182,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -220,7 +201,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -256,7 +237,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": { "id": "R7STCS8xB5d2" }, @@ -264,8 +245,9 @@ "source": [ "import bigframes.pandas as bf\n", "\n", - "bf.options.bigquery.project = PROJECT_ID\n", - "bf.options.bigquery.location = REGION" + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", + "bf.options.bigquery.project = PROJECT_ID" ] }, { @@ -288,7 +270,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": { "id": "zDSwoBo1CU3G" }, @@ -299,7 +281,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": { "id": "tYDoaKgJChiq" }, @@ -307,7 +289,19 @@ { "data": { "text/html": [ - "Query job 4423e883-bd7e-41c9-86b3-52d296a36b00 is DONE. 2.3 GB processed. Open Job" + "Query job 313ed696-37fc-46b3-806e-6041403080d3 is DONE. 2.3 GB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job f149ff34-4807-4cba-841f-fb7bf51bbbd6 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -319,7 +313,7 @@ { "data": { "text/html": [ - "Query job 4ddbf855-a48e-4d98-80d3-290b06d55e98 is DONE. 2.3 GB processed. Open Job" + "Query job 8ed05179-52b2-437d-a709-f651a80de307 is DONE. 4.6 kB processed. Open Job" ], "text/plain": [ "" @@ -389,7 +383,7 @@ "[5 rows x 1 columns]" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -409,7 +403,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": { "id": "OltYSUEcsSOW" }, @@ -431,7 +425,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": { "id": "li38q8FzDDMu" }, @@ -439,7 +433,7 @@ { "data": { "text/html": [ - "Query job 1f75a254-c8c5-468a-a8c0-76f342a2822a is DONE. 0 Bytes processed. Open Job" + "Query job bd6b88fc-6e05-4d71-acb1-d5befaced079 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -457,7 +451,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": { "id": "cOuSOQ5FDewD" }, @@ -465,7 +459,19 @@ { "data": { "text/html": [ - "Query job 15508c20-760e-4137-b312-f010913d13f5 is DONE. 2.3 GB processed. Open Job" + "Query job a4d2983a-7967-4ffb-b2b7-2a387f58776b is DONE. 2.3 GB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 619b0cc2-4162-44ab-a085-e7cc5c48a02b is DONE. 80.0 kB processed. Open Job" ], "text/plain": [ "" @@ -477,7 +483,7 @@ { "data": { "text/html": [ - "Query job 1e23baf5-8523-4fc5-9a73-d059c0b51c33 is DONE. 80.0 kB processed. Open Job" + "Query job 6dc5b3cf-efa6-4350-907e-ab40e3de80aa is DONE. 20.0 kB processed. Open Job" ], "text/plain": [ "" @@ -489,7 +495,7 @@ { "data": { "text/html": [ - "Query job 12bf5383-fa0d-4806-a4a9-d7ee65a0dd01 is DONE. 20.0 kB processed. Open Job" + "Query job 70f25b9e-2d26-4dc2-9d1f-c24d36e58856 is DONE. 72.0 MB processed. Open Job" ], "text/plain": [ "" @@ -501,7 +507,7 @@ { "data": { "text/html": [ - "Query job cafcd732-727b-4100-ac47-e6d98024fd16 is DONE. 80.0 kB processed. Open Job" + "Query job 2b2f366b-b398-4817-a610-cf71c64a8349 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -513,7 +519,7 @@ { "data": { "text/html": [ - "Query job 216b3d31-4159-4faf-93e6-820f82ca8f31 is DONE. 72.0 MB processed. Open Job" + "Query job b0e71a63-1365-4fc5-a764-b25b62387fd1 is DONE. 36.1 kB processed. Open Job" ], "text/plain": [ "" @@ -551,39 +557,39 @@ " \n", " \n", " \n", - " 3\n", - " [0.02506784163415432, -0.03947214409708977, -0...\n", - " {\"token_count\":273,\"truncated\":false}\n", + " 251\n", + " [ 2.20562406e-02 -3.51827666e-02 7.63384486e-...\n", + " {\"token_count\":145,\"truncated\":false}\n", " \n", - " Despite multiple written requests, the unverif...\n", + " A purse was purchased from XXXX XXXX on XX/XX/...\n", " \n", " \n", - " 102\n", - " [0.029197776690125465, -0.028653817251324654, ...\n", - " {\"token_count\":859,\"truncated\":false}\n", + " 300\n", + " [ 0.01977486 -0.04289974 -0.05289588 -0.027267...\n", + " {\"token_count\":498,\"truncated\":false}\n", " \n", - " To Whom It May Concern, Please be advised that...\n", + " XXXX XXXX XXXXXXXX has reported on my credit r...\n", " \n", " \n", - " 660\n", - " [0.034257132560014725, -0.05359702184796333, -...\n", - " {\"token_count\":282,\"truncated\":false}\n", + " 414\n", + " [ 1.37719307e-02 -4.15441953e-02 -7.81692266e-...\n", + " {\"token_count\":263,\"truncated\":false}\n", " \n", - " Transunion has failed to remove a XXXX XXXX b...\n", + " I have tried to dispute US BKPT CT TX XXXXXXXX...\n", " \n", " \n", - " 1500\n", - " [-0.008016454987227917, -0.05421802029013634, ...\n", - " {\"token_count\":39,\"truncated\":false}\n", + " 493\n", + " [ 4.48844060e-02 -1.40293539e-02 -3.46709713e-...\n", + " {\"token_count\":395,\"truncated\":false}\n", " \n", - " FRAUDULENT TRADELINES WERE ATTRIBUTED TO MY CR...\n", + " Discover Student Loan has been holding onto {$...\n", " \n", " \n", - " 1601\n", - " [-0.005403461866080761, -0.024799197912216187,...\n", - " {\"token_count\":94,\"truncated\":false}\n", + " 545\n", + " [ 1.82510037e-02 -1.27867460e-02 -1.57095697e-...\n", + " {\"token_count\":178,\"truncated\":false}\n", " \n", - " I am a victim of identity theft/fraud. I have ...\n", + " My payments have been approximately {$89.00} w...\n", " \n", " \n", "\n", @@ -591,31 +597,31 @@ "[5 rows x 4 columns in total]" ], "text/plain": [ - " text_embedding \\\n", - "3 [0.02506784163415432, -0.03947214409708977, -0... \n", - "102 [0.029197776690125465, -0.028653817251324654, ... \n", - "660 [0.034257132560014725, -0.05359702184796333, -... \n", - "1500 [-0.008016454987227917, -0.05421802029013634, ... \n", - "1601 [-0.005403461866080761, -0.024799197912216187,... \n", + " text_embedding \\\n", + "251 [ 2.20562406e-02 -3.51827666e-02 7.63384486e-... \n", + "300 [ 0.01977486 -0.04289974 -0.05289588 -0.027267... \n", + "414 [ 1.37719307e-02 -4.15441953e-02 -7.81692266e-... \n", + "493 [ 4.48844060e-02 -1.40293539e-02 -3.46709713e-... \n", + "545 [ 1.82510037e-02 -1.27867460e-02 -1.57095697e-... \n", "\n", - " statistics ml_embed_text_status \\\n", - "3 {\"token_count\":273,\"truncated\":false} \n", - "102 {\"token_count\":859,\"truncated\":false} \n", - "660 {\"token_count\":282,\"truncated\":false} \n", - "1500 {\"token_count\":39,\"truncated\":false} \n", - "1601 {\"token_count\":94,\"truncated\":false} \n", + " statistics ml_embed_text_status \\\n", + "251 {\"token_count\":145,\"truncated\":false} \n", + "300 {\"token_count\":498,\"truncated\":false} \n", + "414 {\"token_count\":263,\"truncated\":false} \n", + "493 {\"token_count\":395,\"truncated\":false} \n", + "545 {\"token_count\":178,\"truncated\":false} \n", "\n", - " content \n", - "3 Despite multiple written requests, the unverif... \n", - "102 To Whom It May Concern, Please be advised that... \n", - "660 Transunion has failed to remove a XXXX XXXX b... \n", - "1500 FRAUDULENT TRADELINES WERE ATTRIBUTED TO MY CR... \n", - "1601 I am a victim of identity theft/fraud. I have ... \n", + " content \n", + "251 A purse was purchased from XXXX XXXX on XX/XX/... \n", + "300 XXXX XXXX XXXXXXXX has reported on my credit r... \n", + "414 I have tried to dispute US BKPT CT TX XXXXXXXX... \n", + "493 Discover Student Loan has been holding onto {$... \n", + "545 My payments have been approximately {$89.00} w... \n", "\n", "[5 rows x 4 columns]" ] }, - "execution_count": 11, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -647,7 +653,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": { "id": "AhNTnEC5FRz2" }, @@ -668,7 +674,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": { "id": "6poSxh-fGJF7" }, @@ -676,7 +682,7 @@ { "data": { "text/html": [ - "Query job ed22ef18-cbdf-4c7a-9244-38f65e2bbefb is DONE. 61.5 MB processed. Open Job" + "Query job 37f432dd-9ed7-4bbd-adc1-f33b8cbab33a is DONE. 61.5 MB processed. Open Job" ], "text/plain": [ "" @@ -688,7 +694,7 @@ { "data": { "text/html": [ - "Query job 5e94bc4b-44d6-4c20-b907-cee9795d5b54 is DONE. 61.4 MB processed. Open Job" + "Query job 8ca9cc5a-091a-4d4e-bcf8-04d4bfec7b6b is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -700,7 +706,7 @@ { "data": { "text/html": [ - "Query job 915d58d8-403b-44bf-8cf2-38ad5a87be9d is DONE. 72.3 MB processed. Open Job" + "Query job cdc11d15-fa78-4190-841f-18642ddb53f8 is DONE. 72.3 MB processed. Open Job" ], "text/plain": [ "" @@ -712,7 +718,7 @@ { "data": { "text/html": [ - "Query job fa241e23-d153-49ea-8dff-6d28906bcb1f is DONE. 80.0 kB processed. Open Job" + "Query job 39a6ea59-0e3d-4d69-bf8a-1502b9f1a48f is DONE. 80.0 kB processed. Open Job" ], "text/plain": [ "" @@ -724,7 +730,7 @@ { "data": { "text/html": [ - "Query job a3b00aa3-d6d6-4e30-ac96-816b81fcd202 is DONE. 80.0 kB processed. Open Job" + "Query job 324ab354-ecbd-4bde-8f73-806856a53a19 is DONE. 73.2 MB processed. Open Job" ], "text/plain": [ "" @@ -736,7 +742,19 @@ { "data": { "text/html": [ - "Query job 38277ed2-bcad-4de1-b508-7bb44b3158dc is DONE. 73.2 MB processed. Open Job" + "Query job cb7558b2-a967-491c-82db-e11116f1fba4 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 0cfc2298-e67b-4a03-804d-f4abd8d56da0 is DONE. 36.6 kB processed. Open Job" ], "text/plain": [ "" @@ -776,49 +794,49 @@ " \n", " \n", " \n", - " 3\n", - " 8\n", - " [{'CENTROID_ID': 8, 'DISTANCE': 0.399505154607...\n", - " [0.02506784163415432, -0.03947214409708977, -0...\n", - " {\"token_count\":273,\"truncated\":false}\n", + " 251\n", + " 2\n", + " [{'CENTROID_ID': 2, 'DISTANCE': 0.534540549592...\n", + " [ 2.20562406e-02 -3.51827666e-02 7.63384486e-...\n", + " {\"token_count\":145,\"truncated\":false}\n", " \n", - " Despite multiple written requests, the unverif...\n", + " A purse was purchased from XXXX XXXX on XX/XX/...\n", " \n", " \n", - " 102\n", - " 8\n", - " [{'CENTROID_ID': 8, 'DISTANCE': 0.403332660368...\n", - " [0.029197776690125465, -0.028653817251324654, ...\n", - " {\"token_count\":859,\"truncated\":false}\n", + " 300\n", + " 1\n", + " [{'CENTROID_ID': 1, 'DISTANCE': 0.437379245910...\n", + " [ 0.01977486 -0.04289974 -0.05289588 -0.027267...\n", + " {\"token_count\":498,\"truncated\":false}\n", " \n", - " To Whom It May Concern, Please be advised that...\n", + " XXXX XXXX XXXXXXXX has reported on my credit r...\n", " \n", " \n", - " 660\n", - " 10\n", - " [{'CENTROID_ID': 10, 'DISTANCE': 0.42615208239...\n", - " [0.034257132560014725, -0.05359702184796333, -...\n", - " {\"token_count\":282,\"truncated\":false}\n", + " 414\n", + " 1\n", + " [{'CENTROID_ID': 1, 'DISTANCE': 0.482813493921...\n", + " [ 1.37719307e-02 -4.15441953e-02 -7.81692266e-...\n", + " {\"token_count\":263,\"truncated\":false}\n", " \n", - " Transunion has failed to remove a XXXX XXXX b...\n", + " I have tried to dispute US BKPT CT TX XXXXXXXX...\n", " \n", " \n", - " 1500\n", - " 6\n", - " [{'CENTROID_ID': 6, 'DISTANCE': 0.500031509322...\n", - " [-0.008016454987227917, -0.05421802029013634, ...\n", - " {\"token_count\":39,\"truncated\":false}\n", + " 493\n", + " 9\n", + " [{'CENTROID_ID': 9, 'DISTANCE': 0.561752335987...\n", + " [ 4.48844060e-02 -1.40293539e-02 -3.46709713e-...\n", + " {\"token_count\":395,\"truncated\":false}\n", " \n", - " FRAUDULENT TRADELINES WERE ATTRIBUTED TO MY CR...\n", + " Discover Student Loan has been holding onto {$...\n", " \n", " \n", - " 1601\n", - " 6\n", - " [{'CENTROID_ID': 6, 'DISTANCE': 0.361769337067...\n", - " [-0.005403461866080761, -0.024799197912216187,...\n", - " {\"token_count\":94,\"truncated\":false}\n", + " 545\n", + " 9\n", + " [{'CENTROID_ID': 9, 'DISTANCE': 0.540487926907...\n", + " [ 1.82510037e-02 -1.27867460e-02 -1.57095697e-...\n", + " {\"token_count\":178,\"truncated\":false}\n", " \n", - " I am a victim of identity theft/fraud. I have ...\n", + " My payments have been approximately {$89.00} w...\n", " \n", " \n", "\n", @@ -826,38 +844,38 @@ "[5 rows x 6 columns in total]" ], "text/plain": [ - " CENTROID_ID NEAREST_CENTROIDS_DISTANCE \\\n", - "3 8 [{'CENTROID_ID': 8, 'DISTANCE': 0.399505154607... \n", - "102 8 [{'CENTROID_ID': 8, 'DISTANCE': 0.403332660368... \n", - "660 10 [{'CENTROID_ID': 10, 'DISTANCE': 0.42615208239... \n", - "1500 6 [{'CENTROID_ID': 6, 'DISTANCE': 0.500031509322... \n", - "1601 6 [{'CENTROID_ID': 6, 'DISTANCE': 0.361769337067... \n", + " CENTROID_ID NEAREST_CENTROIDS_DISTANCE \\\n", + "251 2 [{'CENTROID_ID': 2, 'DISTANCE': 0.534540549592... \n", + "300 1 [{'CENTROID_ID': 1, 'DISTANCE': 0.437379245910... \n", + "414 1 [{'CENTROID_ID': 1, 'DISTANCE': 0.482813493921... \n", + "493 9 [{'CENTROID_ID': 9, 'DISTANCE': 0.561752335987... \n", + "545 9 [{'CENTROID_ID': 9, 'DISTANCE': 0.540487926907... \n", "\n", - " text_embedding \\\n", - "3 [0.02506784163415432, -0.03947214409708977, -0... \n", - "102 [0.029197776690125465, -0.028653817251324654, ... \n", - "660 [0.034257132560014725, -0.05359702184796333, -... \n", - "1500 [-0.008016454987227917, -0.05421802029013634, ... \n", - "1601 [-0.005403461866080761, -0.024799197912216187,... \n", + " text_embedding \\\n", + "251 [ 2.20562406e-02 -3.51827666e-02 7.63384486e-... \n", + "300 [ 0.01977486 -0.04289974 -0.05289588 -0.027267... \n", + "414 [ 1.37719307e-02 -4.15441953e-02 -7.81692266e-... \n", + "493 [ 4.48844060e-02 -1.40293539e-02 -3.46709713e-... \n", + "545 [ 1.82510037e-02 -1.27867460e-02 -1.57095697e-... \n", "\n", - " statistics ml_embed_text_status \\\n", - "3 {\"token_count\":273,\"truncated\":false} \n", - "102 {\"token_count\":859,\"truncated\":false} \n", - "660 {\"token_count\":282,\"truncated\":false} \n", - "1500 {\"token_count\":39,\"truncated\":false} \n", - "1601 {\"token_count\":94,\"truncated\":false} \n", + " statistics ml_embed_text_status \\\n", + "251 {\"token_count\":145,\"truncated\":false} \n", + "300 {\"token_count\":498,\"truncated\":false} \n", + "414 {\"token_count\":263,\"truncated\":false} \n", + "493 {\"token_count\":395,\"truncated\":false} \n", + "545 {\"token_count\":178,\"truncated\":false} \n", "\n", - " content \n", - "3 Despite multiple written requests, the unverif... \n", - "102 To Whom It May Concern, Please be advised that... \n", - "660 Transunion has failed to remove a XXXX XXXX b... \n", - "1500 FRAUDULENT TRADELINES WERE ATTRIBUTED TO MY CR... \n", - "1601 I am a victim of identity theft/fraud. I have ... \n", + " content \n", + "251 A purse was purchased from XXXX XXXX on XX/XX/... \n", + "300 XXXX XXXX XXXXXXXX has reported on my credit r... \n", + "414 I have tried to dispute US BKPT CT TX XXXXXXXX... \n", + "493 Discover Student Loan has been holding onto {$... \n", + "545 My payments have been approximately {$89.00} w... \n", "\n", "[5 rows x 6 columns]" ] }, - "execution_count": 13, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -899,7 +917,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": { "id": "2E7wXM_jGqo6" }, @@ -907,7 +925,7 @@ { "data": { "text/html": [ - "Query job 8aec7d59-aaf5-4c55-85d3-1c96ee904558 is DONE. 10.5 MB processed. Open Job" + "Query job 84f95981-01c7-49ca-a10c-5842f07d867f is DONE. 10.6 MB processed. Open Job" ], "text/plain": [ "" @@ -919,7 +937,7 @@ { "data": { "text/html": [ - "Query job f269725a-da1c-46d4-aa3f-3525bbbceaef is DONE. 10.5 MB processed. Open Job" + "Query job 0872869a-94f0-4c3f-9f92-da7272f95cd0 is DONE. 10.6 MB processed. Open Job" ], "text/plain": [ "" @@ -945,7 +963,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": { "id": "ZNDiueI9IP5e" }, @@ -955,52 +973,48 @@ "output_type": "stream", "text": [ "comment list 1:\n", - "1. Out of the blue I received a debt collection notice saying they were collecting debt of {$710.00} for a XXXX XXXX which I have no idea what it was and was never notified of. I replied with written notification disputing the debt and demand of supporting documentation ( as the debt collection simply stated a total due with no supporting documentation ) but received no supporting documentation or verification.\n", - "2. I am referring a case to the Consumer Protection Bureau as follows. \n", - "\n", - "First, please see the most recent document, 'New_Debt_Collector_Account.jpg '. This was sent to me on XX/XX/2021 and arrived on XX/XX/2021. This is a letter from \" I.C. System '' telling me I must pay a delinquent account for \" XXXX ''. An account I thought that was already settled by \" Offices of the XXXX XXXX XXXX ''. Or so I believed. Until now... \n", - "\n", - "See attachment 'dispute.rtf '. This is the original letter I sent to \" Offices of the XXXX XXXX XXXX ''. Within 'dispute.rtf ' is a very detailed, and extremely well articulated ( if I do say so myself ) dispute letter, delineating the abuses and reasons to \" XXXX '' of why I would not pay the bill. In a response, sent back to me by \" Offices of the XXXX XXXX XXXX '', 'dispute_response.jpg ', they said they would discontinue their collection efforts and no information regarding this account would be referred to the credit bureau XXXX \n", - "\n", - "THEN, 7 months later, from \" I.C. System '' I receive, 'New_Debt_Collector_Account.jpg ', as first seent above, saying I still owe this debt.\n", - "\n", - "My question, to \" I.C. System '' \" XXXX XXXX '' and the \" Consumer Protection Bureau '' are : How can I dispute and then remove a debt, that I legitimatlly do not owe, and be exonerated from it, if \" Charter/Spectrum '' can simply refer it to another debt collecting company to try and collect it? And then tarnish my credit? Is misleading a consumer like this 'legal '?\n", + "1. XXXX XXXX XXXXXXXX has reported on my credit report for XXXX that I had 3 payments 30 or more days past due this information was and is incorrect i have sent numerous letters and responses to them asking for information regarding this reporting the bank continues to send me responces stating that my credit report is accurat but no documentation supporting the reporting of negative payments i have sent the XXXX XXXX XXXX numerous document showing past mistake of my payment that were misapplied by thier associates yet they still will not correct my credit report the XXXX XXXX XXXX has the wrong infor mation on my payment, balance last payments amount made & ect i have recently sent them a letter ( This is the exact letter ) and other information im having problems with the problem im having Date BLANK BLANK BLANK Complaint Dispute on credit report reporting XXXX XXXX XXXX Address Mail XXXX fl XXXX XXXX XXXX XXXX FL Zip Code XXXX Regarding Account Number ( Blank ) & Account Number ( Blank ) I ( blank ) on this XXXX Day of XXXX XXXX do hereby request a complete copy of my payment history from XXXX XXXX XXXX to XXXX XXXX XXXX this request is to include dates of all payments that was made on these accounts dates of all payments that were past due on these accounts and dates payments was paid to these account s after due date. I ( Blank ) am also requesting all letters and correspondence advising me / making me aware of my past due payments I also request all payments showing my account were paid 30 or more days late I ( Blank ) also request all payment dates and how payment was made ( Ex XXXX XXXX XXXX XXXXXXXX. XXXX Please Mail this information ASAP\n", + "2. I have tried to dispute US BKPT CT TX XXXXXXXX XXXX XXXX Account number XXXX on my credit report several times as inaccurate ( XX/XX/XXXX XX/XX/XXXX XX/XX/XXXX and XX/XX/XXXX ) as not mine but the credit bureaus have verified that it is accurate. I mailed a letter to the county records office ( XX/XX/XXXX ) pertaining to US BKPT CT TX XXXX Account number XXXX where this occurred and they replied on XX/XX/XXXX stating that they do not send information to the credit bureaus. This is where I am confused because after reading the law the FCRA if the original creditor or institution can not verify the information then the credit bureaus reporting it have to delete it. I sent this into the credit bureaus as well along with the paperwork from the county record office and it seems like they are not doing ANY sort of investigation which they are required to\n", + "3. Unauthorized hard inquires on my credit report and bureau refuses to remove them after they placed them on my credit report with my authorization XXXX Inquiry XX/XX/XXXX XXXX XXXX Inquiry XX/XX/XXXX XXXX XXXX inquiry XX/XX/XXXX and XX/XX/XXXX XXXX XX/XX/XXXX XXXX\n", + "4. XXXX - XX/XX/2020 Equifax Hello, I have reviewed a copy of my current credit report and it shows the inquiries above are fraudulent and I have sent a copy of FTC report to request removal. I have not been successful and need these removed due to attempting to purchase a home.\n", + "5. I have tried to remedy the issue that XXXX XXXX caused as XXXX XXXX indicated to me that Equifax could not remove a discharge debt from my report because of two social security numbers. In fact it was not two ssn 's but rather my deceased husbands DOB XXXX was on my report. XXXX XXXX is notorious for reporting incorrect data so i am going to get this resolved through CEPB. Attached please find the bankruptcy discharge notification and a copy of the requested drivers license with my DOB, XXXX. I expect that the debt for XXXX placed by XXXX XXXX to be removed as all the requested documentation is included in the correspondence.\n", "\n", - "As 'dispute.rtf ' indicates, I even said I would contact the Consumer Protection Bureau and the XXXX. I did not originally do this and regret that decision, but I am doing so now!! \n", - "\n", - "Furthermore, due to the unparalleled absolute deceptive malfeasance on the part of \" XXXX '' and these debt XXXX, I am considering approaching media outlets with my story. Consumers can not and should not be ripped of this way and their credit tarnished, while a corrupt telecommunications company and their debt collecting cronies attempt to charge them for several months of internet they never had. \n", + "comment list 2:\n", + "1. A purse was purchased from XXXX XXXX on XX/XX/2021. As they stated my package was delivered and signed for. Indeed it was, I also still have it. My package was damaged and only XXXX can file a claim with XXXX. I have tried to contact XXXX and was told to contact the shipper. I have contacted XXXX and was told that a chargeback was filed with TCF so there is nothing that they can do. I have provided all of these documents to you all including a police report. I will continue to escalate this if needed.\n", + "2. On Saturday XX/XX/XXXX I submitted a dispute for several fraudulent transactions with chime. I had stopped using chime back in XXXX of 2022 because I believed they were scamming me because of the money that was being taken out of my account without my knowledge and i had also had my phone stolen at work with my chime card and ssi & ID in the back of my phone case. I told them I believed thats how i was scammed for all of those fraudulent transactions that I disputed and also that money from my job had still been posting in my chime account after i had stopped using it because i was unable to change my direct deposit information with my job because i couldnt access my chime account anymore so I didnt have access to my routing and account number but i still had my card connected to my apple pay which I eventually stopped using because i was getting paid but most time my card on apple pay was declined because i was still being scammed out my money. Ive tried ordering new cards several time before I completely stopped using chime however the same thing was happening with each card and chime couldnt figure out how to stop it. \n", + "A few days ago i tried to create a new chime bank account because i had completely forgotten about my old scammed chime account but that app prompted me to sign into my old account Chime told me that they would do a complete investigation and let me know of the results. \n", + "However, on Sunday XX/XX/XXXX at XXXX i got an email from chime stating Hello XXXX XXXX XXXX This letter is to inform you that we have made a final determination regarding the claim referenced above. \n", + "Based on our investigation, we have concluded no error occurred. Therefore, no funds will be credited to your account and this claim is considered closed. \n", "\n", - "This is fraud, it is illegal, and it needs to stop. And I wish to be exonerated from this debt as I was originally led to believe!!! \n", + "I emailed them back for the documentation on how they did the dispute and verified the information was inaccurate. I also asked how is it possible that a investigation for 20+ transactions had been completed in less than 1 day. \n", + "I truly believe chime did not do any investigation at all and that they lied about my investigation/dispute They have been unable to provide me with the documents and dispute information. In fact, they said id have to wait 10+ business days to receive that information in mail because they arent going to email it to me I found this very unfortunate. \n", "\n", - "Finally, if \" XXXX '' are part of any class action lawsuits involving this behaviour ( and I'm sure they are ), then I wish to testify on the behalf on any government, individual, and/or private institutions as to the corrput nature of entities such as \" XXXX '' and their debt collectors, and hereby consent to providing all the following statements, including all attachments herein, and any testimony they want me to give as evidence. \n", + "Here are my reference numbers for my disputes XXXX XXXX\n", + "3. My sister and I attempted to close our aging father 's professional account at Wells Fargo. My sister worked closely with the local branch and followed their directives. But, even after 6 months the bank continued to reject the paperwork presented. Anticipating our father 's further decline, we hired an estate attorney to help us close the account. Even after appointing me as an officer of my dad 's company and presenting new documentation which followed the bank 's directive, the bank again refused to move the money to my mother and to close the account. The entire time the balance of the account was depleted through bank fees from around {$1800.00} to around {$1000.00}. In the end, Wells Fargo refunded the entire original balance of around {$1800.00} plus some a \" consumer satisfaction credit '' and transferred the funds to my mother 's account.\n", + "4. On XXXX XX/XX/2020 a sale of three Tahitian pearl necklaces was made by my online shop. This amounted to approximately {$2800.00}. Some of the funds were withdrawn by me leaving a total of {$220000.00} in the Paypal account. \n", "\n", - "-XXXX XXXX XXXX XXXX XXXX\n", - "3. XXXX called on XX/XX/XXXX at about XXXXXXXX XXXX claiming to be from Sherloq financial, about collecting medical debt from XXXX, he was XXXX and XXXX and said there were four other accounts but did not specify which or how much. I have been contacted by my insurance that I have paid everything in relation to this. I have talked to my doctor and my endocrinologist and they said I don't owe anything either. ( I am XXXX and have XXXX and XXXX that pays for my doctor visits. ) I feel that they are just trying to collect money they are not owed and its predatory.\n", - "4. While moving out of my long time residence in XXXX, CA I began the process to cut off my services in XXXX of XXXX which included the phone, internet and XXXX, which were all included in a single bill. Initially the final date I relayed to XXXX XXXX XXXX was the XXXX of XXXX but because of delays in the move was extended to XX/XX/XXXX. Because XXXX ended up mistakenly cutting off the satellite service on the XXXX I had to call them directly to extend it to the XXXX. I left the house for the last time on XXXX XX/XX/XXXX and turn in all the equipment as required to the local XXXX office. Although I assumed all the services were ended properly I continued to get bills from XXXX ( not from XXXX XXXX XXXX ) so I called several times to rectify the mistake and finally sent a detailed escalation letter to them in XX/XX/XXXX. I felt at this point they finally realized their mistake and closed the bill but in XXXX of XXXX I then received a collection notice from Afni, Inc. for the disputed amount. I recently forwarded them a dispute letter along with other pertinent details of the situation. I have no idea why XXXX is unable to verify the fact I no longer lived at the XXXX residence, nor retained any of the receivers or remotes after the XXXX of XX/XX/XXXX. This should be an easy task on their end especially since I went above and beyond due diligence to work with them to correct this.\n", - "5. Merchants and Medical Credit began reporting on a debt they had acquired on XXXX XXXX 2014 and never sent written notice despite it being required under section 806 of the FDCPA. For 3 years they have been holding my financial life hostage and only recently came to my attention. Despite many disputes with the big three credit reporting agencies section 806 has been ignored and they have continued to break and ignore the proper procedures set forth by the FDCPA.\n", + "Suddenly the balance was frozen for 180 days by Paypal. A telephone call to their customer service on about XXXX XXXX resulted in a rude and abrupt lady telling me that Paypal was parting ways with me. I was given no reasonable explanation why the account was limited or the funds frozen other than to infer that I was busy with fraudulent activity. The rude person refused to give me more details. \n", "\n", - "comment list 2:\n", - "1. I have a PayPal account and a PayPal credit card and a XXXX XXXX Checking account. \n", - "If I use PayPal, or the PayPal credit card the charges are then debited from my XXXX XXXX Checking account.. \n", + "I submitted all the details/documents they requested from then on. My appeals were refused, On XXXX XX/XX/2020 the 180 frozen days expired. I was requested by Paypal to submit all my personal details/documents again. I did. I have the XXXX XXXX XXXX XXXX ID Document. It is perfectly legal and valid in XXXX XXXX as is the new XXXX XXXXXXXX which is now being issued. But Paypal is not accepting my ID Document. So my funds are not being released.They send computer generated emails which offer no explanation as to why my ID document is not being accepted or any solution to the problem. \n", "\n", - "Recently there were two fraudulent and unauthorized charges I was alerted to by PayPal.\n", + "This matter is most frustrating and I'm sure not in line with any financial practice.\n", + "5. On XX/XX/XXXX I received a text from Chase showing -- -- -- -- - Chase Fraud : Did you attempt a {$1700.00} withdrawal on XX/XX/XXXX with card XXXX? \n", + "replay yes or no. Msg & data rates may apply. \n", + "-- -- -- -- - Then I replied no, Then chase sent a text they will close my account, give them a call. \n", "\n", - "One was a debit from XXXX for {$240.00}. I contacted XXXX and they said there was no record for that amount and date for purchases or charges anywhere on XXXX. They said it was most likely fraudulent and I never authorized it. \n", + "So I called chase to report, they are saying because it is pending transaction I have to wait until pending is gone, 2 days later they accepted my claim. \n", "\n", - "The other was from XXXX XXXX for {$50.00}. I did make political donations to politicians during the election cycle and I noted each in my checking account. I STOPPED making any further contributions after the last elections in Georgia. This charge was not one I had authorized and it was dated AFTER the last election and was not one of the ones I had checked against my checking account. \n", + "Today XX/XX/XXXX they refused to credit my money {$1700.00} because my pin number and debit card were used. So I told them I never received card. \n", + "Still their answer is same. \n", "\n", - "I disputed both with XXXX XXXX on my checking account and they researched both of them and determined they were fraudulent and XXXX XXXX noted in writing \" We have completed our research of your inquiry and returned the charges unpaid. As a result no money was deducted from your account '' I have filed two claims disputing both charges to PayPal and each time they have denied my fraudulent/unauthorized claims and I even spoke to PayPal people several times and quoted XXXX XXXX to them and then filed a dispute with them on their denial. \n", + "Then I asked what should I do? file small claim against chase? go to police office? \n", + "They told me I can go to police office to file a claim. \n", "\n", - "They are still denying my dispute and claiming that I owe them {$290.00} for both fraudulent charges. Please help me get this resolved. They keep sending me notices and phone calls. I should not have to pay them since XXXX XXXX returned them as unpaid and determined they were fraudulent and even XXXX says there was no purchase or credit so it was fraudulent and unauthorized.\n", - "2. Banked with truist for almost XXXX months now and never had an issue until i decided to start funding my account and using my debit card to pay my bills, they locked my debit card which is fine, called to have it unblocked no problem and they end up locking it again but this time they are saying i have to come into a branch to do so which IS a problem. Truist bank is nowhere near me in my state, its an out of state bank so thats literally not an option. Bank locked my online banking with money still in my account lol, i tried an ACH transfer and set up bill pay payments and i tried to log in just to find out my account is restricted for security reasons. This has been XXXX of the worst banking experiences i've ever had and im not being treated like a customer at all. its almost like truist isnt allowing me to use my money the way i want or access my funds properly. Ive had no problem up until i made a large deposit into my account and started using those funds. \n", + "I will go to police office after my work. \n", "\n", - "i have no problenm verifying myself any other way but going out of my current state just to visit truist bank is not an option.\n", - "3. Navy Exchange ( NEX ), the \" XXXX '' onboard US XXXX bases, offers currency exchange for personnel stationed overseas ( in XXXX ) to pay their off-base rent. However, the exchange rate offered is always 2-3 % less than the Bank Rate for US dollar to XXXX XXXX exchange. \n", + "Before I go to police office, I am asking your help about this situation. \n", "\n", - "To offset this, the Navy Exchange provides a {$10.00} gift card for use at the NEX, for each month paid. However, this is inequitable because the gift card is always for the same amount, regardless of the monthly rent amount ... so a single military member with an $ XXXX/month ( equivalent ) rent payment derives more proportional benefit from this {$10.00} gift card than a military family whose rent could be closer to $ XXXX ( equivalent ).\n", - "4. In XX/XX/XXXX, based on a friend 's recommendation, I visited a vacation rental home website to rent her neighbor 's property in XXXX, California, USA. The vacation rental home website is called : XXXX. I used the right side of the website called \" Contact Owner '' to reach out to the owner. I received an email from the owner, XXXX, who let me know that the property was only available for 26 days at a time, as such, I did not move forward. I also received another email from the email address : XXXX. The contact was named XXXX XXXX who asked for desired check-in/out dates, number of bedrooms, and preferred location. He also asked about preferred budget and stated that he manages a lot of properties and could offer an attractive discount. I responded with my preferences and he sent an offer for a vacation rental property. He included a link to view the property via XXXX. I asked for the address of the property and he provided the following address : XXXX XXXX XXXX XXXX, California. He let me know that 50 % of the total was due as a deposit and the remaining amount was due 30 days prior to the arrival date. He also let me know that the owners of the property live in XXXX and require payment with the company XXXX ( formerly TransferWise ). I recognize XXXX as I have used the company in the past and already had an account. Therefore, on XX/XX/XXXX, I sent the money through XXXX to the stated \" Owners '' of the property : XXXX XXXX and XXXX XXXX. \n", - "Eight days later, I realized that the transaction was a scam after Googling the email address ( XXXX ). There were at least 20 reviewers with similar experiences that claimed this entity was a scammer for rental properties. At this point ( on XX/XX/XXXX ), I reached back out to XXXX via email to ask for the money back, and he agreed to send the money via check to my mailing address. However, the check did not arrive. I let him know that the money did not arrive and asked him to reverse the XXXX transaction. However, I did not receive a response from XXXX. After this, I contacted my bank. My bank provided a temporary reimbursement while an investigation was performed. After the investigation was complete 60 days later ( XX/XX/XXXX ), the reimbursement was removed since my bank determined that XXXX is the company responsible in this matter. As such, I am looking to get a refund for the amount with XXXX.\n", - "5. I can not withdraw money or pay my rent from my Way to go card from Florida reemployment. It keeps declining me. It was working fine in XXXX, I went to pay my rent for XXXX, and it declined ; I went to an atm again declined. So I ordered a new card and paid expedited shipping ; thinking this one was damaged, I activated it, and it again declined me. There is absolutely no way to contact anyone. All they have is an automatic response which doesn't provide any help\n", + "Please help me.\n", "\n" ] } @@ -1023,7 +1037,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": { "id": "BfHGJLirzSvH" }, @@ -1034,51 +1048,47 @@ "text": [ "Please highlight the most obvious difference between the two lists of comments:\n", "comment list 1:\n", - "1. Out of the blue I received a debt collection notice saying they were collecting debt of {$710.00} for a XXXX XXXX which I have no idea what it was and was never notified of. I replied with written notification disputing the debt and demand of supporting documentation ( as the debt collection simply stated a total due with no supporting documentation ) but received no supporting documentation or verification.\n", - "2. I am referring a case to the Consumer Protection Bureau as follows. \n", - "\n", - "First, please see the most recent document, 'New_Debt_Collector_Account.jpg '. This was sent to me on XX/XX/2021 and arrived on XX/XX/2021. This is a letter from \" I.C. System '' telling me I must pay a delinquent account for \" XXXX ''. An account I thought that was already settled by \" Offices of the XXXX XXXX XXXX ''. Or so I believed. Until now... \n", - "\n", - "See attachment 'dispute.rtf '. This is the original letter I sent to \" Offices of the XXXX XXXX XXXX ''. Within 'dispute.rtf ' is a very detailed, and extremely well articulated ( if I do say so myself ) dispute letter, delineating the abuses and reasons to \" XXXX '' of why I would not pay the bill. In a response, sent back to me by \" Offices of the XXXX XXXX XXXX '', 'dispute_response.jpg ', they said they would discontinue their collection efforts and no information regarding this account would be referred to the credit bureau XXXX \n", - "\n", - "THEN, 7 months later, from \" I.C. System '' I receive, 'New_Debt_Collector_Account.jpg ', as first seent above, saying I still owe this debt.\n", - "\n", - "My question, to \" I.C. System '' \" XXXX XXXX '' and the \" Consumer Protection Bureau '' are : How can I dispute and then remove a debt, that I legitimatlly do not owe, and be exonerated from it, if \" Charter/Spectrum '' can simply refer it to another debt collecting company to try and collect it? And then tarnish my credit? Is misleading a consumer like this 'legal '?\n", - "\n", - "As 'dispute.rtf ' indicates, I even said I would contact the Consumer Protection Bureau and the XXXX. I did not originally do this and regret that decision, but I am doing so now!! \n", + "1. XXXX XXXX XXXXXXXX has reported on my credit report for XXXX that I had 3 payments 30 or more days past due this information was and is incorrect i have sent numerous letters and responses to them asking for information regarding this reporting the bank continues to send me responces stating that my credit report is accurat but no documentation supporting the reporting of negative payments i have sent the XXXX XXXX XXXX numerous document showing past mistake of my payment that were misapplied by thier associates yet they still will not correct my credit report the XXXX XXXX XXXX has the wrong infor mation on my payment, balance last payments amount made & ect i have recently sent them a letter ( This is the exact letter ) and other information im having problems with the problem im having Date BLANK BLANK BLANK Complaint Dispute on credit report reporting XXXX XXXX XXXX Address Mail XXXX fl XXXX XXXX XXXX XXXX FL Zip Code XXXX Regarding Account Number ( Blank ) & Account Number ( Blank ) I ( blank ) on this XXXX Day of XXXX XXXX do hereby request a complete copy of my payment history from XXXX XXXX XXXX to XXXX XXXX XXXX this request is to include dates of all payments that was made on these accounts dates of all payments that were past due on these accounts and dates payments was paid to these account s after due date. I ( Blank ) am also requesting all letters and correspondence advising me / making me aware of my past due payments I also request all payments showing my account were paid 30 or more days late I ( Blank ) also request all payment dates and how payment was made ( Ex XXXX XXXX XXXX XXXXXXXX. XXXX Please Mail this information ASAP\n", + "2. I have tried to dispute US BKPT CT TX XXXXXXXX XXXX XXXX Account number XXXX on my credit report several times as inaccurate ( XX/XX/XXXX XX/XX/XXXX XX/XX/XXXX and XX/XX/XXXX ) as not mine but the credit bureaus have verified that it is accurate. I mailed a letter to the county records office ( XX/XX/XXXX ) pertaining to US BKPT CT TX XXXX Account number XXXX where this occurred and they replied on XX/XX/XXXX stating that they do not send information to the credit bureaus. This is where I am confused because after reading the law the FCRA if the original creditor or institution can not verify the information then the credit bureaus reporting it have to delete it. I sent this into the credit bureaus as well along with the paperwork from the county record office and it seems like they are not doing ANY sort of investigation which they are required to\n", + "3. Unauthorized hard inquires on my credit report and bureau refuses to remove them after they placed them on my credit report with my authorization XXXX Inquiry XX/XX/XXXX XXXX XXXX Inquiry XX/XX/XXXX XXXX XXXX inquiry XX/XX/XXXX and XX/XX/XXXX XXXX XX/XX/XXXX XXXX\n", + "4. XXXX - XX/XX/2020 Equifax Hello, I have reviewed a copy of my current credit report and it shows the inquiries above are fraudulent and I have sent a copy of FTC report to request removal. I have not been successful and need these removed due to attempting to purchase a home.\n", + "5. I have tried to remedy the issue that XXXX XXXX caused as XXXX XXXX indicated to me that Equifax could not remove a discharge debt from my report because of two social security numbers. In fact it was not two ssn 's but rather my deceased husbands DOB XXXX was on my report. XXXX XXXX is notorious for reporting incorrect data so i am going to get this resolved through CEPB. Attached please find the bankruptcy discharge notification and a copy of the requested drivers license with my DOB, XXXX. I expect that the debt for XXXX placed by XXXX XXXX to be removed as all the requested documentation is included in the correspondence.\n", + "comment list 2:\n", + "1. A purse was purchased from XXXX XXXX on XX/XX/2021. As they stated my package was delivered and signed for. Indeed it was, I also still have it. My package was damaged and only XXXX can file a claim with XXXX. I have tried to contact XXXX and was told to contact the shipper. I have contacted XXXX and was told that a chargeback was filed with TCF so there is nothing that they can do. I have provided all of these documents to you all including a police report. I will continue to escalate this if needed.\n", + "2. On Saturday XX/XX/XXXX I submitted a dispute for several fraudulent transactions with chime. I had stopped using chime back in XXXX of 2022 because I believed they were scamming me because of the money that was being taken out of my account without my knowledge and i had also had my phone stolen at work with my chime card and ssi & ID in the back of my phone case. I told them I believed thats how i was scammed for all of those fraudulent transactions that I disputed and also that money from my job had still been posting in my chime account after i had stopped using it because i was unable to change my direct deposit information with my job because i couldnt access my chime account anymore so I didnt have access to my routing and account number but i still had my card connected to my apple pay which I eventually stopped using because i was getting paid but most time my card on apple pay was declined because i was still being scammed out my money. Ive tried ordering new cards several time before I completely stopped using chime however the same thing was happening with each card and chime couldnt figure out how to stop it. \n", + "A few days ago i tried to create a new chime bank account because i had completely forgotten about my old scammed chime account but that app prompted me to sign into my old account Chime told me that they would do a complete investigation and let me know of the results. \n", + "However, on Sunday XX/XX/XXXX at XXXX i got an email from chime stating Hello XXXX XXXX XXXX This letter is to inform you that we have made a final determination regarding the claim referenced above. \n", + "Based on our investigation, we have concluded no error occurred. Therefore, no funds will be credited to your account and this claim is considered closed. \n", "\n", - "Furthermore, due to the unparalleled absolute deceptive malfeasance on the part of \" XXXX '' and these debt XXXX, I am considering approaching media outlets with my story. Consumers can not and should not be ripped of this way and their credit tarnished, while a corrupt telecommunications company and their debt collecting cronies attempt to charge them for several months of internet they never had. \n", + "I emailed them back for the documentation on how they did the dispute and verified the information was inaccurate. I also asked how is it possible that a investigation for 20+ transactions had been completed in less than 1 day. \n", + "I truly believe chime did not do any investigation at all and that they lied about my investigation/dispute They have been unable to provide me with the documents and dispute information. In fact, they said id have to wait 10+ business days to receive that information in mail because they arent going to email it to me I found this very unfortunate. \n", "\n", - "This is fraud, it is illegal, and it needs to stop. And I wish to be exonerated from this debt as I was originally led to believe!!! \n", + "Here are my reference numbers for my disputes XXXX XXXX\n", + "3. My sister and I attempted to close our aging father 's professional account at Wells Fargo. My sister worked closely with the local branch and followed their directives. But, even after 6 months the bank continued to reject the paperwork presented. Anticipating our father 's further decline, we hired an estate attorney to help us close the account. Even after appointing me as an officer of my dad 's company and presenting new documentation which followed the bank 's directive, the bank again refused to move the money to my mother and to close the account. The entire time the balance of the account was depleted through bank fees from around {$1800.00} to around {$1000.00}. In the end, Wells Fargo refunded the entire original balance of around {$1800.00} plus some a \" consumer satisfaction credit '' and transferred the funds to my mother 's account.\n", + "4. On XXXX XX/XX/2020 a sale of three Tahitian pearl necklaces was made by my online shop. This amounted to approximately {$2800.00}. Some of the funds were withdrawn by me leaving a total of {$220000.00} in the Paypal account. \n", "\n", - "Finally, if \" XXXX '' are part of any class action lawsuits involving this behaviour ( and I'm sure they are ), then I wish to testify on the behalf on any government, individual, and/or private institutions as to the corrput nature of entities such as \" XXXX '' and their debt collectors, and hereby consent to providing all the following statements, including all attachments herein, and any testimony they want me to give as evidence. \n", + "Suddenly the balance was frozen for 180 days by Paypal. A telephone call to their customer service on about XXXX XXXX resulted in a rude and abrupt lady telling me that Paypal was parting ways with me. I was given no reasonable explanation why the account was limited or the funds frozen other than to infer that I was busy with fraudulent activity. The rude person refused to give me more details. \n", "\n", - "-XXXX XXXX XXXX XXXX XXXX\n", - "3. XXXX called on XX/XX/XXXX at about XXXXXXXX XXXX claiming to be from Sherloq financial, about collecting medical debt from XXXX, he was XXXX and XXXX and said there were four other accounts but did not specify which or how much. I have been contacted by my insurance that I have paid everything in relation to this. I have talked to my doctor and my endocrinologist and they said I don't owe anything either. ( I am XXXX and have XXXX and XXXX that pays for my doctor visits. ) I feel that they are just trying to collect money they are not owed and its predatory.\n", - "4. While moving out of my long time residence in XXXX, CA I began the process to cut off my services in XXXX of XXXX which included the phone, internet and XXXX, which were all included in a single bill. Initially the final date I relayed to XXXX XXXX XXXX was the XXXX of XXXX but because of delays in the move was extended to XX/XX/XXXX. Because XXXX ended up mistakenly cutting off the satellite service on the XXXX I had to call them directly to extend it to the XXXX. I left the house for the last time on XXXX XX/XX/XXXX and turn in all the equipment as required to the local XXXX office. Although I assumed all the services were ended properly I continued to get bills from XXXX ( not from XXXX XXXX XXXX ) so I called several times to rectify the mistake and finally sent a detailed escalation letter to them in XX/XX/XXXX. I felt at this point they finally realized their mistake and closed the bill but in XXXX of XXXX I then received a collection notice from Afni, Inc. for the disputed amount. I recently forwarded them a dispute letter along with other pertinent details of the situation. I have no idea why XXXX is unable to verify the fact I no longer lived at the XXXX residence, nor retained any of the receivers or remotes after the XXXX of XX/XX/XXXX. This should be an easy task on their end especially since I went above and beyond due diligence to work with them to correct this.\n", - "5. Merchants and Medical Credit began reporting on a debt they had acquired on XXXX XXXX 2014 and never sent written notice despite it being required under section 806 of the FDCPA. For 3 years they have been holding my financial life hostage and only recently came to my attention. Despite many disputes with the big three credit reporting agencies section 806 has been ignored and they have continued to break and ignore the proper procedures set forth by the FDCPA.\n", - "comment list 2:\n", - "1. I have a PayPal account and a PayPal credit card and a XXXX XXXX Checking account. \n", - "If I use PayPal, or the PayPal credit card the charges are then debited from my XXXX XXXX Checking account.. \n", + "I submitted all the details/documents they requested from then on. My appeals were refused, On XXXX XX/XX/2020 the 180 frozen days expired. I was requested by Paypal to submit all my personal details/documents again. I did. I have the XXXX XXXX XXXX XXXX ID Document. It is perfectly legal and valid in XXXX XXXX as is the new XXXX XXXXXXXX which is now being issued. But Paypal is not accepting my ID Document. So my funds are not being released.They send computer generated emails which offer no explanation as to why my ID document is not being accepted or any solution to the problem. \n", "\n", - "Recently there were two fraudulent and unauthorized charges I was alerted to by PayPal.\n", + "This matter is most frustrating and I'm sure not in line with any financial practice.\n", + "5. On XX/XX/XXXX I received a text from Chase showing -- -- -- -- - Chase Fraud : Did you attempt a {$1700.00} withdrawal on XX/XX/XXXX with card XXXX? \n", + "replay yes or no. Msg & data rates may apply. \n", + "-- -- -- -- - Then I replied no, Then chase sent a text they will close my account, give them a call. \n", "\n", - "One was a debit from XXXX for {$240.00}. I contacted XXXX and they said there was no record for that amount and date for purchases or charges anywhere on XXXX. They said it was most likely fraudulent and I never authorized it. \n", + "So I called chase to report, they are saying because it is pending transaction I have to wait until pending is gone, 2 days later they accepted my claim. \n", "\n", - "The other was from XXXX XXXX for {$50.00}. I did make political donations to politicians during the election cycle and I noted each in my checking account. I STOPPED making any further contributions after the last elections in Georgia. This charge was not one I had authorized and it was dated AFTER the last election and was not one of the ones I had checked against my checking account. \n", + "Today XX/XX/XXXX they refused to credit my money {$1700.00} because my pin number and debit card were used. So I told them I never received card. \n", + "Still their answer is same. \n", "\n", - "I disputed both with XXXX XXXX on my checking account and they researched both of them and determined they were fraudulent and XXXX XXXX noted in writing \" We have completed our research of your inquiry and returned the charges unpaid. As a result no money was deducted from your account '' I have filed two claims disputing both charges to PayPal and each time they have denied my fraudulent/unauthorized claims and I even spoke to PayPal people several times and quoted XXXX XXXX to them and then filed a dispute with them on their denial. \n", + "Then I asked what should I do? file small claim against chase? go to police office? \n", + "They told me I can go to police office to file a claim. \n", "\n", - "They are still denying my dispute and claiming that I owe them {$290.00} for both fraudulent charges. Please help me get this resolved. They keep sending me notices and phone calls. I should not have to pay them since XXXX XXXX returned them as unpaid and determined they were fraudulent and even XXXX says there was no purchase or credit so it was fraudulent and unauthorized.\n", - "2. Banked with truist for almost XXXX months now and never had an issue until i decided to start funding my account and using my debit card to pay my bills, they locked my debit card which is fine, called to have it unblocked no problem and they end up locking it again but this time they are saying i have to come into a branch to do so which IS a problem. Truist bank is nowhere near me in my state, its an out of state bank so thats literally not an option. Bank locked my online banking with money still in my account lol, i tried an ACH transfer and set up bill pay payments and i tried to log in just to find out my account is restricted for security reasons. This has been XXXX of the worst banking experiences i've ever had and im not being treated like a customer at all. its almost like truist isnt allowing me to use my money the way i want or access my funds properly. Ive had no problem up until i made a large deposit into my account and started using those funds. \n", + "I will go to police office after my work. \n", "\n", - "i have no problenm verifying myself any other way but going out of my current state just to visit truist bank is not an option.\n", - "3. Navy Exchange ( NEX ), the \" XXXX '' onboard US XXXX bases, offers currency exchange for personnel stationed overseas ( in XXXX ) to pay their off-base rent. However, the exchange rate offered is always 2-3 % less than the Bank Rate for US dollar to XXXX XXXX exchange. \n", + "Before I go to police office, I am asking your help about this situation. \n", "\n", - "To offset this, the Navy Exchange provides a {$10.00} gift card for use at the NEX, for each month paid. However, this is inequitable because the gift card is always for the same amount, regardless of the monthly rent amount ... so a single military member with an $ XXXX/month ( equivalent ) rent payment derives more proportional benefit from this {$10.00} gift card than a military family whose rent could be closer to $ XXXX ( equivalent ).\n", - "4. In XX/XX/XXXX, based on a friend 's recommendation, I visited a vacation rental home website to rent her neighbor 's property in XXXX, California, USA. The vacation rental home website is called : XXXX. I used the right side of the website called \" Contact Owner '' to reach out to the owner. I received an email from the owner, XXXX, who let me know that the property was only available for 26 days at a time, as such, I did not move forward. I also received another email from the email address : XXXX. The contact was named XXXX XXXX who asked for desired check-in/out dates, number of bedrooms, and preferred location. He also asked about preferred budget and stated that he manages a lot of properties and could offer an attractive discount. I responded with my preferences and he sent an offer for a vacation rental property. He included a link to view the property via XXXX. I asked for the address of the property and he provided the following address : XXXX XXXX XXXX XXXX, California. He let me know that 50 % of the total was due as a deposit and the remaining amount was due 30 days prior to the arrival date. He also let me know that the owners of the property live in XXXX and require payment with the company XXXX ( formerly TransferWise ). I recognize XXXX as I have used the company in the past and already had an account. Therefore, on XX/XX/XXXX, I sent the money through XXXX to the stated \" Owners '' of the property : XXXX XXXX and XXXX XXXX. \n", - "Eight days later, I realized that the transaction was a scam after Googling the email address ( XXXX ). There were at least 20 reviewers with similar experiences that claimed this entity was a scammer for rental properties. At this point ( on XX/XX/XXXX ), I reached back out to XXXX via email to ask for the money back, and he agreed to send the money via check to my mailing address. However, the check did not arrive. I let him know that the money did not arrive and asked him to reverse the XXXX transaction. However, I did not receive a response from XXXX. After this, I contacted my bank. My bank provided a temporary reimbursement while an investigation was performed. After the investigation was complete 60 days later ( XX/XX/XXXX ), the reimbursement was removed since my bank determined that XXXX is the company responsible in this matter. As such, I am looking to get a refund for the amount with XXXX.\n", - "5. I can not withdraw money or pay my rent from my Way to go card from Florida reemployment. It keeps declining me. It was working fine in XXXX, I went to pay my rent for XXXX, and it declined ; I went to an atm again declined. So I ordered a new card and paid expedited shipping ; thinking this one was damaged, I activated it, and it again declined me. There is absolutely no way to contact anyone. All they have is an automatic response which doesn't provide any help\n", + "Please help me.\n", "\n" ] } @@ -1102,7 +1112,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 16, "metadata": { "id": "mL5P0_3X04dE" }, @@ -1110,7 +1120,7 @@ { "data": { "text/html": [ - "Query job 48da679e-d991-4af6-939f-8c45b3a262d8 is DONE. 0 Bytes processed. Open Job" + "Query job d3965d90-8af9-46cb-9129-40e1d2866efe is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1128,7 +1138,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "metadata": { "id": "ICWHsqAW1FNk" }, @@ -1140,7 +1150,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 18, "metadata": { "id": "gB7e1LXU1pst" }, @@ -1148,7 +1158,7 @@ { "data": { "text/html": [ - "Query job 8877d0e9-a41e-4344-8dea-bf57c93a505e is DONE. 0 Bytes processed. Open Job" + "Query job 29a26018-027a-4c70-a795-841b5ace87d6 is DONE. 0 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1160,7 +1170,7 @@ { "data": { "text/html": [ - "Query job fa3de153-d6b8-421f-84f6-69e401a36cc8 is DONE. 0 Bytes processed. Open Job" + "Query job 3abcc8cd-fa9f-4a93-b6be-6e22c8cdaceb is DONE. 8 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1172,7 +1182,7 @@ { "data": { "text/html": [ - "Query job 749fbc0b-5da2-4089-ac80-d7a2ac8325f2 is DONE. 0 Bytes processed. Open Job" + "Query job ab5dfd41-98cb-4f24-a9c7-11399fcb2e47 is DONE. 2 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1184,7 +1194,7 @@ { "data": { "text/html": [ - "Query job 6a8c8c0c-894f-41f1-a20f-adfb67349281 is DONE. 0 Bytes processed. Open Job" + "Query job c6c7bce4-81a0-4c4d-a515-2d5dfffc08a2 is DONE. 299 Bytes processed. Open Job" ], "text/plain": [ "" @@ -1196,10 +1206,10 @@ { "data": { "text/plain": [ - "' The most obvious difference between the two lists of comments is the nature of the issues being raised.\\n\\n**Comment list 1 primarily focuses on disputes related to debt collection practices.** \\n\\n- Commenters express concerns about receiving debt collection notices for debts they believe they do not owe, lack of supporting documentation, and the transfer of debt between debt collection agencies without proper resolution. \\n\\n- They highlight the impact on their credit scores and the frustration of dealing with misleading or deceptive practices.\\n\\n\\n**Comment list 2, on the other hand, covers a wider range of issues related to financial services.** \\n\\n- It includes complaints about fraudulent charges'" + "'The most obvious difference between the two lists of comments is their subject matter. Comment list 1 primarily deals with issues related to credit reporting and identity theft, while comment list 2 focuses on issues related to bank accounts, fraudulent transactions, and customer service.'" ] }, - "execution_count": 19, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -1250,7 +1260,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.11.1" } }, "nbformat": 4, diff --git a/notebooks/generative_ai/bq_dataframes_ml_drug_name_generation.ipynb b/notebooks/generative_ai/bq_dataframes_ml_drug_name_generation.ipynb index 8c0b1b0038..32e6cb7924 100644 --- a/notebooks/generative_ai/bq_dataframes_ml_drug_name_generation.ipynb +++ b/notebooks/generative_ai/bq_dataframes_ml_drug_name_generation.ipynb @@ -371,7 +371,14 @@ }, "outputs": [], "source": [ + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", "bpd.options.bigquery.project = PROJECT_ID\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", "bpd.options.bigquery.location = LOCATION" ] }, diff --git a/notebooks/getting_started/getting_started_bq_dataframes.ipynb b/notebooks/getting_started/getting_started_bq_dataframes.ipynb index a9b6aefe30..b59ccbb8ac 100644 --- a/notebooks/getting_started/getting_started_bq_dataframes.ipynb +++ b/notebooks/getting_started/getting_started_bq_dataframes.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "id": "ur8xi4C7S06n" }, @@ -145,11 +145,122 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "id": "mfPoOwPLGpSr" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: bigframes in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (0.25.0)\n", + "Requirement already satisfied: cloudpickle>=2.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (3.0.0)\n", + "Requirement already satisfied: fsspec>=2023.3.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2024.2.0)\n", + "Requirement already satisfied: gcsfs>=2023.3.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2024.2.0)\n", + "Requirement already satisfied: geopandas>=0.12.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (0.14.3)\n", + "Requirement already satisfied: google-auth<3.0dev,>=2.15.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2.28.2)\n", + "Requirement already satisfied: google-cloud-bigquery>=3.10.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (3.19.0)\n", + "Requirement already satisfied: google-cloud-functions>=1.12.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (1.16.3)\n", + "Requirement already satisfied: google-cloud-bigquery-connection>=1.12.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (1.15.3)\n", + "Requirement already satisfied: google-cloud-iam>=2.12.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2.14.3)\n", + "Requirement already satisfied: google-cloud-resource-manager>=1.10.3 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (1.12.3)\n", + "Requirement already satisfied: google-cloud-storage>=2.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2.15.0)\n", + "Requirement already satisfied: ibis-framework<9.0.0dev,>=8.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (8.0.0)\n", + "Requirement already satisfied: pandas<2.1.4,>=1.5.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2.1.3)\n", + "Requirement already satisfied: pydata-google-auth>=1.8.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (1.8.2)\n", + "Requirement already satisfied: requests>=2.27.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2.31.0)\n", + "Requirement already satisfied: scikit-learn>=1.2.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (1.4.1.post1)\n", + "Requirement already satisfied: sqlalchemy<3.0dev,>=1.4 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (2.0.28)\n", + "Requirement already satisfied: sqlglot<=20.11,>=20.8.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (20.11.0)\n", + "Requirement already satisfied: tabulate>=0.9 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (0.9.0)\n", + "Requirement already satisfied: ipywidgets>=7.7.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (8.1.2)\n", + "Requirement already satisfied: humanize>=4.6.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (4.9.0)\n", + "Requirement already satisfied: matplotlib>=3.7.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from bigframes) (3.8.3)\n", + "Requirement already satisfied: aiohttp!=4.0.0a0,!=4.0.0a1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from gcsfs>=2023.3.0->bigframes) (3.9.3)\n", + "Requirement already satisfied: decorator>4.1.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from gcsfs>=2023.3.0->bigframes) (5.1.1)\n", + "Requirement already satisfied: google-auth-oauthlib in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from gcsfs>=2023.3.0->bigframes) (1.2.0)\n", + "Requirement already satisfied: fiona>=1.8.21 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from geopandas>=0.12.2->bigframes) (1.9.6)\n", + "Requirement already satisfied: packaging in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from geopandas>=0.12.2->bigframes) (24.0)\n", + "Requirement already satisfied: pyproj>=3.3.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from geopandas>=0.12.2->bigframes) (3.6.1)\n", + "Requirement already satisfied: shapely>=1.8.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from geopandas>=0.12.2->bigframes) (2.0.3)\n", + "Requirement already satisfied: cachetools<6.0,>=2.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-auth<3.0dev,>=2.15.0->bigframes) (5.3.3)\n", + "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-auth<3.0dev,>=2.15.0->bigframes) (0.3.0)\n", + "Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-auth<3.0dev,>=2.15.0->bigframes) (4.9)\n", + "Requirement already satisfied: google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-bigquery>=3.10.0->google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (2.17.1)\n", + "Requirement already satisfied: google-cloud-core<3.0.0dev,>=1.6.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery>=3.10.0->google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (2.4.1)\n", + "Requirement already satisfied: google-resumable-media<3.0dev,>=0.6.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery>=3.10.0->google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (2.7.0)\n", + "Requirement already satisfied: python-dateutil<3.0dev,>=2.7.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery>=3.10.0->google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (2.9.0.post0)\n", + "Requirement already satisfied: proto-plus<2.0.0dev,>=1.22.3 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery-connection>=1.12.0->bigframes) (1.23.0)\n", + "Requirement already satisfied: protobuf!=3.20.0,!=3.20.1,!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.19.5 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery-connection>=1.12.0->bigframes) (4.25.3)\n", + "Requirement already satisfied: grpc-google-iam-v1<1.0.0dev,>=0.12.4 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery-connection>=1.12.0->bigframes) (0.13.0)\n", + "Requirement already satisfied: google-cloud-bigquery-storage<3.0.0dev,>=2.6.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (2.24.0)\n", + "Requirement already satisfied: grpcio<2.0dev,>=1.47.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (1.62.1)\n", + "Requirement already satisfied: pyarrow>=3.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (15.0.1)\n", + "Requirement already satisfied: db-dtypes<2.0.0dev,>=0.3.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (1.2.0)\n", + "Requirement already satisfied: google-crc32c<2.0dev,>=1.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-cloud-storage>=2.0.0->bigframes) (1.5.0)\n", + "Requirement already satisfied: atpublic<5,>=2.3 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (4.0)\n", + "Requirement already satisfied: bidict<1,>=0.22.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (0.23.1)\n", + "Requirement already satisfied: multipledispatch<2,>=0.6 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (1.0.0)\n", + "Requirement already satisfied: numpy<2,>=1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (1.26.4)\n", + "Requirement already satisfied: parsy<3,>=2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (2.1)\n", + "Requirement already satisfied: pyarrow-hotfix<1,>=0.4 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (0.6)\n", + "Requirement already satisfied: pytz>=2022.7 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (2024.1)\n", + "Requirement already satisfied: rich<14,>=12.4.4 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (13.7.1)\n", + "Requirement already satisfied: toolz<1,>=0.11 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (0.12.1)\n", + "Requirement already satisfied: typing-extensions<5,>=4.3.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (4.10.0)\n", + "Requirement already satisfied: comm>=0.1.3 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipywidgets>=7.7.1->bigframes) (0.2.2)\n", + "Requirement already satisfied: ipython>=6.1.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipywidgets>=7.7.1->bigframes) (8.22.2)\n", + "Requirement already satisfied: traitlets>=4.3.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipywidgets>=7.7.1->bigframes) (5.14.2)\n", + "Requirement already satisfied: widgetsnbextension~=4.0.10 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipywidgets>=7.7.1->bigframes) (4.0.10)\n", + "Requirement already satisfied: jupyterlab-widgets~=3.0.10 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipywidgets>=7.7.1->bigframes) (3.0.10)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from matplotlib>=3.7.1->bigframes) (1.2.0)\n", + "Requirement already satisfied: cycler>=0.10 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from matplotlib>=3.7.1->bigframes) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from matplotlib>=3.7.1->bigframes) (4.49.0)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from matplotlib>=3.7.1->bigframes) (1.4.5)\n", + "Requirement already satisfied: pillow>=8 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from matplotlib>=3.7.1->bigframes) (10.2.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from matplotlib>=3.7.1->bigframes) (3.1.2)\n", + "Requirement already satisfied: tzdata>=2022.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from pandas<2.1.4,>=1.5.0->bigframes) (2024.1)\n", + "Requirement already satisfied: setuptools in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from pydata-google-auth>=1.8.2->bigframes) (69.2.0)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from requests>=2.27.1->bigframes) (3.3.2)\n", + "Requirement already satisfied: idna<4,>=2.5 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from requests>=2.27.1->bigframes) (3.6)\n", + "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from requests>=2.27.1->bigframes) (2.2.1)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from requests>=2.27.1->bigframes) (2024.2.2)\n", + "Requirement already satisfied: scipy>=1.6.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from scikit-learn>=1.2.2->bigframes) (1.12.0)\n", + "Requirement already satisfied: joblib>=1.2.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from scikit-learn>=1.2.2->bigframes) (1.3.2)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from scikit-learn>=1.2.2->bigframes) (3.3.0)\n", + "Requirement already satisfied: greenlet!=0.4.17 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from sqlalchemy<3.0dev,>=1.4->bigframes) (3.0.3)\n", + "Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->gcsfs>=2023.3.0->bigframes) (1.3.1)\n", + "Requirement already satisfied: attrs>=17.3.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->gcsfs>=2023.3.0->bigframes) (23.2.0)\n", + "Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->gcsfs>=2023.3.0->bigframes) (1.4.1)\n", + "Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->gcsfs>=2023.3.0->bigframes) (6.0.5)\n", + "Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from aiohttp!=4.0.0a0,!=4.0.0a1->gcsfs>=2023.3.0->bigframes) (1.9.4)\n", + "Requirement already satisfied: click~=8.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from fiona>=1.8.21->geopandas>=0.12.2->bigframes) (8.1.7)\n", + "Requirement already satisfied: click-plugins>=1.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from fiona>=1.8.21->geopandas>=0.12.2->bigframes) (1.1.1)\n", + "Requirement already satisfied: cligj>=0.5 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from fiona>=1.8.21->geopandas>=0.12.2->bigframes) (0.7.2)\n", + "Requirement already satisfied: six in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from fiona>=1.8.21->geopandas>=0.12.2->bigframes) (1.16.0)\n", + "Requirement already satisfied: googleapis-common-protos<2.0.dev0,>=1.56.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-api-core!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-bigquery>=3.10.0->google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (1.63.0)\n", + "Requirement already satisfied: grpcio-status<2.0.dev0,>=1.33.2 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-api-core[grpc]!=2.0.*,!=2.1.*,!=2.10.*,!=2.2.*,!=2.3.*,!=2.4.*,!=2.5.*,!=2.6.*,!=2.7.*,!=2.8.*,!=2.9.*,<3.0.0dev,>=1.34.1->google-cloud-bigquery>=3.10.0->google-cloud-bigquery[bqstorage,pandas]>=3.10.0->bigframes) (1.62.1)\n", + "Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from google-auth-oauthlib->gcsfs>=2023.3.0->bigframes) (1.4.0)\n", + "Requirement already satisfied: jedi>=0.16 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.19.1)\n", + "Requirement already satisfied: matplotlib-inline in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.1.6)\n", + "Requirement already satisfied: prompt-toolkit<3.1.0,>=3.0.41 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (3.0.43)\n", + "Requirement already satisfied: pygments>=2.4.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (2.17.2)\n", + "Requirement already satisfied: stack-data in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.6.3)\n", + "Requirement already satisfied: pexpect>4.3 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (4.9.0)\n", + "Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from pyasn1-modules>=0.2.1->google-auth<3.0dev,>=2.15.0->bigframes) (0.5.1)\n", + "Requirement already satisfied: markdown-it-py>=2.2.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from rich<14,>=12.4.4->ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (3.0.0)\n", + "Requirement already satisfied: parso<0.9.0,>=0.8.3 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from jedi>=0.16->ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.8.3)\n", + "Requirement already satisfied: mdurl~=0.1 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from markdown-it-py>=2.2.0->rich<14,>=12.4.4->ibis-framework<9.0.0dev,>=8.0.0->ibis-framework[bigquery]<9.0.0dev,>=8.0.0->bigframes) (0.1.2)\n", + "Requirement already satisfied: ptyprocess>=0.5 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from pexpect>4.3->ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.7.0)\n", + "Requirement already satisfied: wcwidth in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from prompt-toolkit<3.1.0,>=3.0.41->ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.2.13)\n", + "Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib->gcsfs>=2023.3.0->bigframes) (3.2.2)\n", + "Requirement already satisfied: executing>=1.2.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from stack-data->ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (2.0.1)\n", + "Requirement already satisfied: asttokens>=2.1.0 in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from stack-data->ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (2.4.1)\n", + "Requirement already satisfied: pure-eval in /usr/local/google/home/swast/envs/bigframes/lib/python3.11/site-packages (from stack-data->ipython>=6.1.0->ipywidgets>=7.7.1->bigframes) (0.2.2)\n" + ] + } + ], "source": [ "!pip install bigframes" ] @@ -167,7 +278,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "id": "f200f10a1da3" }, @@ -234,11 +345,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "id": "oM1iC_MfAts1" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Updated property [core/project].\n", + "\n", + "\n", + "To take a quick anonymous survey, run:\n", + " $ gcloud survey\n", + "\n" + ] + } + ], "source": [ "PROJECT_ID = \"\" # @param {type:\"string\"}\n", "\n", @@ -259,7 +383,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "eF-Twtc4XGem" }, @@ -303,7 +427,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "id": "254614fa0c46" }, @@ -325,7 +449,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "id": "603adbbf0532" }, @@ -346,13 +470,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "id": "PyQmSRbKA8r-" }, "outputs": [], "source": [ - "import bigframes.pandas as bf" + "import bigframes.pandas as bpd" ] }, { @@ -367,14 +491,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "id": "NPPMuw2PXGeo" }, "outputs": [], "source": [ - "bf.options.bigquery.project = PROJECT_ID\n", - "bf.options.bigquery.location = REGION" + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", + "bpd.options.bigquery.project = PROJECT_ID\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", + "bpd.options.bigquery.location = REGION" ] }, { @@ -383,7 +514,7 @@ "id": "pDfrKwMKE_dK" }, "source": [ - "If you want to reset the location of the created DataFrame or Series objects, reset the session by executing `bf.close_session()`. After that, you can reuse `bf.options.bigquery.location` to specify another location." + "If you want to reset the location of the created DataFrame or Series objects, reset the session by executing `bpd.close_session()`. After that, you can reuse `bpd.options.bigquery.location` to specify another location." ] }, { @@ -421,13 +552,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "id": "Vyex9BQI-BNa" }, "outputs": [], "source": [ - "# bq_df_sample = bf.read_gbq(\"bigquery-samples.wikipedia_pageviews.200809h\")" + "# bq_df_sample = bpd.read_gbq(\"bigquery-samples.wikipedia_pageviews.200809h\")" ] }, { @@ -452,7 +583,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "id": "XfGq5apK-D_e" }, @@ -526,7 +657,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "id": "SvyXzkRl783u" }, @@ -552,7 +683,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "id": "3QHQYlnoBLpt" }, @@ -578,15 +709,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "id": "EDAaIwHpQCDZ" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Load job d578c399-e2e5-4f6b-ba28-59d0686a91e7 is DONE. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# If order is not important, use the \"bigquery\" engine to\n", "# allow BigQuery DataFrames to read directly from GCS.\n", - "df_from_local = bf.read_csv(fn, engine=\"bigquery\")" + "df_from_local = bpd.read_csv(fn, engine=\"bigquery\")" ] }, { @@ -600,11 +744,156 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "id": "_gPD0Zn1Stdb" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job f50a129b-4a51-4c21-b155-ab1e85c1403e is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job b0d65008-f9f1-4fec-8620-42f307390049 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job a83d72e8-0cb8-44e9-ad0b-6fe3726ed1e9 is DONE. 501 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
speciesislandculmen_length_mmculmen_depth_mmflipper_length_mmbody_mass_gsex
0Gentoo penguin (Pygoscelis papua)Biscoe50.515.92255400MALE
1Gentoo penguin (Pygoscelis papua)Biscoe45.114.52155000FEMALE
2Adelie Penguin (Pygoscelis adeliae)Torgersen41.418.52023875MALE
3Adelie Penguin (Pygoscelis adeliae)Torgersen38.617.01882900FEMALE
4Gentoo penguin (Pygoscelis papua)Biscoe46.514.82175200FEMALE
\n", + "

5 rows × 7 columns

\n", + "
[5 rows x 7 columns in total]" + ], + "text/plain": [ + " species island culmen_length_mm \\\n", + "0 Gentoo penguin (Pygoscelis papua) Biscoe 50.5 \n", + "1 Gentoo penguin (Pygoscelis papua) Biscoe 45.1 \n", + "2 Adelie Penguin (Pygoscelis adeliae) Torgersen 41.4 \n", + "3 Adelie Penguin (Pygoscelis adeliae) Torgersen 38.6 \n", + "4 Gentoo penguin (Pygoscelis papua) Biscoe 46.5 \n", + "\n", + " culmen_depth_mm flipper_length_mm body_mass_g sex \n", + "0 15.9 225 5400 MALE \n", + "1 14.5 215 5000 FEMALE \n", + "2 18.5 202 3875 MALE \n", + "3 17.0 188 2900 FEMALE \n", + "4 14.8 217 5200 FEMALE \n", + "\n", + "[5 rows x 7 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df_from_local.head()" ] @@ -631,11 +920,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "id": "ZSP7gt13QrQt" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dataset birds created.\n" + ] + } + ], "source": [ "DATASET_ID = \"birds\" # @param {type:\"string\"}\n", "\n", @@ -658,11 +955,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "id": "oP1NIAmUBjop" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 49702108-948c-4a60-a66e-16a3ed6bc102 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "'swast-scratch.birds.penguins'" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df_from_local.to_gbq(\n", " PROJECT_ID + \".\" + DATASET_ID + \".penguins\",\n", @@ -691,14 +1011,159 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "id": "IBuo-d6dWfsA" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 05a6288d-3774-41d0-9884-6bbb5af28942 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 45383ce0-0ca1-4c16-9832-739e9d325673 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 2f672140-ddc6-43b6-b79a-318f29bb9239 is DONE. 501 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
speciesislandculmen_length_mmculmen_depth_mmflipper_length_mmbody_mass_gsex
0Gentoo penguin (Pygoscelis papua)Biscoe50.515.92255400MALE
1Gentoo penguin (Pygoscelis papua)Biscoe45.114.52155000FEMALE
2Adelie Penguin (Pygoscelis adeliae)Torgersen41.418.52023875MALE
3Adelie Penguin (Pygoscelis adeliae)Torgersen38.617.01882900FEMALE
4Gentoo penguin (Pygoscelis papua)Biscoe46.514.82175200FEMALE
\n", + "

5 rows × 7 columns

\n", + "
[5 rows x 7 columns in total]" + ], + "text/plain": [ + " species island culmen_length_mm \\\n", + "0 Gentoo penguin (Pygoscelis papua) Biscoe 50.5 \n", + "1 Gentoo penguin (Pygoscelis papua) Biscoe 45.1 \n", + "2 Adelie Penguin (Pygoscelis adeliae) Torgersen 41.4 \n", + "3 Adelie Penguin (Pygoscelis adeliae) Torgersen 38.6 \n", + "4 Gentoo penguin (Pygoscelis papua) Biscoe 46.5 \n", + "\n", + " culmen_depth_mm flipper_length_mm body_mass_g sex \n", + "0 15.9 225 5400 MALE \n", + "1 14.5 215 5000 FEMALE \n", + "2 18.5 202 3875 MALE \n", + "3 17.0 188 2900 FEMALE \n", + "4 14.8 217 5200 FEMALE \n", + "\n", + "[5 rows x 7 columns]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "query_or_table = f\"\"\"{PROJECT_ID}.{DATASET_ID}.penguins\"\"\"\n", - "bq_df = bf.read_gbq(query_or_table)\n", + "bq_df = bpd.read_gbq(query_or_table)\n", "bq_df.head()" ] }, @@ -733,11 +1198,68 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "id": "6i6HkFJZa8na" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 5c454fa1-a01b-4e95-b947-6f02554a8461 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 2cffe5c7-c0c6-4495-ad67-1f5fb55654fd is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 96b4dead-f526-4be3-b24d-5d7aec99eeeb is DONE. 240 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "0 5400\n", + "1 5000\n", + "2 3875\n", + "3 2900\n", + "4 5200\n", + "5 3725\n", + "6 2975\n", + "7 4150\n", + "8 5300\n", + "9 4150\n", + "Name: body_mass_g, dtype: Int64" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "bq_df[\"body_mass_g\"].head(10)" ] @@ -753,11 +1275,31 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "id": "YKwCW7Nsavap" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 635d000c-14ca-4ecf-bc32-1527821cba28 is DONE. 2.7 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "average_body_mass: 4201.754385964917\n" + ] + } + ], "source": [ "average_body_mass = bq_df[\"body_mass_g\"].mean()\n", "print(f\"average_body_mass: {average_body_mass}\")" @@ -774,11 +1316,108 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "id": "4PyKMR61-Mjy" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job d22d8e48-26a0-4cfb-83fc-3e52b834f487 is DONE. 15.6 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 64fff5f3-7106-4003-9241-a9b09afed781 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job c3d566cc-bed1-4361-96ef-f06956982916 is DONE. 163 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
body_mass_g
species
Adelie Penguin (Pygoscelis adeliae)3700.662252
Chinstrap penguin (Pygoscelis antarctica)3733.088235
Gentoo penguin (Pygoscelis papua)5076.01626
\n", + "

3 rows × 1 columns

\n", + "
[3 rows x 1 columns in total]" + ], + "text/plain": [ + " body_mass_g\n", + "species \n", + "Adelie Penguin (Pygoscelis adeliae) 3700.662252\n", + "Chinstrap penguin (Pygoscelis antarctica) 3733.088235\n", + "Gentoo penguin (Pygoscelis papua) 5076.01626\n", + "\n", + "[3 rows x 1 columns]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "bq_df[[\"species\", \"body_mass_g\"]].groupby(by=bq_df[\"species\"]).mean(numeric_only=True).head()" ] @@ -820,13 +1459,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "id": "rSWTOG-vb2Fc" }, "outputs": [], "source": [ - "@bf.remote_function([float], str)\n", + "@bpd.remote_function([float], str)\n", "def get_bucket(num):\n", " if not num: return \"NA\"\n", " boundary = 4000\n", @@ -846,11 +1485,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "id": "6ejPXoyEQpWE" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cloud Function Name projects/swast-scratch/locations/us-central1/functions/bigframes-71a76285da23f28be467ed16826f7276\n", + "Remote Function Name swast-scratch._63cfa399614a54153cc386c27d6c0c6fdb249f9e.bigframes_71a76285da23f28be467ed16826f7276\n" + ] + } + ], "source": [ "CLOUD_FUNCTION_NAME = format(get_bucket.bigframes_cloud_function)\n", "print(\"Cloud Function Name \" + CLOUD_FUNCTION_NAME)\n", @@ -869,11 +1517,161 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "id": "NxSd9WZFcIji" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 9925acd1-d1e7-4746-90d6-4ce8c2ca30a8 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 2f10b5cd-80bb-4697-9c61-b7848ce15c81 is DONE. 39.6 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 29266b33-3945-44c0-943b-3d6365b9cc7a is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 19ecf156-8940-4c02-b20e-3e52e18c7239 is DONE. 396 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
body_mass_gbody_mass_bucket
05400at_or_above_4000
15000at_or_above_4000
23875below_4000
32900below_4000
45200at_or_above_4000
53725below_4000
62975below_4000
74150at_or_above_4000
85300at_or_above_4000
94150at_or_above_4000
\n", + "

10 rows × 2 columns

\n", + "
[10 rows x 2 columns in total]" + ], + "text/plain": [ + " body_mass_g body_mass_bucket\n", + "0 5400 at_or_above_4000\n", + "1 5000 at_or_above_4000\n", + "2 3875 below_4000\n", + "3 2900 below_4000\n", + "4 5200 at_or_above_4000\n", + "5 3725 below_4000\n", + "6 2975 below_4000\n", + "7 4150 at_or_above_4000\n", + "8 5300 at_or_above_4000\n", + "9 4150 at_or_above_4000\n", + "\n", + "[10 rows x 2 columns]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "bq_df = bq_df.assign(body_mass_bucket=bq_df['body_mass_g'].apply(get_bucket))\n", "bq_df[['body_mass_g', 'body_mass_bucket']].head(10)" @@ -908,7 +1706,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "id": "sx_vKniMq9ZX" }, @@ -925,7 +1723,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "id": "_dTCXvCxtPw9" }, @@ -941,7 +1739,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "id": "EDAIIfcpwNOF" }, @@ -953,7 +1751,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "id": "QwumLUKmVpuH" }, @@ -973,6 +1771,18 @@ "kernelspec": { "display_name": "Python 3", "name": "python3" + }, + "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.11.1" } }, "nbformat": 4, diff --git a/notebooks/getting_started/ml_fundamentals_bq_dataframes.ipynb b/notebooks/getting_started/ml_fundamentals_bq_dataframes.ipynb index 089c167d39..b3c965aded 100644 --- a/notebooks/getting_started/ml_fundamentals_bq_dataframes.ipynb +++ b/notebooks/getting_started/ml_fundamentals_bq_dataframes.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "id": "ur8xi4C7S06n" }, @@ -156,7 +156,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "id": "mfPoOwPLGpSr" }, @@ -211,11 +211,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "id": "oM1iC_MfAts1" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Updated property [core/project].\n" + ] + } + ], "source": [ "PROJECT_ID = \"\" # @param {type:\"string\"}\n", "\n", @@ -236,7 +244,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "id": "eF-Twtc4XGem" }, @@ -258,7 +266,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "BbMh9JHvUHAn" }, @@ -309,7 +317,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "id": "254614fa0c46" }, @@ -331,7 +339,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "id": "603adbbf0532" }, @@ -352,13 +360,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "id": "PyQmSRbKA8r-" }, "outputs": [], "source": [ - "import bigframes.pandas as bf" + "import bigframes.pandas as bpd" ] }, { @@ -373,14 +381,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "id": "NPPMuw2PXGeo" }, "outputs": [], "source": [ - "bf.options.bigquery.project = PROJECT_ID\n", - "bf.options.bigquery.location = REGION" + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", + "bpd.options.bigquery.project = PROJECT_ID\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", + "bpd.options.bigquery.location = REGION" ] }, { @@ -389,7 +404,7 @@ "id": "pDfrKwMKE_dK" }, "source": [ - "If you want to reset the location of the created DataFrame or Series objects, reset the session by executing `bf.reset_session()`. After that, you can reuse `bf.options.bigquery.location` to specify another location." + "If you want to reset the location of the created DataFrame or Series objects, reset the session by executing `bpd.reset_session()`. After that, you can reuse `bpd.options.bigquery.location` to specify another location." ] }, { @@ -405,13 +420,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "id": "d86W4hNqzZJb" }, "outputs": [], "source": [ - "df = bf.read_gbq(\"bigquery-public-data.ml_datasets.penguins\")\n", + "df = bpd.read_gbq(\"bigquery-public-data.ml_datasets.penguins\")\n", "df = df.dropna()\n", "\n", "# BigQuery DataFrames creates a default numbered index, which we can give a name\n", @@ -429,11 +444,168 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "id": "arGaUZVWkSwT" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job d3acda60-1059-4bb0-9912-ed374491c5c3 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 51c6aa1c-ff98-4805-921e-00830e125e56 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 01e2cb6d-604b-4cdd-afb0-8f515a9da951 is DONE. 501 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
speciesislandculmen_length_mmculmen_depth_mmflipper_length_mmbody_mass_gsex
penguin_id
0Gentoo penguin (Pygoscelis papua)Biscoe50.515.9225.05400.0MALE
1Gentoo penguin (Pygoscelis papua)Biscoe45.114.5215.05000.0FEMALE
2Adelie Penguin (Pygoscelis adeliae)Torgersen41.418.5202.03875.0MALE
3Adelie Penguin (Pygoscelis adeliae)Torgersen38.617.0188.02900.0FEMALE
4Gentoo penguin (Pygoscelis papua)Biscoe46.514.8217.05200.0FEMALE
\n", + "

5 rows × 7 columns

\n", + "
[5 rows x 7 columns in total]" + ], + "text/plain": [ + " species island culmen_length_mm \\\n", + "penguin_id \n", + "0 Gentoo penguin (Pygoscelis papua) Biscoe 50.5 \n", + "1 Gentoo penguin (Pygoscelis papua) Biscoe 45.1 \n", + "2 Adelie Penguin (Pygoscelis adeliae) Torgersen 41.4 \n", + "3 Adelie Penguin (Pygoscelis adeliae) Torgersen 38.6 \n", + "4 Gentoo penguin (Pygoscelis papua) Biscoe 46.5 \n", + "\n", + " culmen_depth_mm flipper_length_mm body_mass_g sex \n", + "penguin_id \n", + "0 15.9 225.0 5400.0 MALE \n", + "1 14.5 215.0 5000.0 FEMALE \n", + "2 18.5 202.0 3875.0 MALE \n", + "3 17.0 188.0 2900.0 FEMALE \n", + "4 14.8 217.0 5200.0 FEMALE \n", + "\n", + "[5 rows x 7 columns]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df.head()" ] @@ -458,7 +630,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "id": "B9mW93o9z_-L" }, @@ -482,11 +654,82 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "id": "NysWAWmvlAxB" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 7bd14e04-b3b4-4281-b5be-187f7baad62f is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 240cc7db-19ac-4bd3-8e76-a79f75ded077 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 91194fee-d9b9-4cb9-a469-e49e9d77c624 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 84c71647-956b-4385-8dce-c8bc70a917c8 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 9c94600b-2231-4d04-8e3a-fb46f8892b6a is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "X_train shape: (267, 6)\n", + "X_test shape: (67, 6)\n", + "y_train shape: (267, 1)\n", + "y_test shape: (67, 1)\n" + ] + } + ], "source": [ "from bigframes.ml.model_selection import train_test_split\n", "\n", @@ -514,11 +757,161 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "id": "f8bz1HwLlyLP" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 8ad534c1-eb49-4616-b7a6-f7d8b044b8bf is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 3793de66-fb3c-4ca4-a337-aa708c718cc5 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 66524afb-4509-4927-8902-4a72826e83c4 is DONE. 456 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
islandculmen_length_mmculmen_depth_mmflipper_length_mmsexspecies
penguin_id
188Dream51.518.7187.0MALEChinstrap penguin (Pygoscelis antarctica)
251Biscoe49.516.1224.0MALEGentoo penguin (Pygoscelis papua)
231Biscoe45.713.9214.0FEMALEGentoo penguin (Pygoscelis papua)
271Biscoe59.617.0230.0MALEGentoo penguin (Pygoscelis papua)
128Biscoe38.817.2180.0MALEAdelie Penguin (Pygoscelis adeliae)
\n", + "

5 rows × 6 columns

\n", + "
[5 rows x 6 columns in total]" + ], + "text/plain": [ + " island culmen_length_mm culmen_depth_mm flipper_length_mm \\\n", + "penguin_id \n", + "188 Dream 51.5 18.7 187.0 \n", + "251 Biscoe 49.5 16.1 224.0 \n", + "231 Biscoe 45.7 13.9 214.0 \n", + "271 Biscoe 59.6 17.0 230.0 \n", + "128 Biscoe 38.8 17.2 180.0 \n", + "\n", + " sex species \n", + "penguin_id \n", + "188 MALE Chinstrap penguin (Pygoscelis antarctica) \n", + "251 MALE Gentoo penguin (Pygoscelis papua) \n", + "231 FEMALE Gentoo penguin (Pygoscelis papua) \n", + "271 MALE Gentoo penguin (Pygoscelis papua) \n", + "128 MALE Adelie Penguin (Pygoscelis adeliae) \n", + "\n", + "[5 rows x 6 columns]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "X_test.head(5)" ] @@ -534,11 +927,118 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "id": "PflbhKGkl8v2" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 6a87fcc2-f2d0-44f5-8ab2-08f109c2b70d is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job ed8e49f8-0f4c-4ef2-bbc2-b8c5ef9fd064 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 97fea642-03aa-49fd-943e-f4efa5a87f0f is DONE. 120 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
body_mass_g
penguin_id
1883250.0
2515650.0
2314400.0
2716050.0
1283800.0
\n", + "

5 rows × 1 columns

\n", + "
[5 rows x 1 columns in total]" + ], + "text/plain": [ + " body_mass_g\n", + "penguin_id \n", + "188 3250.0\n", + "251 5650.0\n", + "231 4400.0\n", + "271 6050.0\n", + "128 3800.0\n", + "\n", + "[5 rows x 1 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "y_test.head(5)" ] @@ -579,11 +1079,337 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "id": "yhATDMR-mkdF" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job aee64759-42bb-44d6-b8c7-1c737cdd6eed is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job acb29d04-a20d-4f1c-8d90-51c7e8ac9922 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 2bd034db-7d9b-467c-be17-49bca094cceb is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 5dfb583a-1ced-4f2a-94b9-f1282263134d is DONE. 2.1 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 8fe87288-4a95-49f4-9895-7c41c1004901 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 7ebcecee-beff-402d-ac71-6384014a54da is DONE. 8.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
standard_scaled_culmen_length_mmstandard_scaled_culmen_depth_mmstandard_scaled_flipper_length_mm
penguin_id
01.20778-0.6515311.772656
2-0.4556020.6628550.100476
3-0.967412-0.095445-0.917372
40.476623-1.2076171.191028
5-1.6254540.359535-0.626559
7-0.345929-1.864810.682104
80.842202-1.5614911.409139
90.3486710.865068-0.263041
100.9335961.2189410.827511
11-1.460943-0.297658-0.771966
121.317454-0.4493181.409139
13-0.236255-1.7637040.900214
140.549739-0.297658-0.626559
160.970154-1.0054041.481842
17-1.058807-0.348211-0.190338
181.354012-1.5109371.263732
19-0.053466-1.6625971.191028
20-0.199697-1.5109370.609401
211.1529430.763962-0.190338
22-1.2050380.308982-0.699262
24-0.7846231.775028-0.699262
25-0.839461.724474-0.771966
26-0.6201130.359535-0.990076
270.330392-0.095445-0.408448
292.194842-0.0954451.990767
\n", + "

25 rows × 3 columns

\n", + "
[267 rows x 3 columns in total]" + ], + "text/plain": [ + " standard_scaled_culmen_length_mm standard_scaled_culmen_depth_mm \\\n", + "penguin_id \n", + "0 1.20778 -0.651531 \n", + "2 -0.455602 0.662855 \n", + "3 -0.967412 -0.095445 \n", + "4 0.476623 -1.207617 \n", + "5 -1.625454 0.359535 \n", + "7 -0.345929 -1.86481 \n", + "8 0.842202 -1.561491 \n", + "9 0.348671 0.865068 \n", + "10 0.933596 1.218941 \n", + "11 -1.460943 -0.297658 \n", + "12 1.317454 -0.449318 \n", + "13 -0.236255 -1.763704 \n", + "14 0.549739 -0.297658 \n", + "16 0.970154 -1.005404 \n", + "17 -1.058807 -0.348211 \n", + "18 1.354012 -1.510937 \n", + "19 -0.053466 -1.662597 \n", + "20 -0.199697 -1.510937 \n", + "21 1.152943 0.763962 \n", + "22 -1.205038 0.308982 \n", + "24 -0.784623 1.775028 \n", + "25 -0.83946 1.724474 \n", + "26 -0.620113 0.359535 \n", + "27 0.330392 -0.095445 \n", + "29 2.194842 -0.095445 \n", + "\n", + " standard_scaled_flipper_length_mm \n", + "penguin_id \n", + "0 1.772656 \n", + "2 0.100476 \n", + "3 -0.917372 \n", + "4 1.191028 \n", + "5 -0.626559 \n", + "7 0.682104 \n", + "8 1.409139 \n", + "9 -0.263041 \n", + "10 0.827511 \n", + "11 -0.771966 \n", + "12 1.409139 \n", + "13 0.900214 \n", + "14 -0.626559 \n", + "16 1.481842 \n", + "17 -0.190338 \n", + "18 1.263732 \n", + "19 1.191028 \n", + "20 0.609401 \n", + "21 -0.190338 \n", + "22 -0.699262 \n", + "24 -0.699262 \n", + "25 -0.771966 \n", + "26 -0.990076 \n", + "27 -0.408448 \n", + "29 1.990767 \n", + "...\n", + "\n", + "[267 rows x 3 columns]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from bigframes.ml.preprocessing import StandardScaler\n", "\n", @@ -609,11 +1435,313 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "id": "TfwSLOTXmspI" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 6639e06d-3920-4c64-84d8-b40ce042188c is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 579dfb14-6d39-44c0-9b92-eb6a40c46df8 is DONE. 536 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 7f613d94-a68c-42d5-8afe-0413b32de3a0 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 140e8b5f-a24b-43a3-831f-30a29a4bd7ea is DONE. 2.1 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
standard_scaled_culmen_length_mmstandard_scaled_culmen_depth_mmstandard_scaled_flipper_length_mm
penguin_id
10.220718-1.3592771.045621
15-0.5104390.157322-0.771966
28-1.0588070.713408-0.771966
321.4636851.1683880.39129
33-0.2545340.056215-0.990076
34-0.5104390.4606420.318587
371.3540120.511195-0.263041
41-0.674949-0.095445-1.789814
47-1.1684810.662855-0.117634
520.4583440.308982-0.699262
56-1.0405280.460642-1.135483
57-0.9674120.005662-0.117634
620.988433-0.7526381.191028
651.7561481.3706010.318587
670.677691-1.3592771.045621
75-1.1136441.421155-0.771966
810.6776910.561748-0.408448
89-0.8577390.713408-0.771966
92-0.8029020.308982-0.917372
93-0.3093711.168388-0.263041
96-0.3093710.662855-1.499
100-0.9125760.814515-0.771966
1010.549739-1.3087241.554546
102-0.1265820.662855-0.626559
1071.20778-1.0054041.118325
\n", + "

25 rows × 3 columns

\n", + "
[67 rows x 3 columns in total]" + ], + "text/plain": [ + " standard_scaled_culmen_length_mm standard_scaled_culmen_depth_mm \\\n", + "penguin_id \n", + "1 0.220718 -1.359277 \n", + "15 -0.510439 0.157322 \n", + "28 -1.058807 0.713408 \n", + "32 1.463685 1.168388 \n", + "33 -0.254534 0.056215 \n", + "34 -0.510439 0.460642 \n", + "37 1.354012 0.511195 \n", + "41 -0.674949 -0.095445 \n", + "47 -1.168481 0.662855 \n", + "52 0.458344 0.308982 \n", + "56 -1.040528 0.460642 \n", + "57 -0.967412 0.005662 \n", + "62 0.988433 -0.752638 \n", + "65 1.756148 1.370601 \n", + "67 0.677691 -1.359277 \n", + "75 -1.113644 1.421155 \n", + "81 0.677691 0.561748 \n", + "89 -0.857739 0.713408 \n", + "92 -0.802902 0.308982 \n", + "93 -0.309371 1.168388 \n", + "96 -0.309371 0.662855 \n", + "100 -0.912576 0.814515 \n", + "101 0.549739 -1.308724 \n", + "102 -0.126582 0.662855 \n", + "107 1.20778 -1.005404 \n", + "\n", + " standard_scaled_flipper_length_mm \n", + "penguin_id \n", + "1 1.045621 \n", + "15 -0.771966 \n", + "28 -0.771966 \n", + "32 0.39129 \n", + "33 -0.990076 \n", + "34 0.318587 \n", + "37 -0.263041 \n", + "41 -1.789814 \n", + "47 -0.117634 \n", + "52 -0.699262 \n", + "56 -1.135483 \n", + "57 -0.117634 \n", + "62 1.191028 \n", + "65 0.318587 \n", + "67 1.045621 \n", + "75 -0.771966 \n", + "81 -0.408448 \n", + "89 -0.771966 \n", + "92 -0.917372 \n", + "93 -0.263041 \n", + "96 -1.499 \n", + "100 -0.771966 \n", + "101 1.554546 \n", + "102 -0.626559 \n", + "107 1.118325 \n", + "...\n", + "\n", + "[67 rows x 3 columns]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "scaler.transform(X_test[numeric_columns])" ] @@ -633,11 +1761,498 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "id": "I8Wwx3emmz2J" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job c16fdb5d-3f18-4f85-8a31-705ef4680be5 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 8c94a7c1-7f12-44be-b389-7c854ceead4b is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 1287628d-1380-4495-a5e9-6806440206bc is DONE. 22.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 03163e1a-c789-4046-b71a-b4b4e7bbc043 is DONE. 2.1 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 86f39b30-00db-4ada-8699-0fe49c94eb2d is DONE. 29.2 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job d5b0e8b0-12cd-47f6-85d2-806b2c252d37 is DONE. 536 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 459cdc90-d1f3-4580-9137-9b93d44ca991 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 80d10913-7263-44e6-89f7-719eac4158a3 is DONE. 21.4 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
onehotencoded_islandstandard_scaled_culmen_length_mmstandard_scaled_culmen_depth_mmstandard_scaled_flipper_length_mmonehotencoded_sexonehotencoded_species
penguin_id
0[{'index': 1, 'value': 1.0}]1.20778-0.6515311.772656[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
2[{'index': 3, 'value': 1.0}]-0.4556020.6628550.100476[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
3[{'index': 3, 'value': 1.0}]-0.967412-0.095445-0.917372[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
4[{'index': 1, 'value': 1.0}]0.476623-1.2076171.191028[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
5[{'index': 1, 'value': 1.0}]-1.6254540.359535-0.626559[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
7[{'index': 1, 'value': 1.0}]-0.345929-1.864810.682104[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
8[{'index': 1, 'value': 1.0}]0.842202-1.5614911.409139[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
9[{'index': 3, 'value': 1.0}]0.3486710.865068-0.263041[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
10[{'index': 2, 'value': 1.0}]0.9335961.2189410.827511[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
11[{'index': 3, 'value': 1.0}]-1.460943-0.297658-0.771966[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
12[{'index': 1, 'value': 1.0}]1.317454-0.4493181.409139[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
13[{'index': 1, 'value': 1.0}]-0.236255-1.7637040.900214[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
14[{'index': 2, 'value': 1.0}]0.549739-0.297658-0.626559[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
16[{'index': 1, 'value': 1.0}]0.970154-1.0054041.481842[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
17[{'index': 1, 'value': 1.0}]-1.058807-0.348211-0.190338[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
18[{'index': 1, 'value': 1.0}]1.354012-1.5109371.263732[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
19[{'index': 1, 'value': 1.0}]-0.053466-1.6625971.191028[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
20[{'index': 1, 'value': 1.0}]-0.199697-1.5109370.609401[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
21[{'index': 2, 'value': 1.0}]1.1529430.763962-0.190338[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
22[{'index': 2, 'value': 1.0}]-1.2050380.308982-0.699262[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
24[{'index': 1, 'value': 1.0}]-0.7846231.775028-0.699262[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
25[{'index': 3, 'value': 1.0}]-0.839461.724474-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
26[{'index': 1, 'value': 1.0}]-0.6201130.359535-0.990076[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
27[{'index': 2, 'value': 1.0}]0.330392-0.095445-0.408448[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
29[{'index': 1, 'value': 1.0}]2.194842-0.0954451.990767[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
\n", + "

25 rows × 6 columns

\n", + "
[267 rows x 6 columns in total]" + ], + "text/plain": [ + " onehotencoded_island standard_scaled_culmen_length_mm \\\n", + "penguin_id \n", + "0 [{'index': 1, 'value': 1.0}] 1.20778 \n", + "2 [{'index': 3, 'value': 1.0}] -0.455602 \n", + "3 [{'index': 3, 'value': 1.0}] -0.967412 \n", + "4 [{'index': 1, 'value': 1.0}] 0.476623 \n", + "5 [{'index': 1, 'value': 1.0}] -1.625454 \n", + "7 [{'index': 1, 'value': 1.0}] -0.345929 \n", + "8 [{'index': 1, 'value': 1.0}] 0.842202 \n", + "9 [{'index': 3, 'value': 1.0}] 0.348671 \n", + "10 [{'index': 2, 'value': 1.0}] 0.933596 \n", + "11 [{'index': 3, 'value': 1.0}] -1.460943 \n", + "12 [{'index': 1, 'value': 1.0}] 1.317454 \n", + "13 [{'index': 1, 'value': 1.0}] -0.236255 \n", + "14 [{'index': 2, 'value': 1.0}] 0.549739 \n", + "16 [{'index': 1, 'value': 1.0}] 0.970154 \n", + "17 [{'index': 1, 'value': 1.0}] -1.058807 \n", + "18 [{'index': 1, 'value': 1.0}] 1.354012 \n", + "19 [{'index': 1, 'value': 1.0}] -0.053466 \n", + "20 [{'index': 1, 'value': 1.0}] -0.199697 \n", + "21 [{'index': 2, 'value': 1.0}] 1.152943 \n", + "22 [{'index': 2, 'value': 1.0}] -1.205038 \n", + "24 [{'index': 1, 'value': 1.0}] -0.784623 \n", + "25 [{'index': 3, 'value': 1.0}] -0.83946 \n", + "26 [{'index': 1, 'value': 1.0}] -0.620113 \n", + "27 [{'index': 2, 'value': 1.0}] 0.330392 \n", + "29 [{'index': 1, 'value': 1.0}] 2.194842 \n", + "\n", + " standard_scaled_culmen_depth_mm \\\n", + "penguin_id \n", + "0 -0.651531 \n", + "2 0.662855 \n", + "3 -0.095445 \n", + "4 -1.207617 \n", + "5 0.359535 \n", + "7 -1.86481 \n", + "8 -1.561491 \n", + "9 0.865068 \n", + "10 1.218941 \n", + "11 -0.297658 \n", + "12 -0.449318 \n", + "13 -1.763704 \n", + "14 -0.297658 \n", + "16 -1.005404 \n", + "17 -0.348211 \n", + "18 -1.510937 \n", + "19 -1.662597 \n", + "20 -1.510937 \n", + "21 0.763962 \n", + "22 0.308982 \n", + "24 1.775028 \n", + "25 1.724474 \n", + "26 0.359535 \n", + "27 -0.095445 \n", + "29 -0.095445 \n", + "\n", + " standard_scaled_flipper_length_mm onehotencoded_sex \\\n", + "penguin_id \n", + "0 1.772656 [{'index': 3, 'value': 1.0}] \n", + "2 0.100476 [{'index': 3, 'value': 1.0}] \n", + "3 -0.917372 [{'index': 2, 'value': 1.0}] \n", + "4 1.191028 [{'index': 2, 'value': 1.0}] \n", + "5 -0.626559 [{'index': 2, 'value': 1.0}] \n", + "7 0.682104 [{'index': 2, 'value': 1.0}] \n", + "8 1.409139 [{'index': 3, 'value': 1.0}] \n", + "9 -0.263041 [{'index': 3, 'value': 1.0}] \n", + "10 0.827511 [{'index': 3, 'value': 1.0}] \n", + "11 -0.771966 [{'index': 2, 'value': 1.0}] \n", + "12 1.409139 [{'index': 3, 'value': 1.0}] \n", + "13 0.900214 [{'index': 2, 'value': 1.0}] \n", + "14 -0.626559 [{'index': 2, 'value': 1.0}] \n", + "16 1.481842 [{'index': 3, 'value': 1.0}] \n", + "17 -0.190338 [{'index': 2, 'value': 1.0}] \n", + "18 1.263732 [{'index': 3, 'value': 1.0}] \n", + "19 1.191028 [{'index': 2, 'value': 1.0}] \n", + "20 0.609401 [{'index': 2, 'value': 1.0}] \n", + "21 -0.190338 [{'index': 2, 'value': 1.0}] \n", + "22 -0.699262 [{'index': 2, 'value': 1.0}] \n", + "24 -0.699262 [{'index': 2, 'value': 1.0}] \n", + "25 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "26 -0.990076 [{'index': 2, 'value': 1.0}] \n", + "27 -0.408448 [{'index': 2, 'value': 1.0}] \n", + "29 1.990767 [{'index': 3, 'value': 1.0}] \n", + "\n", + " onehotencoded_species \n", + "penguin_id \n", + "0 [{'index': 3, 'value': 1.0}] \n", + "2 [{'index': 1, 'value': 1.0}] \n", + "3 [{'index': 1, 'value': 1.0}] \n", + "4 [{'index': 3, 'value': 1.0}] \n", + "5 [{'index': 1, 'value': 1.0}] \n", + "7 [{'index': 3, 'value': 1.0}] \n", + "8 [{'index': 3, 'value': 1.0}] \n", + "9 [{'index': 1, 'value': 1.0}] \n", + "10 [{'index': 2, 'value': 1.0}] \n", + "11 [{'index': 1, 'value': 1.0}] \n", + "12 [{'index': 3, 'value': 1.0}] \n", + "13 [{'index': 3, 'value': 1.0}] \n", + "14 [{'index': 2, 'value': 1.0}] \n", + "16 [{'index': 3, 'value': 1.0}] \n", + "17 [{'index': 1, 'value': 1.0}] \n", + "18 [{'index': 3, 'value': 1.0}] \n", + "19 [{'index': 3, 'value': 1.0}] \n", + "20 [{'index': 3, 'value': 1.0}] \n", + "21 [{'index': 2, 'value': 1.0}] \n", + "22 [{'index': 1, 'value': 1.0}] \n", + "24 [{'index': 1, 'value': 1.0}] \n", + "25 [{'index': 1, 'value': 1.0}] \n", + "26 [{'index': 1, 'value': 1.0}] \n", + "27 [{'index': 2, 'value': 1.0}] \n", + "29 [{'index': 3, 'value': 1.0}] \n", + "...\n", + "\n", + "[267 rows x 6 columns]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from bigframes.ml.compose import ColumnTransformer\n", "from bigframes.ml.preprocessing import OneHotEncoder\n", @@ -686,11 +2301,512 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "id": "ZeloMmopm8KI" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job a59bf4cc-4c92-4a68-96b1-7465fbcb3ed0 is DONE. 21.4 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 6860c534-a218-4a55-866d-a6e011399cd9 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 1b3e8da6-2d64-4337-872e-55b874f00596 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job fc118469-8dd7-4187-a3c1-7c5c2f1c5e36 is DONE. 5.7 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 544c5453-cd10-4a08-a338-601d85142df8 is DONE. 536 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 41c82cc9-7268-40ae-a736-f7a5f2c8b413 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job e9836f6b-160d-4ce4-88b6-0b04f40a1549 is DONE. 5.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
predicted_body_mass_gonehotencoded_islandstandard_scaled_culmen_length_mmstandard_scaled_culmen_depth_mmstandard_scaled_flipper_length_mmonehotencoded_sexonehotencoded_species
penguin_id
14772.376044[{'index': 1, 'value': 1.0}]0.220718-1.3592771.045621[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
153883.373922[{'index': 2, 'value': 1.0}]-0.5104390.157322-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
283479.709088[{'index': 2, 'value': 1.0}]-1.0588070.713408-0.771966[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
324223.853626[{'index': 2, 'value': 1.0}]1.4636851.1683880.39129[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
333197.623474[{'index': 2, 'value': 1.0}]-0.2545340.056215-0.990076[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
344155.26742[{'index': 2, 'value': 1.0}]-0.5104390.4606420.318587[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
373991.314095[{'index': 2, 'value': 1.0}]1.3540120.511195-0.263041[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
413232.648242[{'index': 3, 'value': 1.0}]-0.674949-0.095445-1.789814[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
474017.740788[{'index': 2, 'value': 1.0}]-1.1684810.662855-0.117634[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
523365.080596[{'index': 2, 'value': 1.0}]0.4583440.308982-0.699262[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
563791.332002[{'index': 1, 'value': 1.0}]-1.0405280.460642-1.135483[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
573547.892992[{'index': 1, 'value': 1.0}]-0.9674120.005662-0.117634[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
625372.087702[{'index': 1, 'value': 1.0}]0.988433-0.7526381.191028[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
654263.232169[{'index': 2, 'value': 1.0}]1.7561481.3706010.318587[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
675234.45894[{'index': 1, 'value': 1.0}]0.677691-1.3592771.045621[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
753979.314516[{'index': 1, 'value': 1.0}]-1.1136441.421155-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
813481.331391[{'index': 2, 'value': 1.0}]0.6776910.561748-0.408448[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
893915.240555[{'index': 2, 'value': 1.0}]-0.8577390.713408-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
923425.563946[{'index': 2, 'value': 1.0}]-0.8029020.308982-0.917372[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
934141.497717[{'index': 1, 'value': 1.0}]-0.3093711.168388-0.263041[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
963394.72289[{'index': 2, 'value': 1.0}]-0.3093710.662855-1.499[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
1003507.226918[{'index': 2, 'value': 1.0}]-0.9125760.814515-0.771966[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
1014922.286202[{'index': 1, 'value': 1.0}]0.549739-1.3087241.554546[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
1024016.243221[{'index': 2, 'value': 1.0}]-0.1265820.662855-0.626559[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
1074933.655362[{'index': 1, 'value': 1.0}]1.20778-1.0054041.118325[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
\n", + "

25 rows × 7 columns

\n", + "
[67 rows x 7 columns in total]" + ], + "text/plain": [ + " predicted_body_mass_g onehotencoded_island \\\n", + "penguin_id \n", + "1 4772.376044 [{'index': 1, 'value': 1.0}] \n", + "15 3883.373922 [{'index': 2, 'value': 1.0}] \n", + "28 3479.709088 [{'index': 2, 'value': 1.0}] \n", + "32 4223.853626 [{'index': 2, 'value': 1.0}] \n", + "33 3197.623474 [{'index': 2, 'value': 1.0}] \n", + "34 4155.26742 [{'index': 2, 'value': 1.0}] \n", + "37 3991.314095 [{'index': 2, 'value': 1.0}] \n", + "41 3232.648242 [{'index': 3, 'value': 1.0}] \n", + "47 4017.740788 [{'index': 2, 'value': 1.0}] \n", + "52 3365.080596 [{'index': 2, 'value': 1.0}] \n", + "56 3791.332002 [{'index': 1, 'value': 1.0}] \n", + "57 3547.892992 [{'index': 1, 'value': 1.0}] \n", + "62 5372.087702 [{'index': 1, 'value': 1.0}] \n", + "65 4263.232169 [{'index': 2, 'value': 1.0}] \n", + "67 5234.45894 [{'index': 1, 'value': 1.0}] \n", + "75 3979.314516 [{'index': 1, 'value': 1.0}] \n", + "81 3481.331391 [{'index': 2, 'value': 1.0}] \n", + "89 3915.240555 [{'index': 2, 'value': 1.0}] \n", + "92 3425.563946 [{'index': 2, 'value': 1.0}] \n", + "93 4141.497717 [{'index': 1, 'value': 1.0}] \n", + "96 3394.72289 [{'index': 2, 'value': 1.0}] \n", + "100 3507.226918 [{'index': 2, 'value': 1.0}] \n", + "101 4922.286202 [{'index': 1, 'value': 1.0}] \n", + "102 4016.243221 [{'index': 2, 'value': 1.0}] \n", + "107 4933.655362 [{'index': 1, 'value': 1.0}] \n", + "\n", + " standard_scaled_culmen_length_mm standard_scaled_culmen_depth_mm \\\n", + "penguin_id \n", + "1 0.220718 -1.359277 \n", + "15 -0.510439 0.157322 \n", + "28 -1.058807 0.713408 \n", + "32 1.463685 1.168388 \n", + "33 -0.254534 0.056215 \n", + "34 -0.510439 0.460642 \n", + "37 1.354012 0.511195 \n", + "41 -0.674949 -0.095445 \n", + "47 -1.168481 0.662855 \n", + "52 0.458344 0.308982 \n", + "56 -1.040528 0.460642 \n", + "57 -0.967412 0.005662 \n", + "62 0.988433 -0.752638 \n", + "65 1.756148 1.370601 \n", + "67 0.677691 -1.359277 \n", + "75 -1.113644 1.421155 \n", + "81 0.677691 0.561748 \n", + "89 -0.857739 0.713408 \n", + "92 -0.802902 0.308982 \n", + "93 -0.309371 1.168388 \n", + "96 -0.309371 0.662855 \n", + "100 -0.912576 0.814515 \n", + "101 0.549739 -1.308724 \n", + "102 -0.126582 0.662855 \n", + "107 1.20778 -1.005404 \n", + "\n", + " standard_scaled_flipper_length_mm onehotencoded_sex \\\n", + "penguin_id \n", + "1 1.045621 [{'index': 2, 'value': 1.0}] \n", + "15 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "28 -0.771966 [{'index': 2, 'value': 1.0}] \n", + "32 0.39129 [{'index': 3, 'value': 1.0}] \n", + "33 -0.990076 [{'index': 2, 'value': 1.0}] \n", + "34 0.318587 [{'index': 3, 'value': 1.0}] \n", + "37 -0.263041 [{'index': 3, 'value': 1.0}] \n", + "41 -1.789814 [{'index': 2, 'value': 1.0}] \n", + "47 -0.117634 [{'index': 3, 'value': 1.0}] \n", + "52 -0.699262 [{'index': 2, 'value': 1.0}] \n", + "56 -1.135483 [{'index': 3, 'value': 1.0}] \n", + "57 -0.117634 [{'index': 2, 'value': 1.0}] \n", + "62 1.191028 [{'index': 3, 'value': 1.0}] \n", + "65 0.318587 [{'index': 3, 'value': 1.0}] \n", + "67 1.045621 [{'index': 3, 'value': 1.0}] \n", + "75 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "81 -0.408448 [{'index': 2, 'value': 1.0}] \n", + "89 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "92 -0.917372 [{'index': 2, 'value': 1.0}] \n", + "93 -0.263041 [{'index': 3, 'value': 1.0}] \n", + "96 -1.499 [{'index': 2, 'value': 1.0}] \n", + "100 -0.771966 [{'index': 2, 'value': 1.0}] \n", + "101 1.554546 [{'index': 2, 'value': 1.0}] \n", + "102 -0.626559 [{'index': 3, 'value': 1.0}] \n", + "107 1.118325 [{'index': 2, 'value': 1.0}] \n", + "\n", + " onehotencoded_species \n", + "penguin_id \n", + "1 [{'index': 3, 'value': 1.0}] \n", + "15 [{'index': 1, 'value': 1.0}] \n", + "28 [{'index': 1, 'value': 1.0}] \n", + "32 [{'index': 2, 'value': 1.0}] \n", + "33 [{'index': 2, 'value': 1.0}] \n", + "34 [{'index': 1, 'value': 1.0}] \n", + "37 [{'index': 2, 'value': 1.0}] \n", + "41 [{'index': 1, 'value': 1.0}] \n", + "47 [{'index': 1, 'value': 1.0}] \n", + "52 [{'index': 2, 'value': 1.0}] \n", + "56 [{'index': 1, 'value': 1.0}] \n", + "57 [{'index': 1, 'value': 1.0}] \n", + "62 [{'index': 3, 'value': 1.0}] \n", + "65 [{'index': 2, 'value': 1.0}] \n", + "67 [{'index': 3, 'value': 1.0}] \n", + "75 [{'index': 1, 'value': 1.0}] \n", + "81 [{'index': 2, 'value': 1.0}] \n", + "89 [{'index': 1, 'value': 1.0}] \n", + "92 [{'index': 1, 'value': 1.0}] \n", + "93 [{'index': 1, 'value': 1.0}] \n", + "96 [{'index': 1, 'value': 1.0}] \n", + "100 [{'index': 1, 'value': 1.0}] \n", + "101 [{'index': 3, 'value': 1.0}] \n", + "102 [{'index': 1, 'value': 1.0}] \n", + "107 [{'index': 3, 'value': 1.0}] \n", + "\n", + "[67 rows x 7 columns]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from bigframes.ml.linear_model import LinearRegression\n", "\n", @@ -719,11 +2835,555 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "id": "M13zd02znCIg" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 728068d3-2349-4636-a030-016b500a9812 is DONE. 23.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 37bac685-2afa-4ece-b3a3-e0b84a92c65f is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 38416629-4615-45f5-9e27-d9164124f755 is DONE. 6.2 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 0241ea1c-8d96-418a-b3d6-08d819854954 is DONE. 536 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 405bcf9b-d652-42f3-931e-12ca0310fe4f is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 21ca6f31-2ea2-4f71-b030-c738bf5afe27 is DONE. 10.2 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CENTROID_IDNEAREST_CENTROIDS_DISTANCEonehotencoded_islandstandard_scaled_culmen_length_mmstandard_scaled_culmen_depth_mmstandard_scaled_flipper_length_mmonehotencoded_sexonehotencoded_species
penguin_id
13[{'CENTROID_ID': 3, 'DISTANCE': 0.857057881337...[{'index': 1, 'value': 1.0}]0.220718-1.3592771.045621[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
154[{'CENTROID_ID': 4, 'DISTANCE': 1.181613302004...[{'index': 2, 'value': 1.0}]-0.5104390.157322-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
281[{'CENTROID_ID': 1, 'DISTANCE': 1.006856853050...[{'index': 2, 'value': 1.0}]-1.0588070.713408-0.771966[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
322[{'CENTROID_ID': 2, 'DISTANCE': 1.237504384283...[{'index': 2, 'value': 1.0}]1.4636851.1683880.39129[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
332[{'CENTROID_ID': 2, 'DISTANCE': 1.656439702919...[{'index': 2, 'value': 1.0}]-0.2545340.056215-0.990076[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
344[{'CENTROID_ID': 4, 'DISTANCE': 1.343792119214...[{'index': 2, 'value': 1.0}]-0.5104390.4606420.318587[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
372[{'CENTROID_ID': 2, 'DISTANCE': 0.816670297369...[{'index': 2, 'value': 1.0}]1.3540120.511195-0.263041[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
411[{'CENTROID_ID': 1, 'DISTANCE': 1.317560921596...[{'index': 3, 'value': 1.0}]-0.674949-0.095445-1.789814[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
474[{'CENTROID_ID': 4, 'DISTANCE': 1.135112005343...[{'index': 2, 'value': 1.0}]-1.1684810.662855-0.117634[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
522[{'CENTROID_ID': 2, 'DISTANCE': 1.004096945181...[{'index': 2, 'value': 1.0}]0.4583440.308982-0.699262[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
564[{'CENTROID_ID': 4, 'DISTANCE': 1.218648668822...[{'index': 1, 'value': 1.0}]-1.0405280.460642-1.135483[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
571[{'CENTROID_ID': 1, 'DISTANCE': 1.238466630273...[{'index': 1, 'value': 1.0}]-0.9674120.005662-0.117634[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
623[{'CENTROID_ID': 3, 'DISTANCE': 0.876984617451...[{'index': 1, 'value': 1.0}]0.988433-0.7526381.191028[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
652[{'CENTROID_ID': 2, 'DISTANCE': 1.439604004538...[{'index': 2, 'value': 1.0}]1.7561481.3706010.318587[{'index': 3, 'value': 1.0}][{'index': 2, 'value': 1.0}]
673[{'CENTROID_ID': 3, 'DISTANCE': 0.763112987694...[{'index': 1, 'value': 1.0}]0.677691-1.3592771.045621[{'index': 3, 'value': 1.0}][{'index': 3, 'value': 1.0}]
754[{'CENTROID_ID': 4, 'DISTANCE': 1.075788925734...[{'index': 1, 'value': 1.0}]-1.1136441.421155-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
812[{'CENTROID_ID': 2, 'DISTANCE': 0.777307801541...[{'index': 2, 'value': 1.0}]0.6776910.561748-0.408448[{'index': 2, 'value': 1.0}][{'index': 2, 'value': 1.0}]
894[{'CENTROID_ID': 4, 'DISTANCE': 0.891303183824...[{'index': 2, 'value': 1.0}]-0.8577390.713408-0.771966[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
921[{'CENTROID_ID': 1, 'DISTANCE': 0.934676470689...[{'index': 2, 'value': 1.0}]-0.8029020.308982-0.917372[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
934[{'CENTROID_ID': 4, 'DISTANCE': 0.984620018517...[{'index': 1, 'value': 1.0}]-0.3093711.168388-0.263041[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
961[{'CENTROID_ID': 1, 'DISTANCE': 1.446939975674...[{'index': 2, 'value': 1.0}]-0.3093710.662855-1.499[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
1001[{'CENTROID_ID': 1, 'DISTANCE': 1.101117711572...[{'index': 2, 'value': 1.0}]-0.9125760.814515-0.771966[{'index': 2, 'value': 1.0}][{'index': 1, 'value': 1.0}]
1013[{'CENTROID_ID': 3, 'DISTANCE': 0.823832007899...[{'index': 1, 'value': 1.0}]0.549739-1.3087241.554546[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
1024[{'CENTROID_ID': 4, 'DISTANCE': 0.995348310182...[{'index': 2, 'value': 1.0}]-0.1265820.662855-0.626559[{'index': 3, 'value': 1.0}][{'index': 1, 'value': 1.0}]
1073[{'CENTROID_ID': 3, 'DISTANCE': 0.930021405831...[{'index': 1, 'value': 1.0}]1.20778-1.0054041.118325[{'index': 2, 'value': 1.0}][{'index': 3, 'value': 1.0}]
\n", + "

25 rows × 8 columns

\n", + "
[67 rows x 8 columns in total]" + ], + "text/plain": [ + " CENTROID_ID NEAREST_CENTROIDS_DISTANCE \\\n", + "penguin_id \n", + "1 3 [{'CENTROID_ID': 3, 'DISTANCE': 0.857057881337... \n", + "15 4 [{'CENTROID_ID': 4, 'DISTANCE': 1.181613302004... \n", + "28 1 [{'CENTROID_ID': 1, 'DISTANCE': 1.006856853050... \n", + "32 2 [{'CENTROID_ID': 2, 'DISTANCE': 1.237504384283... \n", + "33 2 [{'CENTROID_ID': 2, 'DISTANCE': 1.656439702919... \n", + "34 4 [{'CENTROID_ID': 4, 'DISTANCE': 1.343792119214... \n", + "37 2 [{'CENTROID_ID': 2, 'DISTANCE': 0.816670297369... \n", + "41 1 [{'CENTROID_ID': 1, 'DISTANCE': 1.317560921596... \n", + "47 4 [{'CENTROID_ID': 4, 'DISTANCE': 1.135112005343... \n", + "52 2 [{'CENTROID_ID': 2, 'DISTANCE': 1.004096945181... \n", + "56 4 [{'CENTROID_ID': 4, 'DISTANCE': 1.218648668822... \n", + "57 1 [{'CENTROID_ID': 1, 'DISTANCE': 1.238466630273... \n", + "62 3 [{'CENTROID_ID': 3, 'DISTANCE': 0.876984617451... \n", + "65 2 [{'CENTROID_ID': 2, 'DISTANCE': 1.439604004538... \n", + "67 3 [{'CENTROID_ID': 3, 'DISTANCE': 0.763112987694... \n", + "75 4 [{'CENTROID_ID': 4, 'DISTANCE': 1.075788925734... \n", + "81 2 [{'CENTROID_ID': 2, 'DISTANCE': 0.777307801541... \n", + "89 4 [{'CENTROID_ID': 4, 'DISTANCE': 0.891303183824... \n", + "92 1 [{'CENTROID_ID': 1, 'DISTANCE': 0.934676470689... \n", + "93 4 [{'CENTROID_ID': 4, 'DISTANCE': 0.984620018517... \n", + "96 1 [{'CENTROID_ID': 1, 'DISTANCE': 1.446939975674... \n", + "100 1 [{'CENTROID_ID': 1, 'DISTANCE': 1.101117711572... \n", + "101 3 [{'CENTROID_ID': 3, 'DISTANCE': 0.823832007899... \n", + "102 4 [{'CENTROID_ID': 4, 'DISTANCE': 0.995348310182... \n", + "107 3 [{'CENTROID_ID': 3, 'DISTANCE': 0.930021405831... \n", + "\n", + " onehotencoded_island standard_scaled_culmen_length_mm \\\n", + "penguin_id \n", + "1 [{'index': 1, 'value': 1.0}] 0.220718 \n", + "15 [{'index': 2, 'value': 1.0}] -0.510439 \n", + "28 [{'index': 2, 'value': 1.0}] -1.058807 \n", + "32 [{'index': 2, 'value': 1.0}] 1.463685 \n", + "33 [{'index': 2, 'value': 1.0}] -0.254534 \n", + "34 [{'index': 2, 'value': 1.0}] -0.510439 \n", + "37 [{'index': 2, 'value': 1.0}] 1.354012 \n", + "41 [{'index': 3, 'value': 1.0}] -0.674949 \n", + "47 [{'index': 2, 'value': 1.0}] -1.168481 \n", + "52 [{'index': 2, 'value': 1.0}] 0.458344 \n", + "56 [{'index': 1, 'value': 1.0}] -1.040528 \n", + "57 [{'index': 1, 'value': 1.0}] -0.967412 \n", + "62 [{'index': 1, 'value': 1.0}] 0.988433 \n", + "65 [{'index': 2, 'value': 1.0}] 1.756148 \n", + "67 [{'index': 1, 'value': 1.0}] 0.677691 \n", + "75 [{'index': 1, 'value': 1.0}] -1.113644 \n", + "81 [{'index': 2, 'value': 1.0}] 0.677691 \n", + "89 [{'index': 2, 'value': 1.0}] -0.857739 \n", + "92 [{'index': 2, 'value': 1.0}] -0.802902 \n", + "93 [{'index': 1, 'value': 1.0}] -0.309371 \n", + "96 [{'index': 2, 'value': 1.0}] -0.309371 \n", + "100 [{'index': 2, 'value': 1.0}] -0.912576 \n", + "101 [{'index': 1, 'value': 1.0}] 0.549739 \n", + "102 [{'index': 2, 'value': 1.0}] -0.126582 \n", + "107 [{'index': 1, 'value': 1.0}] 1.20778 \n", + "\n", + " standard_scaled_culmen_depth_mm \\\n", + "penguin_id \n", + "1 -1.359277 \n", + "15 0.157322 \n", + "28 0.713408 \n", + "32 1.168388 \n", + "33 0.056215 \n", + "34 0.460642 \n", + "37 0.511195 \n", + "41 -0.095445 \n", + "47 0.662855 \n", + "52 0.308982 \n", + "56 0.460642 \n", + "57 0.005662 \n", + "62 -0.752638 \n", + "65 1.370601 \n", + "67 -1.359277 \n", + "75 1.421155 \n", + "81 0.561748 \n", + "89 0.713408 \n", + "92 0.308982 \n", + "93 1.168388 \n", + "96 0.662855 \n", + "100 0.814515 \n", + "101 -1.308724 \n", + "102 0.662855 \n", + "107 -1.005404 \n", + "\n", + " standard_scaled_flipper_length_mm onehotencoded_sex \\\n", + "penguin_id \n", + "1 1.045621 [{'index': 2, 'value': 1.0}] \n", + "15 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "28 -0.771966 [{'index': 2, 'value': 1.0}] \n", + "32 0.39129 [{'index': 3, 'value': 1.0}] \n", + "33 -0.990076 [{'index': 2, 'value': 1.0}] \n", + "34 0.318587 [{'index': 3, 'value': 1.0}] \n", + "37 -0.263041 [{'index': 3, 'value': 1.0}] \n", + "41 -1.789814 [{'index': 2, 'value': 1.0}] \n", + "47 -0.117634 [{'index': 3, 'value': 1.0}] \n", + "52 -0.699262 [{'index': 2, 'value': 1.0}] \n", + "56 -1.135483 [{'index': 3, 'value': 1.0}] \n", + "57 -0.117634 [{'index': 2, 'value': 1.0}] \n", + "62 1.191028 [{'index': 3, 'value': 1.0}] \n", + "65 0.318587 [{'index': 3, 'value': 1.0}] \n", + "67 1.045621 [{'index': 3, 'value': 1.0}] \n", + "75 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "81 -0.408448 [{'index': 2, 'value': 1.0}] \n", + "89 -0.771966 [{'index': 3, 'value': 1.0}] \n", + "92 -0.917372 [{'index': 2, 'value': 1.0}] \n", + "93 -0.263041 [{'index': 3, 'value': 1.0}] \n", + "96 -1.499 [{'index': 2, 'value': 1.0}] \n", + "100 -0.771966 [{'index': 2, 'value': 1.0}] \n", + "101 1.554546 [{'index': 2, 'value': 1.0}] \n", + "102 -0.626559 [{'index': 3, 'value': 1.0}] \n", + "107 1.118325 [{'index': 2, 'value': 1.0}] \n", + "\n", + " onehotencoded_species \n", + "penguin_id \n", + "1 [{'index': 3, 'value': 1.0}] \n", + "15 [{'index': 1, 'value': 1.0}] \n", + "28 [{'index': 1, 'value': 1.0}] \n", + "32 [{'index': 2, 'value': 1.0}] \n", + "33 [{'index': 2, 'value': 1.0}] \n", + "34 [{'index': 1, 'value': 1.0}] \n", + "37 [{'index': 2, 'value': 1.0}] \n", + "41 [{'index': 1, 'value': 1.0}] \n", + "47 [{'index': 1, 'value': 1.0}] \n", + "52 [{'index': 2, 'value': 1.0}] \n", + "56 [{'index': 1, 'value': 1.0}] \n", + "57 [{'index': 1, 'value': 1.0}] \n", + "62 [{'index': 3, 'value': 1.0}] \n", + "65 [{'index': 2, 'value': 1.0}] \n", + "67 [{'index': 3, 'value': 1.0}] \n", + "75 [{'index': 1, 'value': 1.0}] \n", + "81 [{'index': 2, 'value': 1.0}] \n", + "89 [{'index': 1, 'value': 1.0}] \n", + "92 [{'index': 1, 'value': 1.0}] \n", + "93 [{'index': 1, 'value': 1.0}] \n", + "96 [{'index': 1, 'value': 1.0}] \n", + "100 [{'index': 1, 'value': 1.0}] \n", + "101 [{'index': 3, 'value': 1.0}] \n", + "102 [{'index': 1, 'value': 1.0}] \n", + "107 [{'index': 3, 'value': 1.0}] \n", + "\n", + "[67 rows x 8 columns]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from bigframes.ml.cluster import KMeans\n", "\n", @@ -750,11 +3410,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "id": "Ku2OXqgJnEeR" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Pipeline(steps=[('preproc',\n", + " ColumnTransformer(transformers=[('scale', StandardScaler(),\n", + " ['culmen_length_mm',\n", + " 'culmen_depth_mm',\n", + " 'flipper_length_mm']),\n", + " ('encode', OneHotEncoder(),\n", + " ['species', 'sex',\n", + " 'island'])])),\n", + " ('linreg', LinearRegression())])" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from bigframes.ml.pipeline import Pipeline\n", "\n", @@ -778,11 +3457,484 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "id": "hsF7FYagnMko" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 95b43592-b198-4f9e-a990-4e837b82121f is DONE. 24.8 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 615b2afb-0c76-45d6-82c7-bde7c8b2b3a4 is DONE. 8.5 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job cf2ed3ca-01bf-4cb6-a71a-d6e30a8428f6 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job d9780763-1d2b-494d-a778-20364c52bd08 is DONE. 29.6 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job f01296ba-7cd0-4d06-b25a-b5697e46bbf7 is DONE. 536 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 5b6fe451-2f8e-471e-a6a0-00b9bffaa826 is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 6a81883b-0514-4251-9f63-490b6346bb8b is DONE. 6.1 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
predicted_body_mass_gislandculmen_length_mmculmen_depth_mmflipper_length_mmsexspecies
penguin_id
14772.374547Biscoe45.114.5215.0FEMALEGentoo penguin (Pygoscelis papua)
153883.371052Dream41.117.5190.0MALEAdelie Penguin (Pygoscelis adeliae)
283479.706166Dream38.118.6190.0FEMALEAdelie Penguin (Pygoscelis adeliae)
324223.851137Dream51.919.5206.0MALEChinstrap penguin (Pygoscelis antarctica)
333197.620461Dream42.517.3187.0FEMALEChinstrap penguin (Pygoscelis antarctica)
344155.265191Dream41.118.1205.0MALEAdelie Penguin (Pygoscelis adeliae)
373991.311319Dream51.318.2197.0MALEChinstrap penguin (Pygoscelis antarctica)
413232.644783Torgersen40.217.0176.0FEMALEAdelie Penguin (Pygoscelis adeliae)
474017.738303Dream37.518.5199.0MALEAdelie Penguin (Pygoscelis adeliae)
523365.077659Dream46.417.8191.0FEMALEChinstrap penguin (Pygoscelis antarctica)
563791.328893Biscoe38.218.1185.0MALEAdelie Penguin (Pygoscelis adeliae)
573547.890609Biscoe38.617.2199.0FEMALEAdelie Penguin (Pygoscelis adeliae)
625372.086117Biscoe49.315.7217.0MALEGentoo penguin (Pygoscelis papua)
654263.229571Dream53.519.9205.0MALEChinstrap penguin (Pygoscelis antarctica)
675234.457401Biscoe47.614.5215.0MALEGentoo penguin (Pygoscelis papua)
753979.311469Biscoe37.820.0190.0MALEAdelie Penguin (Pygoscelis adeliae)
813481.328573Dream47.618.3195.0FEMALEChinstrap penguin (Pygoscelis antarctica)
893915.237615Dream39.218.6190.0MALEAdelie Penguin (Pygoscelis adeliae)
923425.560982Dream39.517.8188.0FEMALEAdelie Penguin (Pygoscelis adeliae)
934141.494969Biscoe42.219.5197.0MALEAdelie Penguin (Pygoscelis adeliae)
963394.719445Dream42.218.5180.0FEMALEAdelie Penguin (Pygoscelis adeliae)
1003507.223965Dream38.918.8190.0FEMALEAdelie Penguin (Pygoscelis adeliae)
1014922.284991Biscoe46.914.6222.0FEMALEGentoo penguin (Pygoscelis papua)
1024016.240318Dream43.218.5192.0MALEAdelie Penguin (Pygoscelis adeliae)
1074933.653758Biscoe50.515.2216.0FEMALEGentoo penguin (Pygoscelis papua)
\n", + "

25 rows × 7 columns

\n", + "
[67 rows x 7 columns in total]" + ], + "text/plain": [ + " predicted_body_mass_g island culmen_length_mm \\\n", + "penguin_id \n", + "1 4772.374547 Biscoe 45.1 \n", + "15 3883.371052 Dream 41.1 \n", + "28 3479.706166 Dream 38.1 \n", + "32 4223.851137 Dream 51.9 \n", + "33 3197.620461 Dream 42.5 \n", + "34 4155.265191 Dream 41.1 \n", + "37 3991.311319 Dream 51.3 \n", + "41 3232.644783 Torgersen 40.2 \n", + "47 4017.738303 Dream 37.5 \n", + "52 3365.077659 Dream 46.4 \n", + "56 3791.328893 Biscoe 38.2 \n", + "57 3547.890609 Biscoe 38.6 \n", + "62 5372.086117 Biscoe 49.3 \n", + "65 4263.229571 Dream 53.5 \n", + "67 5234.457401 Biscoe 47.6 \n", + "75 3979.311469 Biscoe 37.8 \n", + "81 3481.328573 Dream 47.6 \n", + "89 3915.237615 Dream 39.2 \n", + "92 3425.560982 Dream 39.5 \n", + "93 4141.494969 Biscoe 42.2 \n", + "96 3394.719445 Dream 42.2 \n", + "100 3507.223965 Dream 38.9 \n", + "101 4922.284991 Biscoe 46.9 \n", + "102 4016.240318 Dream 43.2 \n", + "107 4933.653758 Biscoe 50.5 \n", + "\n", + " culmen_depth_mm flipper_length_mm sex \\\n", + "penguin_id \n", + "1 14.5 215.0 FEMALE \n", + "15 17.5 190.0 MALE \n", + "28 18.6 190.0 FEMALE \n", + "32 19.5 206.0 MALE \n", + "33 17.3 187.0 FEMALE \n", + "34 18.1 205.0 MALE \n", + "37 18.2 197.0 MALE \n", + "41 17.0 176.0 FEMALE \n", + "47 18.5 199.0 MALE \n", + "52 17.8 191.0 FEMALE \n", + "56 18.1 185.0 MALE \n", + "57 17.2 199.0 FEMALE \n", + "62 15.7 217.0 MALE \n", + "65 19.9 205.0 MALE \n", + "67 14.5 215.0 MALE \n", + "75 20.0 190.0 MALE \n", + "81 18.3 195.0 FEMALE \n", + "89 18.6 190.0 MALE \n", + "92 17.8 188.0 FEMALE \n", + "93 19.5 197.0 MALE \n", + "96 18.5 180.0 FEMALE \n", + "100 18.8 190.0 FEMALE \n", + "101 14.6 222.0 FEMALE \n", + "102 18.5 192.0 MALE \n", + "107 15.2 216.0 FEMALE \n", + "\n", + " species \n", + "penguin_id \n", + "1 Gentoo penguin (Pygoscelis papua) \n", + "15 Adelie Penguin (Pygoscelis adeliae) \n", + "28 Adelie Penguin (Pygoscelis adeliae) \n", + "32 Chinstrap penguin (Pygoscelis antarctica) \n", + "33 Chinstrap penguin (Pygoscelis antarctica) \n", + "34 Adelie Penguin (Pygoscelis adeliae) \n", + "37 Chinstrap penguin (Pygoscelis antarctica) \n", + "41 Adelie Penguin (Pygoscelis adeliae) \n", + "47 Adelie Penguin (Pygoscelis adeliae) \n", + "52 Chinstrap penguin (Pygoscelis antarctica) \n", + "56 Adelie Penguin (Pygoscelis adeliae) \n", + "57 Adelie Penguin (Pygoscelis adeliae) \n", + "62 Gentoo penguin (Pygoscelis papua) \n", + "65 Chinstrap penguin (Pygoscelis antarctica) \n", + "67 Gentoo penguin (Pygoscelis papua) \n", + "75 Adelie Penguin (Pygoscelis adeliae) \n", + "81 Chinstrap penguin (Pygoscelis antarctica) \n", + "89 Adelie Penguin (Pygoscelis adeliae) \n", + "92 Adelie Penguin (Pygoscelis adeliae) \n", + "93 Adelie Penguin (Pygoscelis adeliae) \n", + "96 Adelie Penguin (Pygoscelis adeliae) \n", + "100 Adelie Penguin (Pygoscelis adeliae) \n", + "101 Gentoo penguin (Pygoscelis papua) \n", + "102 Adelie Penguin (Pygoscelis adeliae) \n", + "107 Gentoo penguin (Pygoscelis papua) \n", + "\n", + "[67 rows x 7 columns]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pipeline.fit(X_train, y_train)\n", "\n", @@ -812,11 +3964,106 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "metadata": { "id": "Q8nR1ZqznU-B" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job c098e1d1-b3ed-4ec5-94c7-6ba3b2b59e3f is DONE. 29.6 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 035234b0-537a-44ce-adff-bb51c40b4ffa is DONE. 0 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job b4a2a367-3e06-4fa3-9f00-bdbca884cfdd is DONE. 48 Bytes processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "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", + "
mean_absolute_errormean_squared_errormean_squared_log_errormedian_absolute_errorr2_scoreexplained_variance
0225.88351277765.9892810.004457179.5480410.8731660.873315
\n", + "

1 rows × 6 columns

\n", + "
[1 rows x 6 columns in total]" + ], + "text/plain": [ + " mean_absolute_error mean_squared_error mean_squared_log_error \\\n", + "0 225.883512 77765.989281 0.004457 \n", + "\n", + " median_absolute_error r2_score explained_variance \n", + "0 179.548041 0.873166 0.873315 \n", + "\n", + "[1 rows x 6 columns]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# In the case of a pipeline, this will be equivalent to calling .score on the contained LinearRegression\n", "pipeline.score(X_test, y_test)" @@ -833,11 +4080,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "id": "vdEN4Ob9nan4" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 20ec1716-3e8e-4d3f-ba08-1f7b9970ce3f is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job 6f628f3b-62df-4a5a-8e05-0b313db0ed07 is DONE. 28.9 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job c4eee1e5-146f-4a52-8499-83fe5f701f53 is DONE. 30.0 kB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "0.8731660699616813" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from bigframes.ml.metrics import r2_score\n", "\n", @@ -862,24 +4156,104 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "id": "fb0HpkdpnigJ" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Copy job 06c2b62d-a7aa-46a5-a04a-2f189bafc5ee is DONE. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Pipeline(steps=[('transform',\n", + " ColumnTransformer(transformers=[('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'island'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_length_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_depth_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'flipper_length_mm'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'sex'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'species')])),\n", + " ('estimator',\n", + " LinearRegression(optimize_strategy='NORMAL_EQUATION'))])" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "linreg.to_gbq(f\"{DATASET}.penguins_model\", replace=True)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "id": "_zNOBlHdnkII" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Pipeline(steps=[('transform',\n", + " ColumnTransformer(transformers=[('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'island'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_length_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_depth_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'flipper_length_mm'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'sex'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'species')])),\n", + " ('estimator',\n", + " LinearRegression(optimize_strategy='NORMAL_EQUATION'))])" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "bf.read_gbq_model(f\"{DATASET}.penguins_model\")" + "bpd.read_gbq_model(f\"{DATASET}.penguins_model\")" ] }, { @@ -893,24 +4267,104 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "id": "P76_TQ3IR6nB" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Copy job a0ed8c1b-3a3f-4995-853c-e151d41560d7 is DONE. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Pipeline(steps=[('transform',\n", + " ColumnTransformer(transformers=[('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'island'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_length_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_depth_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'flipper_length_mm'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'sex'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'species')])),\n", + " ('estimator',\n", + " LinearRegression(optimize_strategy='NORMAL_EQUATION'))])" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "pipeline.to_gbq(f\"{DATASET}.penguins_pipeline\", replace=True)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "id": "GKvlKFjAbToJ" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Pipeline(steps=[('transform',\n", + " ColumnTransformer(transformers=[('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'island'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_length_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'culmen_depth_mm'),\n", + " ('standard_scaler',\n", + " StandardScaler(),\n", + " 'flipper_length_mm'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'sex'),\n", + " ('ont_hot_encoder',\n", + " OneHotEncoder(max_categories=1000001,\n", + " min_frequency=0),\n", + " 'species')])),\n", + " ('estimator',\n", + " LinearRegression(optimize_strategy='NORMAL_EQUATION'))])" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "bf.read_gbq_model(f\"{DATASET}.penguins_pipeline\")" + "bpd.read_gbq_model(f\"{DATASET}.penguins_pipeline\")" ] }, { @@ -942,7 +4396,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "metadata": { "id": "QwumLUKmVpuH" }, @@ -963,6 +4417,18 @@ "kernelspec": { "display_name": "Python 3", "name": "python3" + }, + "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.11.1" } }, "nbformat": 4, diff --git a/notebooks/location/regionalized.ipynb b/notebooks/location/regionalized.ipynb index 86f43b1dd6..c05d27c24e 100644 --- a/notebooks/location/regionalized.ipynb +++ b/notebooks/location/regionalized.ipynb @@ -132,7 +132,14 @@ "source": [ "import bigframes.pandas\n", "\n", + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", "bigframes.pandas.options.bigquery.project = PROJECT\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", "bigframes.pandas.options.bigquery.location = BQ_LOCATION" ] }, diff --git a/notebooks/regression/bq_dataframes_ml_linear_regression.ipynb b/notebooks/regression/bq_dataframes_ml_linear_regression.ipynb index 675416f6ea..347a3e8cff 100644 --- a/notebooks/regression/bq_dataframes_ml_linear_regression.ipynb +++ b/notebooks/regression/bq_dataframes_ml_linear_regression.ipynb @@ -340,7 +340,7 @@ }, "outputs": [], "source": [ - "import bigframes.pandas as bf" + "import bigframes.pandas as bpd" ] }, { @@ -360,8 +360,15 @@ }, "outputs": [], "source": [ - "bf.options.bigquery.project = PROJECT_ID\n", - "bf.options.bigquery.location = REGION" + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", + "bpd.options.bigquery.project = PROJECT_ID\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", + "bpd.options.bigquery.location = REGION" ] }, { @@ -370,7 +377,7 @@ "id": "D21CoOlfFTYI" }, "source": [ - "If you want to reset the location of the created DataFrame or Series objects, reset the session by executing `bf.close_session()`. After that, you can reuse `bf.options.bigquery.location` to specify another location." + "If you want to reset the location of the created DataFrame or Series objects, reset the session by executing `bpd.close_session()`. After that, you can reuse `bpd.options.bigquery.location` to specify another location." ] }, { @@ -392,7 +399,7 @@ }, "outputs": [], "source": [ - "df = bf.read_gbq(\"bigquery-public-data.ml_datasets.penguins\")" + "df = bpd.read_gbq(\"bigquery-public-data.ml_datasets.penguins\")" ] }, { diff --git a/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb b/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb index cbbcc57aec..87b8f9c0b6 100644 --- a/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb +++ b/notebooks/visualization/bq_dataframes_covid_line_graphs.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "id": "9GIt_orUtNvA" }, @@ -129,7 +129,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "id": "4aooKMmnxrWF" }, @@ -151,7 +151,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "id": "bk03Rt_HyGx-" }, @@ -200,16 +200,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "id": "R7STCS8xB5d2" }, "outputs": [], "source": [ - "import bigframes.pandas as bf\n", + "import bigframes.pandas as bpd\n", "\n", - "bf.options.bigquery.project = PROJECT_ID\n", - "bf.options.bigquery.location = REGION" + "# Note: The project option is not required in all environments.\n", + "# On BigQuery Studio, the project ID is automatically detected.\n", + "bpd.options.bigquery.project = PROJECT_ID\n", + "\n", + "# Note: The location option is not required.\n", + "# It defaults to the location of the first table or query\n", + "# passed to read_gbq(). For APIs where a location can't be\n", + "# auto-detected, the location defaults to the \"US\" location.\n", + "bpd.options.bigquery.location = REGION" ] }, { @@ -223,13 +230,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "zDSwoBo1CU3G" }, "outputs": [], "source": [ - "all_data = bf.read_gbq(\"bigquery-public-data.covid19_open_data.covid19_open_data\")" + "all_data = bpd.read_gbq(\"bigquery-public-data.covid19_open_data.covid19_open_data\")" ] }, { @@ -243,7 +250,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "id": "UjMT_qhjf8Fu" }, @@ -263,7 +270,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "id": "IaoUf57ZwrJ8" }, @@ -293,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "id": "tYDoaKgJChiq" }, @@ -323,11 +330,46 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "id": "gFbCgfFC2gHw" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 38e28079-9a84-4c28-a04c-cdc0afbb74b1 is DONE. 273.1 MB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Query job b1df794f-6d3f-4f05-8bcd-2da29f4eb402 is DONE. 372.9 MB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHRCAYAAACW3ZisAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB0BklEQVR4nO3deVyU1f4H8M/MAAOyCSqggPuuiLiDmpp71tVr2Z51S+8trVxatbJfy402U9u03SzNsptaVi6pWCq5L4hLuYKyiCCL7Myc3x/I8MwwM8zADM/Mw+f9evFyeOaZmXME5vnO93zPOSohhAARERGRQqjlbgARERGRIzG4ISIiIkVhcENERESKwuCGiIiIFIXBDRERESkKgxsiIiJSFAY3REREpCgMboiIiEhRGNwQERGRojC4ISIiIkVp1MHN77//jltuuQWtWrWCSqXCunXr7H4OIQTefvttdO7cGVqtFuHh4fjvf//r+MYSERGRTTzkboCcCgsLER0djQcffBCTJ0+u03PMmjULmzdvxttvv42oqCjk5OQgJyfHwS0lIiIiW6m4cWYllUqFtWvXYtKkSYZjpaWleO655/DNN98gNzcXPXv2xBtvvIHhw4cDAE6cOIFevXrh2LFj6NKlizwNJyIiIiONeliqNo8++igSExOxevVqHD16FFOmTMG4cePw999/AwB++ukntG/fHhs2bEC7du3Qtm1bTJs2jZkbIiIiGTG4sSAlJQVffPEF1qxZg6FDh6JDhw548sknMWTIEHzxxRcAgLNnz+LChQtYs2YNVqxYgeXLl+PAgQO47bbbZG49ERFR49Woa26sSUpKgk6nQ+fOnY2Ol5aWolmzZgAAvV6P0tJSrFixwnDeZ599hr59++LUqVMcqiIiIpIBgxsLrl27Bo1GgwMHDkCj0Rjd5+fnBwBo2bIlPDw8jAKgbt26AajM/DC4ISIiangMbiyIiYmBTqfD5cuXMXToULPnDB48GBUVFThz5gw6dOgAAPjrr78AAG3atGmwthIREVG1Rj1b6tq1azh9+jSAymDmnXfewYgRIxAcHIzWrVvj3nvvxa5du7Bw4ULExMQgKysLW7duRa9evTBhwgTo9Xr0798ffn5+WLx4MfR6PWbOnImAgABs3rxZ5t4RERE1To06uElISMCIESNqHL///vuxfPlylJeX49VXX8WKFStw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T09PxMTE4PTp02bvnzdvHvLy8gxfqampjmgyERHVExM35CyyZm6EEHjsscewdu1aJCQkoF27dnY/h06nQ1JSEm666Saz92u1Wmi12vo2lYiIHMze2VIsKCZbyRrczJw5E6tWrcL69evh7++PjIwMAEBgYCB8fHwAAFOnTkV4eDji4+MBAC+//DIGDRqEjh07Ijc3F2+99RYuXLiAadOmydYPIiKyH2tuyFlkDW6WLl0KABg+fLjR8S+++AIPPPAAACAlJQVqdfXo2dWrVzF9+nRkZGQgKCgIffv2xe7du9G9e/eGajYRETmAsDMVw1iIbCX7sFRtEhISjL5ftGgRFi1a5KQWERGRq+KwFNnKIQXFubm5jngaIiJqRBiskLPYHdy88cYb+Pbbbw3f33777WjWrBnCw8Nx5MgRhzaOiIiUy97YhrEQ2cru4GbZsmWIjIwEAGzZsgVbtmzBr7/+ivHjx+Opp55yeAOJiEiZmLkhZ7G75iYjI8MQ3GzYsAG33347xowZg7Zt22LgwIEObyARERGRPezO3AQFBRkWwtu4cSNGjRoFoLI4WKfTObZ1RESkWPauOMxMD9nK7szN5MmTcffdd6NTp07Izs7G+PHjAQCHDh1Cx44dHd5AIiJSJgYr5Cx2BzeLFi1C27ZtkZqaijfffBN+fn4AgPT0dMyYMcPhDSQiIiKyh93BjaenJ5588skax+fMmeOQBhERUePAxA05S53Wufnqq68wZMgQtGrVChcuXAAALF68GOvXr3do44iISME4LkVOYndws3TpUsydOxfjx49Hbm6uoYi4adOmWLx4saPbR0REBMD+AmRqvOwObt577z188skneO6556DRaAzH+/Xrh6SkJIc2joiIlIuhCjmL3cHNuXPnEBMTU+O4VqtFYWGhQxpFRETKx1Epcha7g5t27drh8OHDNY5v3LgR3bp1c0SbiIiIamIwRDaye7bU3LlzMXPmTJSUlEAIgb179+Kbb75BfHw8Pv30U2e0kYiIFIg1NOQsdgc306ZNg4+PD55//nkUFRXh7rvvRqtWrbBkyRLceeedzmgjEREpEIelyFnsDm4A4J577sE999yDoqIiXLt2DSEhIY5uFxERKRxjG3IWu2tuiouLUVRUBABo0qQJiouLsXjxYmzevNnhjSMiosald2RTuZtACmB3cDNx4kSsWLECAJCb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DH9/f6xbtw4nT550dPuIiEihqoelLG+/YCq7sAwAMO9/Sbi5VyuntY3cm92Zm48//hh33303wsPDERcXh40bN2LIkCHYv38/srKynNFGIiJSoKr6GdPNMu15LJE5dmduHn74YbRo0QJPPPEEZsyYAT8/P2e0i4iIGglL07/N7S1VhevdkDV2Z25++OEH3HPPPVi9ejVatGiBuLg4zJ8/H5s3b0ZRUZEz2khERApkbvsFNbdfIAewO3MzadIkTJo0CQCQl5eHP/74A2vWrMHNN98MtVrNKeJERGSTqtlSFncFV1kepmLehqypU0FxdnY2duzYgYSEBCQkJCA5ORlBQUEYOnSoo9tHRERKZa6gmIkbcgC7g5uoqCicOHECQUFBuOGGGzB9+nQMGzYMvXr1ckb7iIhI4YxXJbZvzRsic+pUUDxs2DD07NnTGe0hIqJGompoydr2C5aKillPTNbYHdzMnDkTAFBWVoZz586hQ4cO8PCo0+gWERE1YlUznizV3ADVdTlE9rB7tlRxcTEeeughNGnSBD169EBKSgoA4LHHHsPrr7/u8AYSEZGyqe1YxK8Kgx6yxu7g5tlnn8WRI0eQkJAAb29vw/FRo0bh22+/dWjjiIhIeYQQeGvTSfySlFF5wOJsKZXNwQ6RlN3jSevWrcO3336LQYMGGVW49+jRA2fOnHFo44iISHl2n8nGB9urrxdc54Ycze7MTVZWFkJCQmocLywsrHWreiIiorzicqPvTYuIjVha54ajUmSF3cFNv3798PPPPxu+rwpoPv30U8TGxjquZUREpEg+nhqj7422XDANZhjEUB3YPSz12muvYfz48Th+/DgqKiqwZMkSHD9+HLt378aOHTuc0UYiIlIQT43x52pLu4JbS+gw5iFr7M7cDBkyBIcPH0ZFRQWioqKwefNmhISEIDExEX379nVGG4mISEEq9Hqj761NBWc9MdVFnRao6dChAz755BNHt4WIiBqBcp1x3sXWbA2RrezO3BAREdVHuc44c6O2lLlRWQl2OC5FVticuVGr1bXOhlKpVKioqKh3o4iISLlqBjfmry3mN14gqp3Nwc3atWst3peYmIh3330XepNxVCIiIlNlFdZqbrhCMdWfzcHNxIkTaxw7deoUnn32Wfz000+455578PLLLzu0cUREpDw1am6sxDOW7uI6N2RNnWpu0tLS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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import matplotlib.pyplot as plt\n", "\n", @@ -380,7 +422,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "id": "LqqHzjty8jk0" }, @@ -400,7 +442,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "id": "g4MeM8Oe9Q6X" }, @@ -440,14 +482,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "id": "x95ZgBkyDMP4" }, "outputs": [], "source": [ - "bf.options.sampling.enable_downsampling = True # enable downsampling\n", - "bf.options.sampling.max_download_size = 5 # download only 5 mb of data" + "bpd.options.sampling.enable_downsampling = True # enable downsampling\n", + "bpd.options.sampling.max_download_size = 5 # download only 5 mb of data" ] }, { @@ -461,11 +503,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "id": "V0OK02D7PJSL" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "Query job 120a989f-4ce0-47e9-b051-a1a570ecd0e3 is DONE. 12.6 GB processed. Open Job" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "local_symptom_data = symptom_data.to_pandas(sampling_method=\"uniform\")" ] @@ -493,11 +548,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "id": "EG7qM3R18bOb" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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kJeXhwceeABTp07F6tWrAQAnTpzAyZMn8c477+Bf//oX3njjDezZswfXXntt15+wW8tUEkJizowZM5jBYGB/+MMf2LFjx9ibb77JOI7zrYI8a9YsdvXVV7Pvv/+eHTt2jN1///0sKSmJNTQ0MMYYKywsZM888wxjjLGSkhKWmJjIlEqlb3X222+/nd18883nbYfFYmGDBw9m06ZNY19//TU7fvw4++9//8t27NjBGGNs/fr1TKFQsJdeeokdPXqU/fWvf2UymYx9+eWXvnMAYNnZ2WzNmjXs+PHj7De/+Q3T6/WsoaGBeb1eVl1dzQwGA1u5ciWrrq5mdrvdtwpwU1MTY4yx1atXM4VCwaZMmcK2b9/Ojhw5wmw2GxswYABLTExkL7/8Mjt27Bi76667mMFgYHPmzGHr1q1jR48eZfPnz2cjR45koigyxhgrLS1lOp2OPffcc+zYsWNs+/btrKCggN16662+Ns+dO5eNGzeO7dy5k+3evZtNmTKFaTQa9txzz3XvD0tIBAFgGzZs8D3+6KOPGACm0+n8fuRyObvuuusYY4zdcccdDIDfKvN79uxhANiRI0e69vxheRWEkJgxY8YMNnXqVL9tF154IXvwwQfZ119/zQwGA3M6nX778/Ly2CuvvMIYY2zJkiXsqquuYowxtnLlSnb99dezcePGsU8//ZQxxtiQIUPY//3f/523Ha+88gqLi4vzBUnnmjJlCrvjjjv8tv34xz9mV155pe8xAPboo4/6HlutVgbA1xbGGDMajWz16tW+x8GCGQCspKTE77kGDBjAfvKTn/geV1dXMwDsscce823buXMnA8Cqq6sZY4zddttt7Je//KXfeb7++mvG8zxzOBzs6NGjDAD77rvvfPsPHz7MAFAwQ2LaucHM2rVrmUwmY0eOHGHHjx/3+2n99/L4448zuVzudx673c4A+G6uOosSgAnph/Lz8/0eZ2RkoK6uDnv37oXVakVSUpLffofDgbKyMgDAjBkz8Prrr0MQBGzbtg1XXHEF0tPTsXXrVuTn56O0tNSX4NeRkpISFBQUIDExMej+w4cP45e//KXftosvvhjPP/98u69Fp9PBYDCgrq7uvM/fllKpDHhPzj13WloaAGDs2LEB2+rq6pCeno69e/di3759fkNHjDGIoojy8nIcO3YMcrkcEyZM8O0fMWIE4uPju9ReQqJdQUEBBEFAXV0dpk2bFvSYiy++GF6vF2VlZcjLywMAHDt2DAAwYMCALj0fBTOE9EMKhcLvMcdxEEURVqsVGRkZ2Lp1a8DvtF5wp0+fDovFgqKiInz11Vd46qmnkJ6ejhUrVmDcuHHIzMzE0KFDz9sGjUYTjpfS7mvpCo1GEzQhuO25W/cH29b6fFarFb/61a/wm9/8JuBcubm5vi9qQvoCq9WK0tJS3+Py8nKUlJQgMTERw4YNw80334yf/exn+Otf/4qCggKcOXMGW7ZsQX5+Pq666irMmjULhYWF+MUvfoGVK1dCFEUsXrwYl19+OYYNG9altlACMCHEp7CwEDU1NZDL5RgyZIjfT3JyMgApqMnPz8eLL74IhUKBESNGYPr06SguLsZHH32EGTNmdOq58vPzUVJS0u7MhZEjR2L79u1+27Zv345Ro0Z170X2oMLCQhw6dCjgvRsyZAiUSiVGjBgBr9eLPXv2+H7n6NGjUVXzhpDO2r17NwoKClBQUABAKoNQUFCAxx9/HACwevVq/OxnP8P999+P4cOHY/78+fj++++Rm5sLAOB5Hh9++CGSk5Mxffp0XHXVVRg5ciTWrl3b5bZQzwwhxGfWrFmYPHky5s+fj7/85S8YNmwYqqqq8PHHH2PBggW44IILAEgzol544QXfrIPExESMHDkS//3vfztdQOvGG2/EU089hfnz52P58uXIyMhAcXExMjMzMXnyZPzud7/Dddddh4KCAsyaNQsffvgh1q9fjy+++KLHXn93Pfjgg7joootw99134/bbb4dOp8OhQ4fw+eef48UXX8Tw4cMxZ84c/OpXv8KqVasgl8tx7733hq2XipDeNHPmTEjpMsEpFAosW7YMy5Yta/eYzMxMvPfee91uC/XMEEJ8OI7DJ598gunTp+PnP/85hg0bhhtuuAEnT5705YcAUt6MIAh+uTEzZ84M2NYRpVKJzz77DKmpqbjyyisxduxYrFixAjKZDAAwf/58PP/883j22WcxevRovPLKK1i9enWnzx8J+fn52LZtG44dO4Zp06b57lIzMzN9x6xevRqZmZmYMWMGFi5ciF/+8pdITU2NYKsJiX0c6yisIoQQQgiJctQzQwghhJCYRsEMIaRHPPXUU9Dr9UF/OlrPhRBCuoqGmQghPaKxsbHdmUoajQZZWVm93CJCSF9FwQwhhBBCYhoNMxFCCCEkplEwQwghhJCYRsEMIYQQQmIaBTOEEEIIiWkUzBBCCCEkplEwQwghhJCYRsEMIYQQQmLa/wNhCyDCMi8TLQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import seaborn as sns\n", "\n", @@ -513,11 +589,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "id": "5nVy61rEGaM4" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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aW1tjZ9z8803izVr1ojdu3eLjz76SMyfP18UFRWJxsbGlMfJYGaAaW5uFhdffLHIy8sTdrtdXHHFFfELkRBC7N69WwAQ//nPf4QQQvznP/8RALr82r17txAiUt593HHHiby8PGG1WsW0adPEH//4R6GqagYe4ZE98sgjYuTIkcJgMIgTTzxRfPzxx/Hb5s2bJy677LKE81988UUxceJEYTAYxOTJk8U///nPhNs1TRN33nmnKCkpEUajUZx++uli+/btR+OhpEVvno9Ro0Z1+Vq4++67hRBCeL1eccYZZ4ihQ4cKvV4vRo0aJa6++uqceWMWonfPx4033hg/t6SkRJx11lkJ/TKEGFyvDyGE2LZtmwAg3n333U73leuvj+7eD2PPwWWXXSbmzZvX6WeOO+44YTAYxNixYxN67sT09Bxnu94+J/PmzevxfCEi5etlZWXCYDCIYcOGiQsvvFBUV1f3aZzcNZuIiIhyGnNmiIiIKKcxmCEiIqKcxmCGiIiIchqDGSIiIsppDGaIiIgopzGYISIiopzGYIaIiIhyGoMZIiIi6rX3338f55xzDsrLyyFJEl599dVe34cQAg8++CAmTpwIo9GIYcOG4b777uv1/TCYIaIB7aOPPsKUKVOg1+uxaNEirFmzBpIkobW1NdNDixs9ejRWrFiR6WEQ9UpbWxumTZuGRx99NOX7+PnPf44nn3wSDz74ILZt24bXX3+9007sydClPAIiohywZMkSHHfccXjrrbeQl5cHi8WCuro6OByOTA+NKKedeeaZOPPMM7u9PRAI4Pbbb8dzzz2H1tZWHHvssfjNb36DU089FQBQVVWFlStX4uuvv8akSZMARDZvTQVnZohoQKupqcFpp52G4cOHIz8/HwaDAaWlpZAkqcvzVVWFpmlHeZREA8/PfvYzrF+/Hs8//zy++uor/Nd//RcWLlyInTt3AgDeeOMNjB07Fv/4xz8wZswYjB49GldddRVaWlp6/bsYzBANMqeeeipuuOEG/PKXv0RhYSFKS0txzz33xG9vbW3FVVddhaFDh8Jut+O0007Dl19+CQBwOp1QFAWff/45AEDTNBQWFmLWrFnxn/+///s/jBgxIqmx7N+/HxdffDEKCwthtVoxY8YMfPLJJ/HbV65ciXHjxsFgMGDSpEn461//mvDzkiThySefxHnnnQeLxYIJEybg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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# similarly, for fever\n", "\n", @@ -528,11 +625,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "id": "-S1A9E3WGaYH" }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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RMwWoZGkxm8cq1atwpw5cwD4J81btGgR3nzzTbhcLkybNg1/+MMfmmxmOpvdbofVaoXNZmOTExERkUa05v4d02SmIzCZISIi0p7W3L87RQdgIiIiokgxmSEiIiJNYzJDREREmsZkhoiIiDSNyQwRERFpGpMZIiIi0jQmM0RERKRpTGaIiIhI05jMEBERkaYxmSEiIiJNYzJDREREmhZxMlNZWYlXX30VixcvRkVFBQBgx44dOH78eNSCIyIiImqJLpIXffvtt5gyZQqsVit++OEHzJs3D8nJyXjnnXdw5MgRvPbaa9GOk4iIiKhREdXMLFy4EHPmzMGhQ4dgMpmC2y+77DJ89tlnUQuOiIiIqCURJTPffPMN7rjjjgbbe/fujdLS0jYHRURERBSuiJIZo9EIu93eYPvBgwfRs2fPNgdFREREFK6Ikpkrr7wSjz76KDweDwBAkiQcOXIE9913H6655pqoBkhERETUnIiSmWeffRYOhwNpaWmoqanBpEmTMGjQICQmJuJ///d/ox0jERERUZMiGs1ktVrxySefYPPmzdi9ezccDgfOO+88TJkyJdrxERERETUromQmYPz48Rg/fjwA/7wzRERERB0tomamJ598En//+9+Dz6+99lqkpKSgd+/e2L17d9SCIyIiImpJRMnMH//4R2RlZQEAPvnkE3zyySf48MMPMWPGDPz617+OaoBEREREzYmomam0tDSYzLz//vu49tprMXXqVPTv3x9jxoyJaoBEREREzYmoZqZHjx44evQoAGD9+vXBjr9CCPh8vuhFR0RERNSCiGpmrr76atxwww0YPHgwysvLMWPGDADAzp07MWjQoKgGSERERNSciJKZ559/Hv3798fRo0fx1FNPISEhAQBQUlKCX/7yl1ENkIiIiKg5khBCxDqI9mS322G1WmGz2WCxWGIdDhEREYWhNffvsGtm1q1bhxkzZkCv12PdunXNlr3yyivDPSwRERFRm4RdMyPLMkpLS5GWlgZZbrrfsCRJnaoTMGtmiIiItKddamZUVW3070RERESxFNHQbCIiIqLOIqLRTI8++miz+x9++OGIgiEiIiJqrYiSmbVr14Y893g8KCoqgk6nQ3Z2NpMZIiIi6jARJTM7d+5ssM1ut2POnDmYNWtWm4MiIiIiClfU+sxYLBYsW7YMDz30ULQOSURERNSiqHYA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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# similarly, for bruise\n", "local_symptom_data[\"search_trends_bruise\"] = \\\n", @@ -590,7 +708,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.16" + "version": "3.11.1" } }, "nbformat": 4, From 8f6e955fc946db97c95ea012659432355b0cd12c Mon Sep 17 00:00:00 2001 From: Lily Zhang <32233490+junyazhang@users.noreply.github.com> Date: Mon, 18 Mar 2024 12:56:50 -0700 Subject: [PATCH 12/27] feat: support Series.dt.strftime (#453) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: support Series.dt.strftime * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md * address comments * fix imports * 🦉 Updates from OwlBot post-processor See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --------- Co-authored-by: Owl Bot --- bigframes/core/compile/scalar_op_compiler.py | 9 ++++ bigframes/operations/__init__.py | 9 ++++ bigframes/operations/datetimes.py | 8 +++- .../system/small/operations/test_datetimes.py | 47 +++++++++++++++++++ .../pandas/core/arrays/datetimelike.py | 38 +++++++++++++++ 5 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 third_party/bigframes_vendored/pandas/core/arrays/datetimelike.py diff --git a/bigframes/core/compile/scalar_op_compiler.py b/bigframes/core/compile/scalar_op_compiler.py index 67761c0330..c95d1ca45e 100644 --- a/bigframes/core/compile/scalar_op_compiler.py +++ b/bigframes/core/compile/scalar_op_compiler.py @@ -613,6 +613,15 @@ def second_op_impl(x: ibis_types.Value): return typing.cast(ibis_types.TimestampValue, x).second().cast(ibis_dtypes.int64) +@scalar_op_compiler.register_unary_op(ops.StrftimeOp, pass_op=True) +def strftime_op_impl(x: ibis_types.Value, op: ops.StrftimeOp): + return ( + typing.cast(ibis_types.TimestampValue, x) + .strftime(op.date_format) + .cast(ibis_dtypes.str) + ) + + @scalar_op_compiler.register_unary_op(ops.time_op) def time_op_impl(x: ibis_types.Value): return typing.cast(ibis_types.TimestampValue, x).time() diff --git a/bigframes/operations/__init__.py b/bigframes/operations/__init__.py index 37188e490e..c358d46ee1 100644 --- a/bigframes/operations/__init__.py +++ b/bigframes/operations/__init__.py @@ -415,6 +415,15 @@ def output_type(self, *input_types): return input_types[0] +@dataclasses.dataclass(frozen=True) +class StrftimeOp(UnaryOp): + name: typing.ClassVar[str] = "strftime" + date_format: str + + def output_type(self, *input_types): + return dtypes.STRING_DTYPE + + # Binary Ops fillna_op = create_binary_op(name="fillna") cliplower_op = create_binary_op(name="clip_lower") diff --git a/bigframes/operations/datetimes.py b/bigframes/operations/datetimes.py index 66ec347add..eb91bc0b20 100644 --- a/bigframes/operations/datetimes.py +++ b/bigframes/operations/datetimes.py @@ -17,6 +17,7 @@ import datetime as dt from typing import Optional +import bigframes_vendored.pandas.core.arrays.datetimelike as vendored_pandas_datetimelike import bigframes_vendored.pandas.core.indexes.accessor as vendordt from bigframes.core import log_adapter @@ -27,7 +28,9 @@ @log_adapter.class_logger class DatetimeMethods( - bigframes.operations.base.SeriesMethods, vendordt.DatetimeProperties + bigframes.operations.base.SeriesMethods, + vendordt.DatetimeProperties, + vendored_pandas_datetimelike.DatelikeOps, ): __doc__ = vendordt.DatetimeProperties.__doc__ @@ -88,3 +91,6 @@ def tz(self) -> Optional[dt.timezone]: def unit(self) -> str: # Assumption: pyarrow dtype return self._dtype.pyarrow_dtype.unit + + def strftime(self, date_format: str) -> series.Series: + return self._apply_unary_op(ops.StrftimeOp(date_format=date_format)) diff --git a/tests/system/small/operations/test_datetimes.py b/tests/system/small/operations/test_datetimes.py index 3882491ecb..854672585d 100644 --- a/tests/system/small/operations/test_datetimes.py +++ b/tests/system/small/operations/test_datetimes.py @@ -219,3 +219,50 @@ def test_dt_unit(scalars_dfs, col_name): pd_result = scalars_pandas_df[col_name].dt.unit assert bf_result == pd_result + + +@pytest.mark.parametrize( + ("column", "date_format"), + [ + ("timestamp_col", "%B %d, %Y, %r"), + ("timestamp_col", "%m-%d-%Y %H:%M"), + ("datetime_col", "%m-%d-%Y %H:%M"), + ("datetime_col", "%H:%M"), + ], +) +@skip_legacy_pandas +def test_dt_strftime(scalars_df_index, scalars_pandas_df_index, column, date_format): + bf_result = scalars_df_index[column].dt.strftime(date_format).to_pandas() + pd_result = scalars_pandas_df_index[column].dt.strftime(date_format) + pd.testing.assert_series_equal(bf_result, pd_result, check_dtype=False) + assert bf_result.dtype == "string[pyarrow]" + + +def test_dt_strftime_date(): + bf_series = bigframes.series.Series( + ["2014-08-15", "2215-08-15", "2016-02-29"] + ).astype("date32[day][pyarrow]") + + expected_result = pd.Series(["08/15/2014", "08/15/2215", "02/29/2016"]) + bf_result = bf_series.dt.strftime("%m/%d/%Y").to_pandas() + + pd.testing.assert_series_equal( + bf_result, expected_result, check_index_type=False, check_dtype=False + ) + assert bf_result.dtype == "string[pyarrow]" + + +def test_dt_strftime_time(): + bf_series = bigframes.series.Series( + [143542314, 345234512341, 75543252344, 626546437654754, 8543523452345234] + ).astype("time64[us][pyarrow]") + + expected_result = pd.Series( + ["00:02:23", "23:53:54", "20:59:03", "16:40:37", "08:57:32"] + ) + bf_result = bf_series.dt.strftime("%X").to_pandas() + + pd.testing.assert_series_equal( + bf_result, expected_result, check_index_type=False, check_dtype=False + ) + assert bf_result.dtype == "string[pyarrow]" diff --git a/third_party/bigframes_vendored/pandas/core/arrays/datetimelike.py b/third_party/bigframes_vendored/pandas/core/arrays/datetimelike.py new file mode 100644 index 0000000000..4f7e33909e --- /dev/null +++ b/third_party/bigframes_vendored/pandas/core/arrays/datetimelike.py @@ -0,0 +1,38 @@ +# Contains code from https://github.com/pandas-dev/pandas/blob/main/pandas/core/arrays/datetimelike.py + +from bigframes import constants + + +class DatelikeOps: + def strftime(self, date_format: str): + """ + Convert to string Series using specified date_format. + + Return a Series of formatted strings specified by date_format. Details + of the string format can be found in `BigQuery format elements doc + <%(https://cloud.google.com/bigquery/docs/reference/standard-sql/format-elements)s>`__. + + **Examples:** + + >>> import bigframes.pandas as bpd + >>> bpd.options.display.progress_bar = None + + >>> s = bpd.to_datetime( + ... ['2014-08-15 08:15:12', '2012-02-29 08:15:12+06:00', '2015-08-15 08:15:12+05:00'], + ... utc=True + ... ).astype("timestamp[us, tz=UTC][pyarrow]") + + >>> s.dt.strftime("%B %d, %Y, %r") + 0 August 15, 2014, 08:15:12 AM + 1 February 29, 2012, 02:15:12 AM + 2 August 15, 2015, 03:15:12 AM + Name: 0, dtype: string + + Args: + date_format (str): + Date format string (e.g. "%Y-%m-%d"). + + Returns: + bigframes.series.Series of formatted strings. + """ + raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) From 718a00c1fa8ac44b0d3a79a2217e5b12690785fb Mon Sep 17 00:00:00 2001 From: Chelsea Lin <124939984+chelsea-lin@users.noreply.github.com> Date: Mon, 18 Mar 2024 13:04:53 -0700 Subject: [PATCH 13/27] fix: series.(to_csv|to_json) leverages bq export (#452) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Tim Sweña (Swast) --- bigframes/dataframe.py | 12 ++--- bigframes/series.py | 20 ++++--- tests/system/small/test_series.py | 28 +++++++--- .../bigframes_vendored/pandas/core/generic.py | 4 +- .../bigframes_vendored/pandas/core/series.py | 53 ------------------- 5 files changed, 40 insertions(+), 77 deletions(-) diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index 5dae7a82f9..e8328b6047 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -2588,16 +2588,16 @@ def to_json( if "*" not in path_or_buf: raise NotImplementedError(ERROR_IO_REQUIRES_WILDCARD) - if lines is True and orient != "records": - raise ValueError( - "'lines' keyword is only valid when 'orient' is 'records'." - ) - # TODO(ashleyxu) Support lines=False for small tables with arrays and TO_JSON_STRING. # See: https://cloud.google.com/bigquery/docs/reference/standard-sql/json_functions#to_json_string if lines is False: raise NotImplementedError( - f"Only newline delimited JSON format is supported. {constants.FEEDBACK_LINK}" + f"Only newline-delimited JSON is supported. Add `lines=True` to your function call. {constants.FEEDBACK_LINK}" + ) + + if lines is True and orient != "records": + raise ValueError( + "'lines' keyword is only valid when 'orient' is 'records'." ) result_table = self._run_io_query( diff --git a/bigframes/series.py b/bigframes/series.py index ef2feb4f92..86afdd047c 100644 --- a/bigframes/series.py +++ b/bigframes/series.py @@ -1390,9 +1390,10 @@ def to_frame(self, name: blocks.Label = None) -> bigframes.dataframe.DataFrame: ) return bigframes.dataframe.DataFrame(block) - def to_csv(self, path_or_buf=None, **kwargs) -> typing.Optional[str]: - # TODO(b/280651142): Implement version that leverages bq export native csv support to bypass local pandas step. - return self.to_pandas().to_csv(path_or_buf, **kwargs) + def to_csv( + self, path_or_buf: str, sep=",", *, header: bool = True, index: bool = True + ) -> None: + return self.to_frame().to_csv(path_or_buf, sep=sep, header=header, index=index) def to_dict(self, into: type[dict] = dict) -> typing.Mapping: return typing.cast(dict, self.to_pandas().to_dict(into)) # type: ignore @@ -1402,14 +1403,17 @@ def to_excel(self, excel_writer, sheet_name="Sheet1", **kwargs) -> None: def to_json( self, - path_or_buf=None, + path_or_buf: str, orient: typing.Literal[ "split", "records", "index", "columns", "values", "table" ] = "columns", - **kwargs, - ) -> typing.Optional[str]: - # TODO(b/280651142): Implement version that leverages bq export native csv support to bypass local pandas step. - return self.to_pandas().to_json(path_or_buf, **kwargs) + *, + lines: bool = False, + index: bool = True, + ) -> None: + return self.to_frame().to_json( + path_or_buf=path_or_buf, orient=orient, lines=lines, index=index + ) def to_latex( self, buf=None, columns=None, header=True, index=True, **kwargs diff --git a/tests/system/small/test_series.py b/tests/system/small/test_series.py index e22037a1ce..584dc21956 100644 --- a/tests/system/small/test_series.py +++ b/tests/system/small/test_series.py @@ -2384,18 +2384,30 @@ def test_to_frame(scalars_dfs): assert_pandas_df_equal(bf_result, pd_result) -def test_to_json(scalars_df_index, scalars_pandas_df_index): - bf_result = scalars_df_index["int64_col"].to_json() - pd_result = scalars_pandas_df_index["int64_col"].to_json() +def test_to_json(gcs_folder, scalars_df_index, scalars_pandas_df_index): + path = gcs_folder + "test_series_to_json*.jsonl" + scalars_df_index["int64_col"].to_json(path, lines=True, orient="records") + gcs_df = pd.read_json(path, lines=True) - assert bf_result == pd_result + pd.testing.assert_series_equal( + gcs_df["int64_col"].astype(pd.Int64Dtype()), + scalars_pandas_df_index["int64_col"], + check_dtype=False, + check_index=False, + ) -def test_to_csv(scalars_df_index, scalars_pandas_df_index): - bf_result = scalars_df_index["int64_col"].to_csv() - pd_result = scalars_pandas_df_index["int64_col"].to_csv() +def test_to_csv(gcs_folder, scalars_df_index, scalars_pandas_df_index): + path = gcs_folder + "test_series_to_csv*.csv" + scalars_df_index["int64_col"].to_csv(path) + gcs_df = pd.read_csv(path) - assert bf_result == pd_result + pd.testing.assert_series_equal( + gcs_df["int64_col"].astype(pd.Int64Dtype()), + scalars_pandas_df_index["int64_col"], + check_dtype=False, + check_index=False, + ) def test_to_latex(scalars_df_index, scalars_pandas_df_index): diff --git a/third_party/bigframes_vendored/pandas/core/generic.py b/third_party/bigframes_vendored/pandas/core/generic.py index 7f8e1f7b53..9358dca17b 100644 --- a/third_party/bigframes_vendored/pandas/core/generic.py +++ b/third_party/bigframes_vendored/pandas/core/generic.py @@ -183,7 +183,7 @@ def to_json( *, index: bool = True, lines: bool = False, - ) -> str | None: + ) -> None: """Convert the object to a JSON string, written to Cloud Storage. Note NaN's and None will be converted to null and datetime objects @@ -241,7 +241,7 @@ def to_json( """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) - def to_csv(self, path_or_buf: str, *, index: bool = True) -> str | None: + def to_csv(self, path_or_buf: str, *, index: bool = True) -> None: """Write object to a comma-separated values (csv) file on Cloud Storage. Args: diff --git a/third_party/bigframes_vendored/pandas/core/series.py b/third_party/bigframes_vendored/pandas/core/series.py index ab96e731b9..6a4c7f0ad5 100644 --- a/third_party/bigframes_vendored/pandas/core/series.py +++ b/third_party/bigframes_vendored/pandas/core/series.py @@ -535,59 +535,6 @@ def to_xarray(self): """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) - def to_json( - self, - path_or_buf=None, - orient: Literal[ - "split", "records", "index", "columns", "values", "table" - ] = "columns", - **kwarg, - ) -> str | None: - """ - Convert the object to a JSON string. - - Note NaN's and None will be converted to null and datetime objects - will be converted to UNIX timestamps. - - Args: - path_or_buf (str, path object, file-like object, or None, default None): - String, path object (implementing os.PathLike[str]), or file-like - object implementing a write() function. If None, the result is - returned as a string. - orient ({"split", "records", "index", "columns", "values", "table"}, default "columns"): - Indication of expected JSON string format. - 'split' : dict like {{'index' -> [index], 'columns' -> [columns],'data' -> [values]}} - 'records' : list like [{{column -> value}}, ... , {{column -> value}}] - 'index' : dict like {{index -> {{column -> value}}}} - 'columns' : dict like {{column -> {{index -> value}}}} - 'values' : just the values array - 'table' : dict like {{'schema': {{schema}}, 'data': {{data}}}} - Describing the data, where data component is like ``orient='records'``. - - Returns: - None or str: If path_or_buf is None, returns the resulting json format as a - string. Otherwise returns None. - """ - raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) - - def to_csv(self, path_or_buf: str, *, index: bool = True) -> str | None: - """ - Write object to a comma-separated values (csv) file. - - Args: - path_or_buf (str, path object, file-like object, or None, default None): - String, path object (implementing os.PathLike[str]), or file-like - object implementing a write() function. If None, the result is - returned as a string. If a non-binary file object is passed, it should - be opened with `newline=''`, disabling universal newlines. If a binary - file object is passed, `mode` might need to contain a `'b'`. - - Returns: - None or str: If path_or_buf is None, returns the resulting csv format - as a string. Otherwise returns None. - """ - raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) - def agg(self, func): """ Aggregate using one or more operations over the specified axis. From d2d425a93aa9e96f3b71c3ca3b185f4b5eaf32ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Mon, 18 Mar 2024 15:12:21 -0500 Subject: [PATCH 14/27] feat: `read_gbq_table` supports `LIKE` as a operator in `filters` (#454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes internal issue 330149095 🦕 --- bigframes/session/__init__.py | 1 + tests/system/small/test_session.py | 12 ++++++++++++ third_party/bigframes_vendored/pandas/io/gbq.py | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/bigframes/session/__init__.py b/bigframes/session/__init__.py index 40831292de..4cb3c11859 100644 --- a/bigframes/session/__init__.py +++ b/bigframes/session/__init__.py @@ -318,6 +318,7 @@ def _to_query( valid_operators: Mapping[third_party_pandas_gbq.FilterOps, str] = { "in": "IN", "not in": "NOT IN", + "LIKE": "LIKE", "==": "=", ">": ">", "<": "<", diff --git a/tests/system/small/test_session.py b/tests/system/small/test_session.py index aba4a52c43..d0cd24e2be 100644 --- a/tests/system/small/test_session.py +++ b/tests/system/small/test_session.py @@ -327,6 +327,18 @@ def test_read_gbq_twice_with_same_timestamp(session, penguins_table_id): assert df3 is not None +def test_read_gbq_table_clustered_with_filter(session: bigframes.Session): + df = session.read_gbq_table( + "bigquery-public-data.cloud_storage_geo_index.landsat_index", + filters=[[("sensor_id", "LIKE", "OLI%")], [("sensor_id", "LIKE", "%TIRS")]], # type: ignore + columns=["sensor_id"], + ) + sensors = df.groupby(["sensor_id"]).agg("count").to_pandas(ordered=False) + assert "OLI" in sensors.index + assert "TIRS" in sensors.index + assert "OLI_TIRS" in sensors.index + + def test_read_gbq_wildcard(session: bigframes.Session): df = session.read_gbq("bigquery-public-data.noaa_gsod.gsod193*") assert df.shape == (348485, 32) diff --git a/third_party/bigframes_vendored/pandas/io/gbq.py b/third_party/bigframes_vendored/pandas/io/gbq.py index 1f31c530d2..74602b5af1 100644 --- a/third_party/bigframes_vendored/pandas/io/gbq.py +++ b/third_party/bigframes_vendored/pandas/io/gbq.py @@ -7,7 +7,7 @@ from bigframes import constants -FilterOps = Literal["in", "not in", "<", "<=", "==", "!=", ">=", ">"] +FilterOps = Literal["in", "not in", "<", "<=", "==", "!=", ">=", ">", "LIKE"] FilterType = Tuple[str, FilterOps, Any] FiltersType = Union[Iterable[FilterType], Iterable[Iterable[FilterType]]] @@ -112,7 +112,7 @@ def read_gbq( query results. filters (Union[Iterable[FilterType], Iterable[Iterable[FilterType]]], default ()): To filter out data. Filter syntax: [[(column, op, val), …],…] where - op is [==, >, >=, <, <=, !=, in, not in]. The innermost tuples + op is [==, >, >=, <, <=, !=, in, not in, LIKE]. The innermost tuples are transposed into a set of filters applied through an AND operation. The outer Iterable combines these sets of filters through an OR operation. A single Iterable of tuples can also From 874026da612bf08fbaf6d7dbfaa3325dc8a61500 Mon Sep 17 00:00:00 2001 From: Chelsea Lin <124939984+chelsea-lin@users.noreply.github.com> Date: Mon, 18 Mar 2024 17:50:07 -0700 Subject: [PATCH 15/27] fix: disable to_json and to_csv related tests (#462) * fix: disable series to_json and to_csv tests * disable the rest ones --- tests/system/small/test_dataframe_io.py | 3 +++ tests/system/small/test_series.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/tests/system/small/test_dataframe_io.py b/tests/system/small/test_dataframe_io.py index f9a0d2481b..adc729565e 100644 --- a/tests/system/small/test_dataframe_io.py +++ b/tests/system/small/test_dataframe_io.py @@ -115,6 +115,7 @@ def test_to_pandas_batches_w_correct_dtypes(scalars_df_default_index): pd.testing.assert_series_equal(actual, expected) +@pytest.mark.skip(reason="Disable to unblock kokoro tests") @pytest.mark.parametrize( ("index"), [True, False], @@ -163,6 +164,7 @@ def test_to_csv_index( pd.testing.assert_frame_equal(gcs_df, scalars_pandas_df) +@pytest.mark.skip(reason="Disable to unblock kokoro tests") def test_to_csv_tabs( scalars_dfs: Tuple[bigframes.dataframe.DataFrame, pd.DataFrame], gcs_folder: str, @@ -413,6 +415,7 @@ def test_to_json_index_invalid_lines( scalars_df.to_json(path, index=index) +@pytest.mark.skip(reason="Disable to unblock kokoro tests") @pytest.mark.parametrize( ("index"), [True, False], diff --git a/tests/system/small/test_series.py b/tests/system/small/test_series.py index 584dc21956..4ce3dcfe2c 100644 --- a/tests/system/small/test_series.py +++ b/tests/system/small/test_series.py @@ -2384,6 +2384,7 @@ def test_to_frame(scalars_dfs): assert_pandas_df_equal(bf_result, pd_result) +@pytest.mark.skip(reason="Disable to unblock kokoro tests") def test_to_json(gcs_folder, scalars_df_index, scalars_pandas_df_index): path = gcs_folder + "test_series_to_json*.jsonl" scalars_df_index["int64_col"].to_json(path, lines=True, orient="records") @@ -2397,6 +2398,7 @@ def test_to_json(gcs_folder, scalars_df_index, scalars_pandas_df_index): ) +@pytest.mark.skip(reason="Disable to unblock kokoro tests") def test_to_csv(gcs_folder, scalars_df_index, scalars_pandas_df_index): path = gcs_folder + "test_series_to_csv*.csv" scalars_df_index["int64_col"].to_csv(path) From 6611c2803f174edcf11c5606c56f3ec36c4ae3e5 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Mon, 18 Mar 2024 18:50:20 -0700 Subject: [PATCH 16/27] refactor: Reimplement implicit joiner at expression layer (#436) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- bigframes/core/__init__.py | 16 +- bigframes/core/compile/compiler.py | 2 - bigframes/core/compile/row_identity.py | 265 --------------------- bigframes/core/compile/single_column.py | 218 +++++++---------- bigframes/core/expression.py | 22 +- bigframes/core/ordering.py | 29 ++- bigframes/core/rewrite.py | 299 ++++++++++++++++++++++++ bigframes/operations/__init__.py | 6 +- tests/system/small/test_dataframe.py | 14 +- 9 files changed, 462 insertions(+), 409 deletions(-) delete mode 100644 bigframes/core/compile/row_identity.py create mode 100644 bigframes/core/rewrite.py diff --git a/bigframes/core/__init__.py b/bigframes/core/__init__.py index e4a60e08e1..02582b17ba 100644 --- a/bigframes/core/__init__.py +++ b/bigframes/core/__init__.py @@ -28,6 +28,7 @@ import bigframes.core.nodes as nodes from bigframes.core.ordering import OrderingColumnReference import bigframes.core.ordering as orderings +import bigframes.core.rewrite import bigframes.core.utils from bigframes.core.window_spec import WindowSpec import bigframes.dtypes @@ -351,14 +352,15 @@ def join( join_def: join_def.JoinDefinition, allow_row_identity_join: bool = False, ): - return ArrayValue( - nodes.JoinNode( - left_child=self.node, - right_child=other.node, - join=join_def, - allow_row_identity_join=allow_row_identity_join, - ) + join_node = nodes.JoinNode( + left_child=self.node, + right_child=other.node, + join=join_def, + allow_row_identity_join=allow_row_identity_join, ) + if allow_row_identity_join: + return ArrayValue(bigframes.core.rewrite.maybe_rewrite_join(join_node)) + return ArrayValue(join_node) def _uniform_sampling(self, fraction: float) -> ArrayValue: """Sampling the table on given fraction. diff --git a/bigframes/core/compile/compiler.py b/bigframes/core/compile/compiler.py index 4ced85352c..ec6c79db5f 100644 --- a/bigframes/core/compile/compiler.py +++ b/bigframes/core/compile/compiler.py @@ -66,7 +66,6 @@ def compile_join(node: nodes.JoinNode, ordered: bool = True): left=left_ordered, right=right_ordered, join=node.join, - allow_row_identity_join=node.allow_row_identity_join, ) else: left_unordered = compile_unordered_ir(node.left_child) @@ -75,7 +74,6 @@ def compile_join(node: nodes.JoinNode, ordered: bool = True): left=left_unordered, right=right_unordered, join=node.join, - allow_row_identity_join=node.allow_row_identity_join, ) diff --git a/bigframes/core/compile/row_identity.py b/bigframes/core/compile/row_identity.py deleted file mode 100644 index f46e2f9463..0000000000 --- a/bigframes/core/compile/row_identity.py +++ /dev/null @@ -1,265 +0,0 @@ -# Copyright 2023 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Helpers to join ArrayValue objects.""" - -from __future__ import annotations - -import functools -import typing - -import ibis -import ibis.expr.types as ibis_types - -import bigframes.constants as constants -import bigframes.core.compile.compiled as compiled -import bigframes.core.join_def as join_def -import bigframes.core.joins as joining -import bigframes.core.ordering as orderings - -SUPPORTED_ROW_IDENTITY_HOW = {"outer", "left", "inner"} - - -def join_by_row_identity_unordered( - left: compiled.UnorderedIR, - right: compiled.UnorderedIR, - join_def: join_def.JoinDefinition, -) -> compiled.UnorderedIR: - """Compute join when we are joining by row identity not a specific column.""" - if join_def.type not in SUPPORTED_ROW_IDENTITY_HOW: - raise NotImplementedError( - f"Only how='outer','left','inner' currently supported. {constants.FEEDBACK_LINK}" - ) - - if not left._table.equals(right._table): - raise ValueError( - "Cannot combine objects without an explicit join/merge key. " - f"Left based on: {left._table.compile()}, but " - f"right based on: {right._table.compile()}" - ) - - left_predicates = left._predicates - right_predicates = right._predicates - # TODO(tbergeron): Skip generating these for inner part of join - ( - left_relative_predicates, - right_relative_predicates, - ) = _get_relative_predicates(left_predicates, right_predicates) - - combined_predicates = [] - if left_predicates or right_predicates: - joined_predicates = _join_predicates( - left_predicates, right_predicates, join_type=join_def.type - ) - combined_predicates = list(joined_predicates) # builder expects mutable list - - left_mask = ( - left_relative_predicates if join_def.type in ["right", "outer"] else None - ) - right_mask = ( - right_relative_predicates if join_def.type in ["left", "outer"] else None - ) - - # Public mapping must use JOIN_NAME_REMAPPER to stay in sync with consumers of join result - map_left_id = join_def.get_left_mapping() - map_right_id = join_def.get_right_mapping() - joined_columns = [ - _mask_value(left._get_ibis_column(key), left_mask).name(map_left_id[key]) - for key in left.column_ids - ] + [ - _mask_value(right._get_ibis_column(key), right_mask).name(map_right_id[key]) - for key in right.column_ids - ] - - joined_expr = compiled.UnorderedIR( - left._table, - columns=joined_columns, - predicates=combined_predicates, - ) - return joined_expr - - -def join_by_row_identity_ordered( - left: compiled.OrderedIR, - right: compiled.OrderedIR, - join_def: join_def.JoinDefinition, -) -> compiled.OrderedIR: - """Compute join when we are joining by row identity not a specific column.""" - if join_def.type not in SUPPORTED_ROW_IDENTITY_HOW: - raise NotImplementedError( - f"Only how='outer','left','inner' currently supported. {constants.FEEDBACK_LINK}" - ) - - if not left._table.equals(right._table): - raise ValueError( - "Cannot combine objects without an explicit join/merge key. " - f"Left based on: {left._table.compile()}, but " - f"right based on: {right._table.compile()}" - ) - - left_predicates = left._predicates - right_predicates = right._predicates - # TODO(tbergeron): Skip generating these for inner part of join - ( - left_relative_predicates, - right_relative_predicates, - ) = _get_relative_predicates(left_predicates, right_predicates) - - combined_predicates = [] - if left_predicates or right_predicates: - joined_predicates = _join_predicates( - left_predicates, right_predicates, join_type=join_def.type - ) - combined_predicates = list(joined_predicates) # builder expects mutable list - - left_mask = ( - left_relative_predicates if join_def.type in ["right", "outer"] else None - ) - right_mask = ( - right_relative_predicates if join_def.type in ["left", "outer"] else None - ) - - # Public mapping must use JOIN_NAME_REMAPPER to stay in sync with consumers of join result - lpublicmapping = join_def.get_left_mapping() - rpublicmapping = join_def.get_right_mapping() - lhiddenmapping, rhiddenmapping = joining.JoinNameRemapper(namespace="hidden")( - left._hidden_column_ids, right._hidden_column_ids - ) - map_left_id = {**lpublicmapping, **lhiddenmapping} - map_right_id = {**rpublicmapping, **rhiddenmapping} - - joined_columns = [ - _mask_value(left._get_ibis_column(key), left_mask).name(map_left_id[key]) - for key in left.column_ids - ] + [ - _mask_value(right._get_ibis_column(key), right_mask).name(map_right_id[key]) - for key in right.column_ids - ] - - # If left isn't being masked, can just use left ordering - if not left_mask: - col_mapping = { - order_ref.column_id: map_left_id[order_ref.column_id] - for order_ref in left._ordering.ordering_value_columns - } - new_ordering = left._ordering.with_column_remap(col_mapping) - else: - ordering_columns = [ - col_ref.with_name(map_left_id[col_ref.column_id]) - for col_ref in left._ordering.ordering_value_columns - ] + [ - col_ref.with_name(map_right_id[col_ref.column_id]) - for col_ref in right._ordering.ordering_value_columns - ] - left_total_order_cols = frozenset( - map_left_id[col] for col in left._ordering.total_ordering_columns - ) - # Assume that left ordering is sufficient since 1:1 join over same base table - join_total_order_cols = left_total_order_cols - new_ordering = orderings.ExpressionOrdering( - tuple(ordering_columns), total_ordering_columns=join_total_order_cols - ) - - hidden_ordering_columns = [ - left._get_hidden_ordering_column(key.column_id).name(map_left_id[key.column_id]) - for key in left._ordering.ordering_value_columns - if key.column_id in left._hidden_ordering_column_names.keys() - ] + [ - right._get_hidden_ordering_column(key.column_id).name( - map_right_id[key.column_id] - ) - for key in right._ordering.ordering_value_columns - if key.column_id in right._hidden_ordering_column_names.keys() - ] - - joined_expr = compiled.OrderedIR( - left._table, - columns=joined_columns, - hidden_ordering_columns=hidden_ordering_columns, - ordering=new_ordering, - predicates=combined_predicates, - ) - return joined_expr - - -def _mask_value( - value: ibis_types.Value, - predicates: typing.Optional[typing.Sequence[ibis_types.BooleanValue]] = None, -): - if predicates: - return ( - ibis.case() - .when(_reduce_predicate_list(predicates), value) - .else_(ibis.null()) - .end() - ) - return value - - -def _join_predicates( - left_predicates: typing.Collection[ibis_types.BooleanValue], - right_predicates: typing.Collection[ibis_types.BooleanValue], - join_type: str = "outer", -) -> typing.Tuple[ibis_types.BooleanValue, ...]: - """Combines predicates lists for each side of a join.""" - if join_type == "outer": - if not left_predicates: - return () - if not right_predicates: - return () - # TODO(tbergeron): Investigate factoring out common predicates - joined_predicates = _reduce_predicate_list(left_predicates).__or__( - _reduce_predicate_list(right_predicates) - ) - return (joined_predicates,) - if join_type == "left": - return tuple(left_predicates) - if join_type == "inner": - _, right_relative_predicates = _get_relative_predicates( - left_predicates, right_predicates - ) - return (*left_predicates, *right_relative_predicates) - else: - raise ValueError( - f"Unsupported join_type: {join_type}. {constants.FEEDBACK_LINK}" - ) - - -def _get_relative_predicates( - left_predicates: typing.Collection[ibis_types.BooleanValue], - right_predicates: typing.Collection[ibis_types.BooleanValue], -) -> tuple[ - typing.Tuple[ibis_types.BooleanValue, ...], - typing.Tuple[ibis_types.BooleanValue, ...], -]: - """Get predicates that apply to only one side of the join. Not strictly necessary but simplifies resulting query.""" - left_relative_predicates = tuple(left_predicates) or () - right_relative_predicates = tuple(right_predicates) or () - if left_predicates and right_predicates: - # Factor out common predicates needed for left/right column masking - left_relative_predicates = tuple(set(left_predicates) - set(right_predicates)) - right_relative_predicates = tuple(set(right_predicates) - set(left_predicates)) - return (left_relative_predicates, right_relative_predicates) - - -def _reduce_predicate_list( - predicate_list: typing.Collection[ibis_types.BooleanValue], -) -> ibis_types.BooleanValue: - """Converts a list of predicates BooleanValues into a single BooleanValue.""" - if len(predicate_list) == 0: - raise ValueError("Cannot reduce empty list of predicates") - if len(predicate_list) == 1: - (item,) = predicate_list - return item - return functools.reduce(lambda acc, pred: acc.__and__(pred), predicate_list) diff --git a/bigframes/core/compile/single_column.py b/bigframes/core/compile/single_column.py index 7beebfcb66..31ebf87d17 100644 --- a/bigframes/core/compile/single_column.py +++ b/bigframes/core/compile/single_column.py @@ -23,7 +23,6 @@ import ibis.expr.types as ibis_types import bigframes.core.compile.compiled as compiled -import bigframes.core.compile.row_identity import bigframes.core.join_def as join_defs import bigframes.core.joins as joining import bigframes.core.ordering as orderings @@ -33,7 +32,6 @@ def join_by_column_ordered( left: compiled.OrderedIR, right: compiled.OrderedIR, join: join_defs.JoinDefinition, - allow_row_identity_join: bool = False, ) -> compiled.OrderedIR: """Join two expressions by column equality. @@ -51,90 +49,72 @@ def join_by_column_ordered( first the coalesced join keys, then, all the left columns, and finally, all the right columns. """ - if ( - allow_row_identity_join - and join.type in bigframes.core.compile.row_identity.SUPPORTED_ROW_IDENTITY_HOW - and left._table.equals(right._table) - # Make sure we're joining on exactly the same column(s), at least with - # regards to value its possible that they both have the same names but - # were modified in different ways. Ignore differences in the names. - and all( - left._get_ibis_column(lcol) - .name("index") - .equals(right._get_ibis_column(rcol).name("index")) - for lcol, rcol in join.conditions - ) - ): - return bigframes.core.compile.row_identity.join_by_row_identity_ordered( - left, right, join_def=join - ) - else: - l_hidden_mapping, r_hidden_mapping = joining.JoinNameRemapper( - namespace="hidden" - )(left._hidden_column_ids, right._hidden_column_ids) - l_mapping = {**join.get_left_mapping(), **l_hidden_mapping} - r_mapping = {**join.get_right_mapping(), **r_hidden_mapping} - - left_table = left._to_ibis_expr( - ordering_mode="unordered", - expose_hidden_cols=True, - col_id_overrides=l_mapping, - ) - right_table = right._to_ibis_expr( - ordering_mode="unordered", - expose_hidden_cols=True, - col_id_overrides=r_mapping, - ) - join_conditions = [ - value_to_join_key(left_table[l_mapping[left_index]]) - == value_to_join_key(right_table[r_mapping[right_index]]) - for left_index, right_index in join.conditions - ] - - combined_table = ibis.join( - left_table, - right_table, - predicates=join_conditions, - how=join.type, # type: ignore - ) - - # Preserve ordering accross joins. - ordering = join_orderings( - left._ordering, - right._ordering, - l_mapping, - r_mapping, - left_order_dominates=(join.type != "right"), - ) - - # We could filter out the original join columns, but predicates/ordering - # might still reference them in implicit joins. - columns = [ - combined_table[l_mapping[col.get_name()]] for col in left.columns - ] + [combined_table[r_mapping[col.get_name()]] for col in right.columns] - hidden_ordering_columns = [ - *[ - combined_table[l_hidden_mapping[col.get_name()]] - for col in left._hidden_ordering_columns - ], - *[ - combined_table[r_hidden_mapping[col.get_name()]] - for col in right._hidden_ordering_columns - ], - ] - return compiled.OrderedIR( - combined_table, - columns=columns, - hidden_ordering_columns=hidden_ordering_columns, - ordering=ordering, - ) + + l_hidden_mapping, r_hidden_mapping = joining.JoinNameRemapper(namespace="hidden")( + left._hidden_column_ids, right._hidden_column_ids + ) + l_mapping = {**join.get_left_mapping(), **l_hidden_mapping} + r_mapping = {**join.get_right_mapping(), **r_hidden_mapping} + + left_table = left._to_ibis_expr( + ordering_mode="unordered", + expose_hidden_cols=True, + col_id_overrides=l_mapping, + ) + right_table = right._to_ibis_expr( + ordering_mode="unordered", + expose_hidden_cols=True, + col_id_overrides=r_mapping, + ) + join_conditions = [ + value_to_join_key(left_table[l_mapping[left_index]]) + == value_to_join_key(right_table[r_mapping[right_index]]) + for left_index, right_index in join.conditions + ] + + combined_table = ibis.join( + left_table, + right_table, + predicates=join_conditions, + how=join.type, # type: ignore + ) + + # Preserve ordering accross joins. + ordering = join_orderings( + left._ordering, + right._ordering, + l_mapping, + r_mapping, + left_order_dominates=(join.type != "right"), + ) + + # We could filter out the original join columns, but predicates/ordering + # might still reference them in implicit joins. + columns = [combined_table[l_mapping[col.get_name()]] for col in left.columns] + [ + combined_table[r_mapping[col.get_name()]] for col in right.columns + ] + hidden_ordering_columns = [ + *[ + combined_table[l_hidden_mapping[col.get_name()]] + for col in left._hidden_ordering_columns + ], + *[ + combined_table[r_hidden_mapping[col.get_name()]] + for col in right._hidden_ordering_columns + ], + ] + return compiled.OrderedIR( + combined_table, + columns=columns, + hidden_ordering_columns=hidden_ordering_columns, + ordering=ordering, + ) def join_by_column_unordered( left: compiled.UnorderedIR, right: compiled.UnorderedIR, join: join_defs.JoinDefinition, - allow_row_identity_join: bool = False, ) -> compiled.UnorderedIR: """Join two expressions by column equality. @@ -152,54 +132,36 @@ def join_by_column_unordered( first the coalesced join keys, then, all the left columns, and finally, all the right columns. """ - if ( - allow_row_identity_join - and join.type in bigframes.core.compile.row_identity.SUPPORTED_ROW_IDENTITY_HOW - and left._table.equals(right._table) - # Make sure we're joining on exactly the same column(s), at least with - # regards to value its possible that they both have the same names but - # were modified in different ways. Ignore differences in the names. - and all( - left._get_ibis_column(lcol) - .name("index") - .equals(right._get_ibis_column(rcol).name("index")) - for lcol, rcol in join.conditions - ) - ): - return bigframes.core.compile.row_identity.join_by_row_identity_unordered( - left, right, join_def=join - ) - else: - # Value column mapping must use JOIN_NAME_REMAPPER to stay in sync with consumers of join result - l_mapping = join.get_left_mapping() - r_mapping = join.get_right_mapping() - left_table = left._to_ibis_expr( - col_id_overrides=l_mapping, - ) - right_table = right._to_ibis_expr( - col_id_overrides=r_mapping, - ) - join_conditions = [ - value_to_join_key(left_table[l_mapping[left_index]]) - == value_to_join_key(right_table[r_mapping[right_index]]) - for left_index, right_index in join.conditions - ] - - combined_table = ibis.join( - left_table, - right_table, - predicates=join_conditions, - how=join.type, # type: ignore - ) - # We could filter out the original join columns, but predicates/ordering - # might still reference them in implicit joins. - columns = [ - combined_table[l_mapping[col.get_name()]] for col in left.columns - ] + [combined_table[r_mapping[col.get_name()]] for col in right.columns] - return compiled.UnorderedIR( - combined_table, - columns=columns, - ) + # Value column mapping must use JOIN_NAME_REMAPPER to stay in sync with consumers of join result + l_mapping = join.get_left_mapping() + r_mapping = join.get_right_mapping() + left_table = left._to_ibis_expr( + col_id_overrides=l_mapping, + ) + right_table = right._to_ibis_expr( + col_id_overrides=r_mapping, + ) + join_conditions = [ + value_to_join_key(left_table[l_mapping[left_index]]) + == value_to_join_key(right_table[r_mapping[right_index]]) + for left_index, right_index in join.conditions + ] + + combined_table = ibis.join( + left_table, + right_table, + predicates=join_conditions, + how=join.type, # type: ignore + ) + # We could filter out the original join columns, but predicates/ordering + # might still reference them in implicit joins. + columns = [combined_table[l_mapping[col.get_name()]] for col in left.columns] + [ + combined_table[r_mapping[col.get_name()]] for col in right.columns + ] + return compiled.UnorderedIR( + combined_table, + columns=columns, + ) def value_to_join_key(value: ibis_types.Value): diff --git a/bigframes/core/expression.py b/bigframes/core/expression.py index ec9e698412..4c2ae461fd 100644 --- a/bigframes/core/expression.py +++ b/bigframes/core/expression.py @@ -18,7 +18,7 @@ import dataclasses import itertools import typing -from typing import Union +from typing import Mapping, Union import bigframes.dtypes as dtypes import bigframes.operations @@ -81,6 +81,11 @@ def output_type( ) -> dtypes.ExpressionType: ... + @abc.abstractmethod + def bind_all_variables(self, bindings: Mapping[str, Expression]) -> Expression: + """Replace all variables with expression given in `bindings`.""" + ... + @dataclasses.dataclass(frozen=True) class ScalarConstantExpression(Expression): @@ -99,6 +104,9 @@ def output_type( ) -> dtypes.ExpressionType: return self.dtype + def bind_all_variables(self, bindings: Mapping[str, Expression]) -> Expression: + return self + @dataclasses.dataclass(frozen=True) class UnboundVariableExpression(Expression): @@ -128,6 +136,12 @@ def output_type( else: raise ValueError("Type of variable has not been fixed.") + def bind_all_variables(self, bindings: Mapping[str, Expression]) -> Expression: + if self.id in bindings.keys(): + return bindings[self.id] + else: + raise ValueError(f"Variable {self.id} remains unbound") + @dataclasses.dataclass(frozen=True) class OpExpression(Expression): @@ -163,3 +177,9 @@ def output_type( map(lambda x: x.output_type(input_types=input_types), self.inputs) ) return self.op.output_type(*operand_types) + + def bind_all_variables(self, bindings: Mapping[str, Expression]) -> Expression: + return OpExpression( + self.op, + tuple(input.bind_all_variables(bindings) for input in self.inputs), + ) diff --git a/bigframes/core/ordering.py b/bigframes/core/ordering.py index 1fd5ab4e37..bbfc7cf9d8 100644 --- a/bigframes/core/ordering.py +++ b/bigframes/core/ordering.py @@ -23,6 +23,8 @@ import ibis.expr.datatypes as ibis_dtypes import ibis.expr.types as ibis_types +import bigframes.core.expression as expression + # TODO(tbergeron): Encode more efficiently ORDERING_ID_STRING_BASE: int = 10 # Sufficient to store any value up to 2^63 @@ -52,15 +54,38 @@ class OrderingColumnReference: direction: OrderingDirection = OrderingDirection.ASC na_last: bool = True - def with_name(self, name: str): + def with_name(self, name: str) -> OrderingColumnReference: return OrderingColumnReference(name, self.direction, self.na_last) - def with_reverse(self): + def with_reverse(self) -> OrderingColumnReference: return OrderingColumnReference( self.column_id, self.direction.reverse(), not self.na_last ) +@dataclass(frozen=True) +class OrderingExpression: + """ + An expression that defines a scalar value to order, a direction and a null behavior. Maps directly to ORDER BY expressions in GoogleSQL. + This is more of OrderingColumnReference which order on a previously projected column id instead of any scalar expression. + """ + + # TODO: Right now, expression trees requires projecting a value before it can be sorted on. If OrderByNode used this instead, we could avoid some such projections and simplify the tree. + scalar_expression: expression.Expression + direction: OrderingDirection = OrderingDirection.ASC + na_last: bool = True + + def remap_names(self, mapping: dict[str, str]) -> OrderingExpression: + return OrderingExpression( + self.scalar_expression.rename(mapping), self.direction, self.na_last + ) + + def with_reverse(self) -> OrderingExpression: + return OrderingExpression( + self.scalar_expression, self.direction.reverse(), not self.na_last + ) + + # Encoding classes specify additional properties for some ordering representations @dataclass(frozen=True) class StringEncoding: diff --git a/bigframes/core/rewrite.py b/bigframes/core/rewrite.py new file mode 100644 index 0000000000..a518108f4a --- /dev/null +++ b/bigframes/core/rewrite.py @@ -0,0 +1,299 @@ +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import dataclasses +import functools +import itertools +from typing import Optional, Sequence, Tuple + +import bigframes.core.expression as scalar_exprs +import bigframes.core.guid as guids +import bigframes.core.join_def as join_defs +import bigframes.core.nodes as nodes +import bigframes.core.ordering as order +import bigframes.operations as ops + +Selection = Tuple[Tuple[scalar_exprs.Expression, str], ...] + + +@dataclasses.dataclass(frozen=True) +class SquashedSelect: + """Squash together as many nodes as possible, separating out the projection, filter and reordering expressions.""" + + root: nodes.BigFrameNode + columns: Tuple[Tuple[scalar_exprs.Expression, str], ...] + predicate: Optional[scalar_exprs.Expression] + ordering: Tuple[order.OrderingExpression, ...] + + @classmethod + def from_node(cls, node: nodes.BigFrameNode) -> SquashedSelect: + if isinstance(node, nodes.ProjectionNode): + return cls.from_node(node.child).project(node.assignments) + elif isinstance(node, nodes.FilterNode): + return cls.from_node(node.child).filter(node.predicate) + elif isinstance(node, nodes.ReversedNode): + return cls.from_node(node.child).reverse() + elif isinstance(node, nodes.OrderByNode): + return cls.from_node(node.child).order_with(node.by) + else: + selection = tuple( + (scalar_exprs.UnboundVariableExpression(id), id) + for id in get_node_column_ids(node) + ) + return cls(node, selection, None, ()) + + def project( + self, projection: Tuple[Tuple[scalar_exprs.Expression, str], ...] + ) -> SquashedSelect: + lookup = {id: expr for expr, id in self.columns} + new_columns = tuple( + (expr.bind_all_variables(lookup), id) for expr, id in projection + ) + return SquashedSelect(self.root, new_columns, self.predicate, self.ordering) + + def filter(self, predicate: scalar_exprs.Expression) -> SquashedSelect: + lookup = {id: expr for expr, id in self.columns} + if self.predicate is None: + new_predicate = predicate.bind_all_variables(lookup) + else: + new_predicate = ops.and_op.as_expr( + self.predicate, predicate.bind_all_variables(lookup) + ) + return SquashedSelect(self.root, self.columns, new_predicate, self.ordering) + + def reverse(self) -> SquashedSelect: + new_ordering = tuple(expr.with_reverse() for expr in self.ordering) + return SquashedSelect(self.root, self.columns, self.predicate, new_ordering) + + def order_with(self, by: Tuple[order.OrderingColumnReference, ...]): + exprs_by_id = {id: expr for expr, id in self.columns} + as_order_exprs = [ + order.OrderingExpression( + exprs_by_id[ref.column_id], ref.direction, ref.na_last + ) + for ref in by + ] + new_ordering = (*as_order_exprs, *self.ordering) + return SquashedSelect(self.root, self.columns, self.predicate, new_ordering) + + def maybe_join( + self, right: SquashedSelect, join_def: join_defs.JoinDefinition + ) -> Optional[SquashedSelect]: + if join_def.type == "cross": + # Cannot convert cross join to projection + return None + + r_exprs_by_id = {id: expr for expr, id in right.columns} + l_exprs_by_id = {id: expr for expr, id in self.columns} + l_join_exprs = [l_exprs_by_id[cond.left_id] for cond in join_def.conditions] + r_join_exprs = [r_exprs_by_id[cond.right_id] for cond in join_def.conditions] + + if (self.root != right.root) or any( + l_expr != r_expr for l_expr, r_expr in zip(l_join_exprs, r_join_exprs) + ): + return None + + join_type = join_def.type + + # Mask columns and remap names to expected schema + lselection = self.columns + rselection = right.columns + if join_type == "inner": + new_predicate = and_predicates(self.predicate, right.predicate) + elif join_type == "outer": + new_predicate = or_predicates(self.predicate, right.predicate) + elif join_type == "left": + new_predicate = self.predicate + elif join_type == "right": + new_predicate = right.predicate + + l_relative, r_relative = relative_predicates(self.predicate, right.predicate) + lmask = l_relative if join_type in {"right", "outer"} else None + rmask = r_relative if join_type in {"left", "outer"} else None + if lmask is not None: + lselection = tuple((apply_mask(expr, lmask), id) for expr, id in lselection) + if rmask is not None: + rselection = tuple((apply_mask(expr, rmask), id) for expr, id in rselection) + new_columns = remap_names(join_def, lselection, rselection) + + # Reconstruct ordering + if join_type == "right": + new_ordering = right.ordering + elif join_type == "outer": + if lmask is not None: + prefix = order.OrderingExpression(lmask, order.OrderingDirection.DESC) + left_ordering = tuple( + order.OrderingExpression( + apply_mask(ref.scalar_expression, lmask), + ref.direction, + ref.na_last, + ) + for ref in self.ordering + ) + right_ordering = ( + tuple( + order.OrderingExpression( + apply_mask(ref.scalar_expression, rmask), + ref.direction, + ref.na_last, + ) + for ref in right.ordering + ) + if rmask + else right.ordering + ) + new_ordering = (prefix, *left_ordering, *right_ordering) + else: + new_ordering = self.ordering + elif join_type in {"inner", "left"}: + new_ordering = self.ordering + else: + raise ValueError(f"Unexpected join type {join_type}") + return SquashedSelect(self.root, new_columns, new_predicate, new_ordering) + + def expand(self) -> nodes.BigFrameNode: + # Safest to apply predicates first, as it may filter out inputs that cannot be handled by other expressions + root = ( + nodes.FilterNode(child=self.root, predicate=self.predicate) + if self.predicate + else self.root + ) + if self.ordering: + # Need this clumsy 3-node expansion as OrderByNode doesn't support expressions (yet?) + # Could also directly compile this whole class directly + ordering_assignments = [ + (ref.scalar_expression, guids.generate_guid()) for ref in self.ordering + ] + as_ordering_refs = tuple( + order.OrderingColumnReference(id, ref.direction, ref.na_last) + for ref, (_, id) in zip(self.ordering, ordering_assignments) + ) + extended_projection = nodes.ProjectionNode( + child=root, assignments=(*self.columns, *ordering_assignments) + ) + ordered_node = nodes.OrderByNode( + child=extended_projection, by=as_ordering_refs + ) + drop_ordering_selection = tuple( + (scalar_exprs.UnboundVariableExpression(id), id) + for _, id in self.columns + ) + pruned_node = nodes.ProjectionNode( + child=ordered_node, assignments=drop_ordering_selection + ) + return pruned_node + else: + return nodes.ProjectionNode(child=root, assignments=self.columns) + + +def maybe_rewrite_join(join_node: nodes.JoinNode) -> nodes.BigFrameNode: + left_side = SquashedSelect.from_node(join_node.left_child) + right_side = SquashedSelect.from_node(join_node.right_child) + joined = left_side.maybe_join(right_side, join_node.join) + if joined is not None: + return joined.expand() + else: + return join_node + + +def remap_names( + join: join_defs.JoinDefinition, lselection: Selection, rselection: Selection +) -> Selection: + new_selection: Selection = tuple() + l_exprs_by_id = {id: expr for expr, id in lselection} + r_exprs_by_id = {id: expr for expr, id in rselection} + for mapping in join.mappings: + if mapping.source_table == join_defs.JoinSide.LEFT: + expr = l_exprs_by_id[mapping.source_id] + else: # Right + expr = r_exprs_by_id[mapping.source_id] + id = mapping.destination_id + new_selection = (*new_selection, (expr, id)) + return new_selection + + +def and_predicates( + expr1: Optional[scalar_exprs.Expression], expr2: Optional[scalar_exprs.Expression] +) -> Optional[scalar_exprs.Expression]: + if expr1 is None: + return expr2 + if expr2 is None: + return expr1 + left_predicates = decompose_conjunction(expr1) + right_predicates = decompose_conjunction(expr2) + # remove common predicates + all_predicates = itertools.chain( + left_predicates, [p for p in right_predicates if p not in left_predicates] + ) + return merge_predicates(list(all_predicates)) + + +def or_predicates( + expr1: Optional[scalar_exprs.Expression], expr2: Optional[scalar_exprs.Expression] +) -> Optional[scalar_exprs.Expression]: + if (expr1 is None) or (expr2 is None): + return None + # TODO(tbergeron): Factor out common predicates + return ops.or_op.as_expr(expr1, expr2) + + +def relative_predicates( + expr1: Optional[scalar_exprs.Expression], expr2: Optional[scalar_exprs.Expression] +) -> Tuple[Optional[scalar_exprs.Expression], Optional[scalar_exprs.Expression]]: + left_predicates = decompose_conjunction(expr1) if expr1 else () + right_predicates = decompose_conjunction(expr2) if expr2 else () + left_relative = tuple( + pred for pred in left_predicates if pred not in right_predicates + ) + right_relative = tuple( + pred for pred in right_predicates if pred not in left_predicates + ) + return merge_predicates(left_relative), merge_predicates(right_relative) + + +def apply_mask( + expr: scalar_exprs.Expression, mask: scalar_exprs.Expression +) -> scalar_exprs.Expression: + return ops.where_op.as_expr(expr, mask, scalar_exprs.const(None)) + + +def merge_predicates( + predicates: Sequence[scalar_exprs.Expression], +) -> Optional[scalar_exprs.Expression]: + if len(predicates) == 0: + return None + + return functools.reduce(ops.and_op.as_expr, predicates) + + +def decompose_conjunction( + expr: scalar_exprs.Expression, +) -> Tuple[scalar_exprs.Expression, ...]: + if isinstance(expr, scalar_exprs.OpExpression) and isinstance( + expr.op, type(ops.and_op) + ): + return tuple( + itertools.chain.from_iterable(decompose_conjunction(i) for i in expr.inputs) + ) + else: + return (expr,) + + +def get_node_column_ids(node: nodes.BigFrameNode) -> Tuple[str, ...]: + # TODO: Convert to use node.schema once that has been merged + # Note: this actually compiles the node to get the schema + import bigframes.core + + return tuple(bigframes.core.ArrayValue(node).column_ids) diff --git a/bigframes/operations/__init__.py b/bigframes/operations/__init__.py index c358d46ee1..b122f1fe7c 100644 --- a/bigframes/operations/__init__.py +++ b/bigframes/operations/__init__.py @@ -30,15 +30,15 @@ class RowOp(typing.Protocol): @property def name(self) -> str: - raise NotImplementedError("RowOp abstract base class has no implementation") + ... @property def arguments(self) -> int: """The number of column argument the operation takes""" - raise NotImplementedError("RowOp abstract base class has no implementation") + ... def output_type(self, *input_types: dtypes.ExpressionType) -> dtypes.ExpressionType: - raise NotImplementedError("Abstract typing rule has no output type") + ... # These classes can be used to create simple ops that don't take local parameters diff --git a/tests/system/small/test_dataframe.py b/tests/system/small/test_dataframe.py index be4211a2fc..3714106860 100644 --- a/tests/system/small/test_dataframe.py +++ b/tests/system/small/test_dataframe.py @@ -2056,11 +2056,23 @@ def test_join_same_table(scalars_dfs, how): bf_df, pd_df = scalars_dfs bf_df_a = bf_df.set_index("int64_too")[["string_col", "int64_col"]] + bf_df_a = bf_df_a.sort_index() + bf_df_b = bf_df.set_index("int64_too")[["float64_col"]] + bf_df_b = bf_df_b[bf_df_b.float64_col > 0] + bf_df_b = bf_df_b.sort_values("float64_col") + bf_result = bf_df_a.join(bf_df_b, how=how).to_pandas() - pd_df_a = pd_df.set_index("int64_too")[["string_col", "int64_col"]] + + pd_df_a = pd_df.set_index("int64_too")[["string_col", "int64_col"]].sort_index() + pd_df_a = pd_df_a.sort_index() + pd_df_b = pd_df.set_index("int64_too")[["float64_col"]] + pd_df_b = pd_df_b[pd_df_b.float64_col > 0] + pd_df_b = pd_df_b.sort_values("float64_col") + pd_result = pd_df_a.join(pd_df_b, how=how) + assert_pandas_df_equal(bf_result, pd_result, ignore_order=True) From 3bab1a917a5833bd58b20071a229ee95cf86a251 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Mon, 18 Mar 2024 20:18:17 -0700 Subject: [PATCH 17/27] fix: df.drop_na preserves columns dtype (#457) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- bigframes/core/block_transforms.py | 37 +++++++---------------- bigframes/core/blocks.py | 45 ++++++++++++++++++---------- bigframes/core/indexes/index.py | 2 +- bigframes/dataframe.py | 10 +++---- bigframes/series.py | 10 +++---- tests/system/small/test_dataframe.py | 18 +++++++++-- 6 files changed, 66 insertions(+), 56 deletions(-) diff --git a/bigframes/core/block_transforms.py b/bigframes/core/block_transforms.py index 9cc0a05680..6b9a367f55 100644 --- a/bigframes/core/block_transforms.py +++ b/bigframes/core/block_transforms.py @@ -13,6 +13,7 @@ # limitations under the License. from __future__ import annotations +import functools import typing import pandas as pd @@ -307,7 +308,7 @@ def drop_duplicates( ) -> blocks.Block: block, dupe_indicator_id = indicate_duplicates(block, columns, keep) block, keep_indicator_id = block.apply_unary_op(dupe_indicator_id, ops.invert_op) - return block.filter(keep_indicator_id).drop_columns( + return block.filter_by_id(keep_indicator_id).drop_columns( (dupe_indicator_id, keep_indicator_id) ) @@ -459,32 +460,14 @@ def dropna( """ Drop na entries from block """ + predicates = [ops.notnull_op.as_expr(column_id) for column_id in column_ids] + if len(predicates) == 0: + return block if how == "any": - filtered_block = block - for column in column_ids: - filtered_block, result_id = filtered_block.apply_unary_op( - column, ops.notnull_op - ) - filtered_block = filtered_block.filter(result_id) - filtered_block = filtered_block.drop_columns([result_id]) - return filtered_block + predicate = functools.reduce(ops.and_op.as_expr, predicates) else: # "all" - filtered_block = block - predicate = None - for column in column_ids: - filtered_block, partial_predicate = filtered_block.apply_unary_op( - column, ops.notnull_op - ) - if predicate: - filtered_block, predicate = filtered_block.apply_binary_op( - partial_predicate, predicate, ops.or_op - ) - else: - predicate = partial_predicate - if predicate: - filtered_block = filtered_block.filter(predicate) - filtered_block = filtered_block.select_columns(block.value_columns) - return filtered_block + predicate = functools.reduce(ops.or_op.as_expr, predicates) + return block.filter(predicate) def nsmallest( @@ -513,7 +496,7 @@ def nsmallest( window_spec=windows.WindowSpec(ordering=tuple(order_refs)), ) block, condition = block.project_expr(ops.le_op.as_expr(counter, ex.const(n))) - block = block.filter(condition) + block = block.filter_by_id(condition) return block.drop_columns([counter, condition]) @@ -543,7 +526,7 @@ def nlargest( window_spec=windows.WindowSpec(ordering=tuple(order_refs)), ) block, condition = block.project_expr(ops.le_op.as_expr(counter, ex.const(n))) - block = block.filter(condition) + block = block.filter_by_id(condition) return block.drop_columns([counter, condition]) diff --git a/bigframes/core/blocks.py b/bigframes/core/blocks.py index 375ce7e7e0..0ebbe48cc4 100644 --- a/bigframes/core/blocks.py +++ b/bigframes/core/blocks.py @@ -37,6 +37,7 @@ import bigframes.constants as constants import bigframes.core as core import bigframes.core.expression as ex +import bigframes.core.expression as scalars import bigframes.core.guid as guid import bigframes.core.join_def as join_defs import bigframes.core.ordering as ordering @@ -701,7 +702,7 @@ def project_expr( block = Block( array_val, index_columns=self.index_columns, - column_labels=[*self.column_labels, label], + column_labels=self.column_labels.insert(len(self.column_labels), label), index_labels=self.index.names, ) return (block, result_id) @@ -793,7 +794,7 @@ def apply_window_op( if skip_null_groups: for key in window_spec.grouping_keys: block, not_null_id = block.apply_unary_op(key, ops.notnull_op) - block = block.filter(not_null_id).drop_columns([not_null_id]) + block = block.filter_by_id(not_null_id).drop_columns([not_null_id]) result_id = guid.generate_guid() expr = block._expr.project_window_op( column, @@ -806,7 +807,9 @@ def apply_window_op( block = Block( expr, index_columns=self.index_columns, - column_labels=[*self.column_labels, result_label], + column_labels=self.column_labels.insert( + len(self.column_labels), result_label + ), index_labels=self._index_labels, ) return (block, result_id) @@ -850,7 +853,7 @@ def assign_label(self, column_id: str, new_label: Label) -> Block: ) return self.with_column_labels(new_labels) - def filter(self, column_id: str, keep_null: bool = False): + def filter_by_id(self, column_id: str, keep_null: bool = False): return Block( self._expr.filter_by_id(column_id, keep_null), index_columns=self.index_columns, @@ -858,6 +861,14 @@ def filter(self, column_id: str, keep_null: bool = False): index_labels=self.index.names, ) + def filter(self, predicate: scalars.Expression): + return Block( + self._expr.filter(predicate), + index_columns=self.index_columns, + column_labels=self.column_labels, + index_labels=self.index.names, + ) + def aggregate_all_and_stack( self, operation: agg_ops.UnaryAggregateOp, @@ -1086,8 +1097,11 @@ def summarize( unpivot_columns=tuple(columns), index_col_ids=tuple([label_col_id]), ) - labels = self._get_labels_for_columns(column_ids) - return Block(expr, column_labels=labels, index_columns=[label_col_id]) + return Block( + expr, + column_labels=self._get_labels_for_columns(column_ids), + index_columns=[label_col_id], + ) def corr(self): """Returns a block object to compute the self-correlation on this block.""" @@ -1156,10 +1170,10 @@ def _standard_stats(self, column_id) -> typing.Sequence[agg_ops.UnaryAggregateOp return stats - def _get_labels_for_columns(self, column_ids: typing.Sequence[str]): + def _get_labels_for_columns(self, column_ids: typing.Sequence[str]) -> pd.Index: """Get column label for value columns, or index name for index columns""" - lookup = self.col_id_to_label - return [lookup.get(col_id, None) for col_id in column_ids] + indices = [self.value_columns.index(col_id) for col_id in column_ids] + return self.column_labels.take(indices, allow_fill=False) def _normalize_expression( self, @@ -1255,7 +1269,7 @@ def _forward_slice(self, start: int = 0, stop=None, step: int = 1): for cond in conditions: block, cond_id = block.project_expr(cond) - block = block.filter(cond_id) + block = block.filter_by_id(cond_id) return block.select_columns(self.value_columns) @@ -1292,7 +1306,7 @@ def promote_offsets(self, label: Label = None) -> typing.Tuple[Block, str]: Block( expr, index_columns=self.index_columns, - column_labels=[label, *self.column_labels], + column_labels=self.column_labels.insert(0, label), index_labels=self._index_labels, ), result_id, @@ -1391,10 +1405,9 @@ def pivot( if values_in_index or len(values) > 1: value_labels = self._get_labels_for_columns(values) column_index = self._create_pivot_column_index(value_labels, columns_values) + return result_block.with_column_labels(column_index) else: - column_index = columns_values - - return result_block.with_column_labels(column_index) + return result_block.with_column_labels(columns_values) def stack(self, how="left", levels: int = 1): """Unpivot last column axis level into row axis""" @@ -1517,8 +1530,8 @@ def _column_type(self, col_id: str) -> bigframes.dtypes.Dtype: @staticmethod def _create_pivot_column_index( - value_labels: Sequence[typing.Hashable], columns_values: pd.Index - ): + value_labels: pd.Index, columns_values: pd.Index + ) -> pd.Index: index_parts = [] for value in value_labels: as_frame = columns_values.to_frame() diff --git a/bigframes/core/indexes/index.py b/bigframes/core/indexes/index.py index 328dd49397..c8cb07d339 100644 --- a/bigframes/core/indexes/index.py +++ b/bigframes/core/indexes/index.py @@ -378,7 +378,7 @@ def drop( block, condition_id = block.project_expr( ops.ne_op.as_expr(level_id, ex.const(labels)) ) - block = block.filter(condition_id, keep_null=True) + block = block.filter_by_id(condition_id, keep_null=True) block = block.drop_columns([condition_id]) return Index(block) diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index e8328b6047..ad71c9b6e4 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -525,7 +525,7 @@ def _getitem_bool_series(self, key: bigframes.series.Series) -> DataFrame: ) = self._block.join(key._block, how="left") block = combined_index filter_col_id = get_column_right[key._value_column] - block = block.filter(filter_col_id) + block = block.filter_by_id(filter_col_id) block = block.drop_columns([filter_col_id]) return DataFrame(block) @@ -1193,7 +1193,7 @@ def drop( block, condition_id = block.project_expr( ops.ne_op.as_expr(level_id, ex.const(index)) ) - block = block.filter(condition_id, keep_null=True).select_columns( + block = block.filter_by_id(condition_id, keep_null=True).select_columns( self._block.value_columns ) if columns: @@ -1214,7 +1214,7 @@ def _drop_by_index(self, index: indexes.Index) -> DataFrame: ops.isnull_op, ) - drop_block = drop_block.filter(drop_col) + drop_block = drop_block.filter_by_id(drop_col) original_columns = [ get_column_left[column] for column in self._block.value_columns ] @@ -1558,7 +1558,7 @@ def _filter_rows( label_string_id, ops.StrContainsRegexOp(pat=regex) ) - block = block.filter(mask_id) + block = block.filter_by_id(mask_id) block = block.select_columns(self._block.value_columns) return DataFrame(block) elif items is not None: @@ -1567,7 +1567,7 @@ def _filter_rows( block, mask_id = block.apply_unary_op( self._block.index_columns[0], ops.IsInOp(values=tuple(items)) ) - block = block.filter(mask_id) + block = block.filter_by_id(mask_id) block = block.select_columns(self._block.value_columns) return DataFrame(block) else: diff --git a/bigframes/series.py b/bigframes/series.py index 86afdd047c..8c3f1352f2 100644 --- a/bigframes/series.py +++ b/bigframes/series.py @@ -354,7 +354,7 @@ def drop( block, condition_id = block.project_expr( ops.ne_op.as_expr(level_id, ex.const(index)) ) - block = block.filter(condition_id, keep_null=True) + block = block.filter_by_id(condition_id, keep_null=True) block = block.drop_columns([condition_id]) return Series(block.select_column(self._value_column)) @@ -861,7 +861,7 @@ def mode(self) -> Series: max_value_count_col_id, ops.eq_op, ) - block = block.filter(is_mode_col_id) + block = block.filter_by_id(is_mode_col_id) # use temporary name for reset_index to avoid collision, restore after dropping extra columns block = ( block.with_index_labels(["mode_temp_internal"]) @@ -1032,7 +1032,7 @@ def __getitem__(self, indexer): return self.iloc[indexer] if isinstance(indexer, Series): (left, right, block) = self._align(indexer, "left") - block = block.filter(right) + block = block.filter_by_id(right) block = block.select_column(left) return Series(block) return self.loc[indexer] @@ -1304,7 +1304,7 @@ def filter( label_string_id, ops.StrContainsRegexOp(pat=regex) ) - block = block.filter(mask_id) + block = block.filter_by_id(mask_id) block = block.select_columns([self._value_column]) return Series(block) elif items is not None: @@ -1313,7 +1313,7 @@ def filter( block, mask_id = block.apply_unary_op( self._block.index_columns[0], ops.IsInOp(values=tuple(items)) ) - block = block.filter(mask_id) + block = block.filter_by_id(mask_id) block = block.select_columns([self._value_column]) return Series(block) else: diff --git a/tests/system/small/test_dataframe.py b/tests/system/small/test_dataframe.py index 3714106860..2048ada44f 100644 --- a/tests/system/small/test_dataframe.py +++ b/tests/system/small/test_dataframe.py @@ -842,6 +842,7 @@ def test_assign_callable_lambda(scalars_dfs): assert_pandas_df_equal(bf_result, pd_result) +@skip_legacy_pandas @pytest.mark.parametrize( ("axis", "how", "ignore_index"), [ @@ -852,8 +853,6 @@ def test_assign_callable_lambda(scalars_dfs): ], ) def test_df_dropna(scalars_dfs, axis, how, ignore_index): - if pd.__version__.startswith("1."): - pytest.skip("ignore_index parameter not supported in pandas 1.x.") scalars_df, scalars_pandas_df = scalars_dfs df = scalars_df.dropna(axis=axis, how=how, ignore_index=ignore_index) bf_result = df.to_pandas() @@ -864,6 +863,21 @@ def test_df_dropna(scalars_dfs, axis, how, ignore_index): pandas.testing.assert_frame_equal(bf_result, pd_result) +@skip_legacy_pandas +def test_df_dropna_range_columns(scalars_dfs): + scalars_df, scalars_pandas_df = scalars_dfs + scalars_df = scalars_df.copy() + scalars_pandas_df = scalars_pandas_df.copy() + scalars_df.columns = pandas.RangeIndex(0, len(scalars_df.columns)) + scalars_pandas_df.columns = pandas.RangeIndex(0, len(scalars_pandas_df.columns)) + + df = scalars_df.dropna() + bf_result = df.to_pandas() + pd_result = scalars_pandas_df.dropna() + + pandas.testing.assert_frame_equal(bf_result, pd_result) + + def test_df_interpolate(scalars_dfs): scalars_df, scalars_pandas_df = scalars_dfs columns = ["int64_col", "int64_too", "float64_col"] From 5dd9e6e23e3ffd07abbde70a43129238ff07d056 Mon Sep 17 00:00:00 2001 From: Shobhit Singh Date: Tue, 19 Mar 2024 14:11:58 +0000 Subject: [PATCH 18/27] test: do GCF cleanup in both presubmit and e2e tests (#423) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test: do GCF cleanup in both presubmit and e2e tests * use functions client from session * address review comments --------- Co-authored-by: Tim Sweña (Swast) --- tests/system/conftest.py | 67 ++++++- tests/system/large/test_remote_function.py | 219 ++++++--------------- tests/system/utils.py | 63 ++++++ 3 files changed, 185 insertions(+), 164 deletions(-) diff --git a/tests/system/conftest.py b/tests/system/conftest.py index 4b5ebc9d43..e6b241c9a3 100644 --- a/tests/system/conftest.py +++ b/tests/system/conftest.py @@ -21,6 +21,7 @@ import typing from typing import Dict, Optional +import google.api_core.exceptions import google.cloud.bigquery as bigquery import google.cloud.bigquery_connection_v1 as bigquery_connection_v1 import google.cloud.exceptions @@ -34,7 +35,15 @@ import test_utils.prefixer import bigframes -from tests.system.utils import convert_pandas_dtypes +import tests.system.utils + +# Use this to control the number of cloud functions being deleted in a single +# test session. This should help soften the spike of the number of mutations per +# minute tracked against a quota limit (default 60, increased to 120 for +# bigframes-dev project) by the Cloud Functions API +# We are running pytest with "-n 20". Let's say each session lasts about a +# minute, so we are setting a limit of 120/20 = 6 deletions per session. +MAX_NUM_FUNCTIONS_TO_DELETE_PER_SESSION = 6 CURRENT_DIR = pathlib.Path(__file__).parent DATA_DIR = CURRENT_DIR.parent / "data" @@ -348,7 +357,7 @@ def nested_pandas_df() -> pd.DataFrame: DATA_DIR / "nested.jsonl", lines=True, ) - convert_pandas_dtypes(df, bytes_col=True) + tests.system.utils.convert_pandas_dtypes(df, bytes_col=True) df = df.set_index("rowindex") return df @@ -400,7 +409,7 @@ def scalars_pandas_df_default_index() -> pd.DataFrame: DATA_DIR / "scalars.jsonl", lines=True, ) - convert_pandas_dtypes(df, bytes_col=True) + tests.system.utils.convert_pandas_dtypes(df, bytes_col=True) df = df.set_index("rowindex", drop=False) df.index.name = None @@ -1040,3 +1049,55 @@ def floats_bf(session, floats_pd): @pytest.fixture() def floats_product_bf(session, floats_product_pd): return session.read_pandas(floats_product_pd) + + +@pytest.fixture(scope="session", autouse=True) +def cleanup_cloud_functions(session, cloudfunctions_client, dataset_id_permanent): + """Clean up stale cloud functions.""" + permanent_endpoints = tests.system.utils.get_remote_function_endpoints( + session.bqclient, dataset_id_permanent + ) + delete_count = 0 + for cloud_function in tests.system.utils.get_cloud_functions( + cloudfunctions_client, + session.bqclient.project, + session.bqclient.location, + name_prefix="bigframes-", + ): + # Ignore bigframes cloud functions referred by the remote functions in + # the permanent dataset + if cloud_function.service_config.uri in permanent_endpoints: + continue + + # Ignore the functions less than one day old + age = datetime.now() - datetime.fromtimestamp( + cloud_function.update_time.timestamp() + ) + if age.days <= 0: + continue + + # Go ahead and delete + try: + tests.system.utils.delete_cloud_function( + cloudfunctions_client, cloud_function.name + ) + delete_count += 1 + if delete_count >= MAX_NUM_FUNCTIONS_TO_DELETE_PER_SESSION: + break + except google.api_core.exceptions.NotFound: + # This can happen when multiple pytest sessions are running in + # parallel. Two or more sessions may discover the same cloud + # function, but only one of them would be able to delete it + # successfully, while the other instance will run into this + # exception. Ignore this exception. + pass + except google.api_core.exceptions.ResourceExhausted: + # This can happen if we are hitting GCP limits, e.g. + # google.api_core.exceptions.ResourceExhausted: 429 Quota exceeded + # for quota metric 'Per project mutation requests' and limit + # 'Per project mutation requests per minute per region' of service + # 'cloudfunctions.googleapis.com' for consumer + # 'project_number:1084210331973'. + # [reason: "RATE_LIMIT_EXCEEDED" domain: "googleapis.com" ... + # Let's stop further clean up and leave it to later. + break diff --git a/tests/system/large/test_remote_function.py b/tests/system/large/test_remote_function.py index c0a1f6c4ec..f0b138c110 100644 --- a/tests/system/large/test_remote_function.py +++ b/tests/system/large/test_remote_function.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from datetime import datetime import importlib.util import inspect import math # must keep this at top level to test udf referring global import @@ -21,26 +20,19 @@ import tempfile import textwrap -from google.api_core.exceptions import BadRequest, NotFound, ResourceExhausted -from google.cloud import bigquery, functions_v2, storage +from google.api_core.exceptions import BadRequest, NotFound +from google.cloud import bigquery, storage import pandas import pytest import test_utils.prefixer import bigframes -from bigframes.functions.remote_function import ( - get_cloud_function_name, - get_remote_function_locations, +from bigframes.functions.remote_function import get_cloud_function_name +from tests.system.utils import ( + assert_pandas_df_equal, + delete_cloud_function, + get_cloud_functions, ) -from tests.system.utils import assert_pandas_df_equal - -# Use this to control the number of cloud functions being deleted in a single -# test session. This should help soften the spike of the number of mutations per -# minute tracked against a quota limit (default 60, increased to 120 for -# bigframes-dev project) by the Cloud Functions API -# We are running pytest with "-n 20". Let's say each session lasts about a -# minute, so we are setting a limit of 120/20 = 6 deletions per session. -_MAX_NUM_FUNCTIONS_TO_DELETE_PER_SESSION = 6 # NOTE: Keep this import at the top level to test global var behavior with # remote functions @@ -48,57 +40,8 @@ _team_euler = "Team Euler" -def get_remote_function_endpoints(bigquery_client, dataset_id): - """Get endpoints used by the remote functions in a datset""" - endpoints = set() - routines = bigquery_client.list_routines(dataset=dataset_id) - for routine in routines: - rf_options = routine._properties.get("remoteFunctionOptions") - if not rf_options: - continue - rf_endpoint = rf_options.get("endpoint") - if rf_endpoint: - endpoints.add(rf_endpoint) - return endpoints - - -def get_cloud_functions( - functions_client, project, location, name=None, name_prefix=None -): - """Get the cloud functions in the given project and location.""" - - assert ( - not name or not name_prefix - ), f"At most one of the {name.__name__} or {name_prefix.__name__} can be passed." - - _, location = get_remote_function_locations(location) - parent = f"projects/{project}/locations/{location}" - request = functions_v2.ListFunctionsRequest(parent=parent) - page_result = functions_client.list_functions(request=request) - for response in page_result: - # If name is provided and it does not match then skip - if bool(name): - full_name = parent + f"/functions/{name}" - if response.name != full_name: - continue - # If name prefix is provided and it does not match then skip - elif bool(name_prefix): - full_name_prefix = parent + f"/functions/{name_prefix}" - if not response.name.startswith(full_name_prefix): - continue - - yield response - - -def delete_cloud_function(functions_client, full_name): - """Delete a cloud function with the given fully qualified name.""" - request = functions_v2.DeleteFunctionRequest(name=full_name) - operation = functions_client.delete_function(request=request) - return operation - - def cleanup_remote_function_assets( - bigquery_client, functions_client, remote_udf, ignore_failures=True + bigquery_client, cloudfunctions_client, remote_udf, ignore_failures=True ): """Clean up the GCP assets behind a bigframes remote function.""" @@ -112,7 +55,9 @@ def cleanup_remote_function_assets( # Clean up cloud function try: - delete_cloud_function(functions_client, remote_udf.bigframes_cloud_function) + delete_cloud_function( + cloudfunctions_client, remote_udf.bigframes_cloud_function + ) except Exception: # By default don't raise exception in cleanup if not ignore_failures: @@ -169,62 +114,6 @@ def bq_cf_connection() -> str: return "bigframes-rf-conn" -@pytest.fixture(scope="module") -def functions_client() -> functions_v2.FunctionServiceClient: - """Cloud Functions client""" - return functions_v2.FunctionServiceClient() - - -@pytest.fixture(scope="module", autouse=True) -def cleanup_cloud_functions(session, functions_client, dataset_id_permanent): - """Clean up stale cloud functions.""" - permanent_endpoints = get_remote_function_endpoints( - session.bqclient, dataset_id_permanent - ) - delete_count = 0 - for cloud_function in get_cloud_functions( - functions_client, - session.bqclient.project, - session.bqclient.location, - name_prefix="bigframes-", - ): - # Ignore bigframes cloud functions referred by the remote functions in - # the permanent dataset - if cloud_function.service_config.uri in permanent_endpoints: - continue - - # Ignore the functions less than one day old - age = datetime.now() - datetime.fromtimestamp( - cloud_function.update_time.timestamp() - ) - if age.days <= 0: - continue - - # Go ahead and delete - try: - delete_cloud_function(functions_client, cloud_function.name) - delete_count += 1 - if delete_count >= _MAX_NUM_FUNCTIONS_TO_DELETE_PER_SESSION: - break - except NotFound: - # This can happen when multiple pytest sessions are running in - # parallel. Two or more sessions may discover the same cloud - # function, but only one of them would be able to delete it - # successfully, while the other instance will run into this - # exception. Ignore this exception. - pass - except ResourceExhausted: - # This can happen if we are hitting GCP limits, e.g. - # google.api_core.exceptions.ResourceExhausted: 429 Quota exceeded - # for quota metric 'Per project mutation requests' and limit - # 'Per project mutation requests per minute per region' of service - # 'cloudfunctions.googleapis.com' for consumer - # 'project_number:1084210331973'. - # [reason: "RATE_LIMIT_EXCEEDED" domain: "googleapis.com" ... - # Let's stop further clean up and leave it to later. - break - - @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_multiply_with_ibis( session, @@ -232,7 +121,6 @@ def test_remote_function_multiply_with_ibis( ibis_client, dataset_id, bq_cf_connection, - functions_client, ): try: @@ -274,7 +162,9 @@ def multiply(x, y): ) finally: # clean up the gcp assets created for the remote function - cleanup_remote_function_assets(session.bqclient, functions_client, multiply) + cleanup_remote_function_assets( + session.bqclient, session.cloudfunctionsclient, multiply + ) @pytest.mark.flaky(retries=2, delay=120) @@ -284,7 +174,6 @@ def test_remote_function_stringify_with_ibis( ibis_client, dataset_id, bq_cf_connection, - functions_client, ): try: @@ -319,12 +208,14 @@ def stringify(x): ) finally: # clean up the gcp assets created for the remote function - cleanup_remote_function_assets(session.bqclient, functions_client, stringify) + cleanup_remote_function_assets( + session.bqclient, session.cloudfunctionsclient, stringify + ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_decorator_with_bigframes_series( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -362,12 +253,14 @@ def square(x): assert_pandas_df_equal(bf_result, pd_result) finally: # clean up the gcp assets created for the remote function - cleanup_remote_function_assets(session.bqclient, functions_client, square) + cleanup_remote_function_assets( + session.bqclient, session.cloudfunctionsclient, square + ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_explicit_with_bigframes_series( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -407,13 +300,16 @@ def add_one(x): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, remote_add_one + session.bqclient, session.cloudfunctionsclient, remote_add_one ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_explicit_dataset_not_created( - session, scalars_dfs, dataset_id_not_created, bq_cf_connection, functions_client + session, + scalars_dfs, + dataset_id_not_created, + bq_cf_connection, ): try: @@ -451,12 +347,14 @@ def square(x): assert_pandas_df_equal(bf_result, pd_result) finally: # clean up the gcp assets created for the remote function - cleanup_remote_function_assets(session.bqclient, functions_client, square) + cleanup_remote_function_assets( + session.bqclient, session.cloudfunctionsclient, square + ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_udf_referring_outside_var( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: POSITIVE_SIGN = 1 @@ -502,12 +400,14 @@ def sign(num): assert_pandas_df_equal(bf_result, pd_result) finally: # clean up the gcp assets created for the remote function - cleanup_remote_function_assets(session.bqclient, functions_client, remote_sign) + cleanup_remote_function_assets( + session.bqclient, session.cloudfunctionsclient, remote_sign + ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_udf_referring_outside_import( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: import math as mymath @@ -548,13 +448,13 @@ def circumference(radius): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, remote_circumference + session.bqclient, session.cloudfunctionsclient, remote_circumference ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_udf_referring_global_var_and_import( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -597,7 +497,7 @@ def find_team(num): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, remote_find_team + session.bqclient, session.cloudfunctionsclient, remote_find_team ) @@ -607,7 +507,6 @@ def test_remote_function_restore_with_bigframes_series( scalars_dfs, dataset_id, bq_cf_connection, - functions_client, ): try: @@ -623,7 +522,7 @@ def add_one(x): # There should be no cloud function yet for the unique udf cloud_functions = list( get_cloud_functions( - functions_client, + session.cloudfunctionsclient, session.bqclient.project, session.bqclient.location, name=add_one_uniq_cf_name, @@ -644,7 +543,7 @@ def add_one(x): # There should have been excactly one cloud function created at this point cloud_functions = list( get_cloud_functions( - functions_client, + session.cloudfunctionsclient, session.bqclient.project, session.bqclient.location, name=add_one_uniq_cf_name, @@ -684,7 +583,7 @@ def inner_test(): # Let's delete the cloud function while not touching the bq remote function delete_operation = delete_cloud_function( - functions_client, cloud_functions[0].name + session.cloudfunctionsclient, cloud_functions[0].name ) delete_operation.result() assert delete_operation.done() @@ -692,7 +591,7 @@ def inner_test(): # There should be no cloud functions at this point for the uniq udf cloud_functions = list( get_cloud_functions( - functions_client, + session.cloudfunctionsclient, session.bqclient.project, session.bqclient.location, name=add_one_uniq_cf_name, @@ -714,7 +613,7 @@ def inner_test(): # There should be excactly one cloud function again cloud_functions = list( get_cloud_functions( - functions_client, + session.cloudfunctionsclient, session.bqclient.project, session.bqclient.location, name=add_one_uniq_cf_name, @@ -731,13 +630,13 @@ def inner_test(): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, remote_add_one + session.bqclient, session.cloudfunctionsclient, remote_add_one ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_udf_mask_default_value( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -771,13 +670,13 @@ def is_odd(num): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, is_odd_remote + session.bqclient, session.cloudfunctionsclient, is_odd_remote ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_udf_mask_custom_value( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -814,14 +713,12 @@ def is_odd(num): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, is_odd_remote + session.bqclient, session.cloudfunctionsclient, is_odd_remote ) @pytest.mark.flaky(retries=2, delay=120) -def test_remote_udf_lambda( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client -): +def test_remote_udf_lambda(session, scalars_dfs, dataset_id, bq_cf_connection): try: add_one_lambda = lambda x: x + 1 # noqa: E731 @@ -858,13 +755,13 @@ def test_remote_udf_lambda( finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, add_one_lambda_remote + session.bqclient, session.cloudfunctionsclient, add_one_lambda_remote ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_with_explicit_name( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -915,13 +812,13 @@ def square(x): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, square_remote + session.bqclient, session.cloudfunctionsclient, square_remote ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_with_external_package_dependencies( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -960,13 +857,13 @@ def pd_np_foo(x): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, pd_np_foo_remote + session.bqclient, session.cloudfunctionsclient, pd_np_foo_remote ) @pytest.mark.flaky(retries=2, delay=120) def test_remote_function_with_explicit_name_reuse( - session, scalars_dfs, dataset_id, bq_cf_connection, functions_client + session, scalars_dfs, dataset_id, bq_cf_connection ): try: @@ -1113,13 +1010,13 @@ def plusone(x): finally: # clean up the gcp assets created for the remote function cleanup_remote_function_assets( - session.bqclient, functions_client, square_remote1 + session.bqclient, session.cloudfunctionsclient, square_remote1 ) cleanup_remote_function_assets( - session.bqclient, functions_client, square_remote2 + session.bqclient, session.cloudfunctionsclient, square_remote2 ) cleanup_remote_function_assets( - session.bqclient, functions_client, plusone_remote + session.bqclient, session.cloudfunctionsclient, plusone_remote ) for dir_ in dirs_to_cleanup: shutil.rmtree(dir_) diff --git a/tests/system/utils.py b/tests/system/utils.py index a4647b4f51..8ea49ed7e2 100644 --- a/tests/system/utils.py +++ b/tests/system/utils.py @@ -15,13 +15,19 @@ import base64 import decimal import functools +from typing import Iterable, Optional, Set import geopandas as gpd # type: ignore +import google.api_core.operation +from google.cloud import bigquery, functions_v2 +from google.cloud.functions_v2.types import functions import numpy as np import pandas as pd import pyarrow as pa # type: ignore import pytest +from bigframes.functions import remote_function + def skip_legacy_pandas(test): @functools.wraps(test) @@ -241,3 +247,60 @@ def assert_pandas_df_equal_pca(actual, expected, **kwargs): except AssertionError: # Allow for sign difference per column pd.testing.assert_series_equal(-actual[column], expected[column], **kwargs) + + +def get_remote_function_endpoints( + bigquery_client: bigquery.Client, dataset_id: str +) -> Set[str]: + """Get endpoints used by the remote functions in a datset""" + endpoints = set() + routines = bigquery_client.list_routines(dataset=dataset_id) + for routine in routines: + rf_options = routine._properties.get("remoteFunctionOptions") + if not rf_options: + continue + rf_endpoint = rf_options.get("endpoint") + if rf_endpoint: + endpoints.add(rf_endpoint) + return endpoints + + +def get_cloud_functions( + functions_client: functions_v2.FunctionServiceClient, + project: str, + location: str, + name: Optional[str] = None, + name_prefix: Optional[str] = None, +) -> Iterable[functions.ListFunctionsResponse]: + """Get the cloud functions in the given project and location.""" + + assert ( + not name or not name_prefix + ), "Either 'name' or 'name_prefix' can be passed but not both." + + _, location = remote_function.get_remote_function_locations(location) + parent = f"projects/{project}/locations/{location}" + request = functions_v2.ListFunctionsRequest(parent=parent) + page_result = functions_client.list_functions(request=request) + for response in page_result: + # If name is provided and it does not match then skip + if bool(name): + full_name = parent + f"/functions/{name}" + if response.name != full_name: + continue + # If name prefix is provided and it does not match then skip + elif bool(name_prefix): + full_name_prefix = parent + f"/functions/{name_prefix}" + if not response.name.startswith(full_name_prefix): + continue + + yield response + + +def delete_cloud_function( + functions_client: functions_v2.FunctionServiceClient, full_name: str +) -> google.api_core.operation.Operation: + """Delete a cloud function with the given fully qualified name.""" + request = functions_v2.DeleteFunctionRequest(name=full_name) + operation = functions_client.delete_function(request=request) + return operation From 340f0b5b41fc5150d73890c7f27ae68dc308e160 Mon Sep 17 00:00:00 2001 From: Ashley Xu <139821907+ashleyxuu@users.noreply.github.com> Date: Tue, 19 Mar 2024 09:03:25 -0700 Subject: [PATCH 19/27] docs: add the pages for at and iat indexers (#456) --- docs/reference/bigframes.pandas/indexers.rst | 28 +++++++++++++++++++ docs/templates/toc.yml | 8 ++++++ .../bigframes_vendored/pandas/core/frame.py | 12 ++++++-- .../bigframes_vendored/pandas/core/series.py | 12 ++++++-- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/docs/reference/bigframes.pandas/indexers.rst b/docs/reference/bigframes.pandas/indexers.rst index a7388bcb6b..602b6de837 100644 --- a/docs/reference/bigframes.pandas/indexers.rst +++ b/docs/reference/bigframes.pandas/indexers.rst @@ -3,6 +3,34 @@ Indexers ========= +AtDataFrameIndexer +-------------------- +.. autoclass:: bigframes.core.indexers.AtDataFrameIndexer + :members: + :inherited-members: + :undoc-members: + +AtSeriesIndexer +-------------------- +.. autoclass:: bigframes.core.indexers.AtSeriesIndexer + :members: + :inherited-members: + :undoc-members: + +IatDataFrameIndexer +-------------------- +.. autoclass:: bigframes.core.indexers.IatDataFrameIndexer + :members: + :inherited-members: + :undoc-members: + +IatSeriesIndexer +-------------------- +.. autoclass:: bigframes.core.indexers.IatSeriesIndexer + :members: + :inherited-members: + :undoc-members: + ILocDataFrameIndexer -------------------- .. autoclass:: bigframes.core.indexers.ILocDataFrameIndexer diff --git a/docs/templates/toc.yml b/docs/templates/toc.yml index 224b535416..c07e6141f1 100644 --- a/docs/templates/toc.yml +++ b/docs/templates/toc.yml @@ -41,6 +41,14 @@ uid: bigframes.core.groupby.SeriesGroupBy name: Groupby - items: + - name: AtDataFrameIndexer + uid: bigframes.core.indexers.AtDataFrameIndexer + - name: AtSeriesIndexer + uid: bigframes.core.indexers.AtSeriesIndexer + - name: IatDataFrameIndexer + uid: bigframes.core.indexers.IatDataFrameIndexer + - name: IatSeriesIndexer + uid: bigframes.core.indexers.IatSeriesIndexer - name: ILocDataFrameIndexer uid: bigframes.core.indexers.ILocDataFrameIndexer - name: IlocSeriesIndexer diff --git a/third_party/bigframes_vendored/pandas/core/frame.py b/third_party/bigframes_vendored/pandas/core/frame.py index 7793b31a21..4eceb8a2f1 100644 --- a/third_party/bigframes_vendored/pandas/core/frame.py +++ b/third_party/bigframes_vendored/pandas/core/frame.py @@ -5129,12 +5129,20 @@ def loc(self): @property def iat(self): - """Access a single value for a row/column pair by integer position.""" + """Access a single value for a row/column pair by integer position. + + Returns: + bigframes.core.indexers.IatDataFrameIndexer: Indexers object. + """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) @property def at(self): - """Access a single value for a row/column label pair.""" + """Access a single value for a row/column label pair. + + Returns: + bigframes.core.indexers.AtDataFrameIndexer: Indexers object. + """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) def dot(self, other): diff --git a/third_party/bigframes_vendored/pandas/core/series.py b/third_party/bigframes_vendored/pandas/core/series.py index 6a4c7f0ad5..7120c4d155 100644 --- a/third_party/bigframes_vendored/pandas/core/series.py +++ b/third_party/bigframes_vendored/pandas/core/series.py @@ -3278,12 +3278,20 @@ def loc(self): @property def iat(self): - """Access a single value for a row/column pair by integer position.""" + """Access a single value for a row/column pair by integer position. + + Returns: + bigframes.core.indexers.IatSeriesIndexer: Indexers object. + """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) @property def at(self): - """Access a single value for a row/column label pair.""" + """Access a single value for a row/column label pair. + + Returns: + bigframes.core.indexers.AtSeriesIndexer: Indexers object. + """ raise NotImplementedError(constants.ABSTRACT_METHOD_ERROR_MESSAGE) @property From 85fefa2f1d4dbe3e0c9d4ab8124cea88eb5df38f Mon Sep 17 00:00:00 2001 From: Ashley Xu <139821907+ashleyxuu@users.noreply.github.com> Date: Tue, 19 Mar 2024 10:06:10 -0700 Subject: [PATCH 20/27] docs: add code samples for `ml.metrics.r2_score` (#459) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes internal #330220122 🦕 --- .../sklearn/metrics/_regression.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/third_party/bigframes_vendored/sklearn/metrics/_regression.py b/third_party/bigframes_vendored/sklearn/metrics/_regression.py index 9740c540e9..be531a9b1c 100644 --- a/third_party/bigframes_vendored/sklearn/metrics/_regression.py +++ b/third_party/bigframes_vendored/sklearn/metrics/_regression.py @@ -42,6 +42,18 @@ def r2_score(y_true, y_pred, force_finite=True) -> float: these cases are replaced with 1.0 (perfect predictions) or 0.0 (imperfect predictions) respectively. + **Examples:** + + >>> import bigframes.pandas as bpd + >>> import bigframes.ml.metrics + >>> bpd.options.display.progress_bar = None + + >>> y_true = bpd.DataFrame([3, -0.5, 2, 7]) + >>> y_pred = bpd.DataFrame([2.5, 0.0, 2, 8]) + >>> r2_score = bigframes.ml.metrics.r2_score(y_true, y_pred) + >>> r2_score + 0.9486081370449679 + Args: y_true (Series or DataFrame of shape (n_samples,)): Ground truth (correct) target values. From 3971bd27c96b68b859399564dbb6abdb93de5f14 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Tue, 19 Mar 2024 10:31:34 -0700 Subject: [PATCH 21/27] fix: fix grouping series on multiple other series (#455) --- bigframes/series.py | 2 +- tests/system/small/test_series.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bigframes/series.py b/bigframes/series.py index 8c3f1352f2..d01ee88cf5 100644 --- a/bigframes/series.py +++ b/bigframes/series.py @@ -1195,7 +1195,7 @@ def _groupby_values( get_column_right, ) = block.join(key._block, how="inner" if dropna else "left") - value_col = get_column_left[self._value_column] + value_col = get_column_left[value_col] grouping_cols = [ *[get_column_left[value] for value in grouping_cols], get_column_right[key._value_column], diff --git a/tests/system/small/test_series.py b/tests/system/small/test_series.py index 4ce3dcfe2c..f63ea977ff 100644 --- a/tests/system/small/test_series.py +++ b/tests/system/small/test_series.py @@ -1313,9 +1313,15 @@ def test_any(scalars_dfs): def test_groupby_sum(scalars_dfs): scalars_df, scalars_pandas_df = scalars_dfs col_name = "int64_too" - bf_series = scalars_df[col_name].groupby(scalars_df["string_col"]).sum() + bf_series = ( + scalars_df[col_name] + .groupby([scalars_df["bool_col"], ~scalars_df["bool_col"]]) + .sum() + ) pd_series = ( - scalars_pandas_df[col_name].groupby(scalars_pandas_df["string_col"]).sum() + scalars_pandas_df[col_name] + .groupby([scalars_pandas_df["bool_col"], ~scalars_pandas_df["bool_col"]]) + .sum() ) # TODO(swast): Update groupby to use index based on group by key(s). bf_result = bf_series.to_pandas() From 73fe0f89a96557afc4225521654978b96a2291b3 Mon Sep 17 00:00:00 2001 From: Garrett Wu <6505921+GarrettWu@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:11:16 -0700 Subject: [PATCH 22/27] fix!: exclude remote models for .register() (#465) * fix: exclude remote models for .register() * fix mypy --- bigframes/ml/base.py | 1 + bigframes/ml/llm.py | 6 +++--- tests/system/small/ml/test_register.py | 17 ++++------------- 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/bigframes/ml/base.py b/bigframes/ml/base.py index 9001987e9a..e58ed4feef 100644 --- a/bigframes/ml/base.py +++ b/bigframes/ml/base.py @@ -90,6 +90,7 @@ def __repr__(self): return prettyprinter.pformat(self) +# TODO(garrettwu): refactor to reflect the actual property. Now the class contains .register() method. class Predictor(BaseEstimator): """A BigQuery DataFrames ML Model base class that can be used to predict outputs.""" diff --git a/bigframes/ml/llm.py b/bigframes/ml/llm.py index 79f6b90bfd..10c3cc51b2 100644 --- a/bigframes/ml/llm.py +++ b/bigframes/ml/llm.py @@ -48,7 +48,7 @@ @log_adapter.class_logger -class PaLM2TextGenerator(base.Predictor): +class PaLM2TextGenerator(base.BaseEstimator): """PaLM2 text generator LLM model. Args: @@ -258,7 +258,7 @@ def to_gbq(self, model_name: str, replace: bool = False) -> PaLM2TextGenerator: @log_adapter.class_logger -class PaLM2TextEmbeddingGenerator(base.Predictor): +class PaLM2TextEmbeddingGenerator(base.BaseEstimator): """PaLM2 text embedding generator LLM model. Args: @@ -418,7 +418,7 @@ def to_gbq( @log_adapter.class_logger -class GeminiTextGenerator(base.Predictor): +class GeminiTextGenerator(base.BaseEstimator): """Gemini text generator LLM model. Args: diff --git a/tests/system/small/ml/test_register.py b/tests/system/small/ml/test_register.py index bcf1f4a5b0..6d8ff0a712 100644 --- a/tests/system/small/ml/test_register.py +++ b/tests/system/small/ml/test_register.py @@ -14,6 +14,8 @@ from typing import cast +import pytest + from bigframes.ml import core, imported, linear_model, llm @@ -54,19 +56,8 @@ def test_linear_reg_register_with_params( def test_palm2_text_generator_register( ephemera_palm2_text_generator_model: llm.PaLM2TextGenerator, ): - model = ephemera_palm2_text_generator_model - model.register() - - model_name = "bigframes_" + cast( - str, cast(core.BqmlModel, model._bqml_model).model.model_id - ) - # Only registered model contains the field, and the field includes project/dataset. Here only check model_id. - assert ( - model_name[:63] # truncated - in cast(core.BqmlModel, model._bqml_model).model.training_runs[-1][ - "vertexAiModelId" - ] - ) + with pytest.raises(AttributeError): + ephemera_palm2_text_generator_model.register() # type: ignore def test_imported_tensorflow_register( From 4e8e97d661078ed38d77be93b0bc1ad0fd52949c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Swe=C3=B1a=20=28Swast=29?= Date: Tue, 19 Mar 2024 13:30:45 -0500 Subject: [PATCH 23/27] feat: set `force=True` by default in `DataFrame.peek()` (#469) --- bigframes/dataframe.py | 12 ++++++------ tests/system/small/test_dataframe.py | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index ad71c9b6e4..c10a0c2456 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -1086,19 +1086,19 @@ def head(self, n: int = 5) -> DataFrame: def tail(self, n: int = 5) -> DataFrame: return typing.cast(DataFrame, self.iloc[-n:]) - def peek(self, n: int = 5, *, force: bool = False) -> pandas.DataFrame: + def peek(self, n: int = 5, *, force: bool = True) -> pandas.DataFrame: """ Preview n arbitrary rows from the dataframe. No guarantees about row selection or ordering. - DataFrame.peek(force=False) will always be very fast, but will not succeed if data requires - full data scanning. Using force=True will always succeed, but may be perform expensive - computations. + ``DataFrame.peek(force=False)`` will always be very fast, but will not succeed if data requires + full data scanning. Using ``force=True`` will always succeed, but may be perform queries. + Query results will be cached so that future steps will benefit from these queries. Args: n (int, default 5): The number of rows to select from the dataframe. Which N rows are returned is non-deterministic. - force (bool, default False): + force (bool, default True): If the data cannot be peeked efficiently, the dataframe will instead be fully materialized as part - of the operation if force=True. If force=False, the operation will throw a ValueError. + of the operation if ``force=True``. If ``force=False``, the operation will throw a ValueError. Returns: pandas.DataFrame: A pandas DataFrame with n rows. diff --git a/tests/system/small/test_dataframe.py b/tests/system/small/test_dataframe.py index 2048ada44f..ee32fb25ac 100644 --- a/tests/system/small/test_dataframe.py +++ b/tests/system/small/test_dataframe.py @@ -429,14 +429,14 @@ def test_rename(scalars_dfs): def test_df_peek(scalars_dfs): scalars_df, scalars_pandas_df = scalars_dfs - peek_result = scalars_df.peek(n=3) + peek_result = scalars_df.peek(n=3, force=False) pd.testing.assert_index_equal(scalars_pandas_df.columns, peek_result.columns) assert len(peek_result) == 3 def test_df_peek_filtered(scalars_dfs): scalars_df, scalars_pandas_df = scalars_dfs - peek_result = scalars_df[scalars_df.int64_col != 0].peek(n=3) + peek_result = scalars_df[scalars_df.int64_col != 0].peek(n=3, force=False) pd.testing.assert_index_equal(scalars_pandas_df.columns, peek_result.columns) assert len(peek_result) == 3 @@ -449,9 +449,9 @@ def test_df_peek_exception(scalars_dfs): scalars_df[["int64_col", "int64_too"]].cumsum().peek(n=3, force=False) -def test_df_peek_force(scalars_dfs): +def test_df_peek_force_default(scalars_dfs): scalars_df, scalars_pandas_df = scalars_dfs - peek_result = scalars_df[["int64_col", "int64_too"]].cumsum().peek(n=3, force=True) + peek_result = scalars_df[["int64_col", "int64_too"]].cumsum().peek(n=3) pd.testing.assert_index_equal( scalars_pandas_df[["int64_col", "int64_too"]].columns, peek_result.columns ) From f55680cd0eed46ee06cd9baf658de792f4a27f31 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Tue, 19 Mar 2024 12:46:17 -0700 Subject: [PATCH 24/27] fix: any() on empty set now correctly returns False (#471) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- bigframes/core/compile/aggregate_compiler.py | 2 +- tests/system/small/test_index.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/bigframes/core/compile/aggregate_compiler.py b/bigframes/core/compile/aggregate_compiler.py index 7059c4fdc1..9c1db0f162 100644 --- a/bigframes/core/compile/aggregate_compiler.py +++ b/bigframes/core/compile/aggregate_compiler.py @@ -414,7 +414,7 @@ def _( result = _is_true(column).any() return cast( ibis_types.BooleanScalar, - _apply_window_if_present(result, window).fillna(ibis_types.literal(True)), + _apply_window_if_present(result, window).fillna(ibis_types.literal(False)), ) diff --git a/tests/system/small/test_index.py b/tests/system/small/test_index.py index 2961884ebf..1f39ba25fe 100644 --- a/tests/system/small/test_index.py +++ b/tests/system/small/test_index.py @@ -68,6 +68,10 @@ def test_index_has_duplicates(scalars_df_index, scalars_pandas_df_index): assert bf_result == pd_result +def test_index_empty_has_duplicates(): + assert not bpd.Index([]).has_duplicates + + def test_index_values(scalars_df_index, scalars_pandas_df_index): bf_result = scalars_df_index.index.values pd_result = scalars_pandas_df_index.index.values From b519197d51cc098ac4981a9a57a9d6988ba07d03 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Tue, 19 Mar 2024 12:54:16 -0700 Subject: [PATCH 25/27] fix: fix broken multiindex loc cases (#467) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- bigframes/core/indexers.py | 157 ++++++++++---------------- bigframes/core/indexes/index.py | 3 +- bigframes/dataframe.py | 4 +- bigframes/series.py | 4 + tests/system/small/test_multiindex.py | 25 +++- 5 files changed, 88 insertions(+), 105 deletions(-) diff --git a/bigframes/core/indexers.py b/bigframes/core/indexers.py index 0a47c3a78e..8d6a1cbdfe 100644 --- a/bigframes/core/indexers.py +++ b/bigframes/core/indexers.py @@ -15,7 +15,7 @@ from __future__ import annotations import typing -from typing import List, Tuple, Union +from typing import Tuple, Union import ibis import pandas as pd @@ -147,19 +147,22 @@ def __getitem__( ... def __getitem__(self, key): - # TODO(swast): If the DataFrame has a MultiIndex, we'll need to - # disambiguate this from a single row selection. + # TODO(tbergeron): Pandas will try both splitting 2-tuple into row, index or as 2-part + # row key. We must choose one, so bias towards treating as multi-part row label if isinstance(key, tuple) and len(key) == 2: - df = typing.cast( - bigframes.dataframe.DataFrame, - _loc_getitem_series_or_dataframe(self._dataframe, key[0]), - ) + is_row_multi_index = self._dataframe.index.nlevels > 1 + is_first_item_tuple = isinstance(key[0], tuple) + if not is_row_multi_index or is_first_item_tuple: + df = typing.cast( + bigframes.dataframe.DataFrame, + _loc_getitem_series_or_dataframe(self._dataframe, key[0]), + ) - columns = key[1] - if isinstance(columns, pd.Series) and columns.dtype == "bool": - columns = df.columns[columns] + columns = key[1] + if isinstance(columns, pd.Series) and columns.dtype == "bool": + columns = df.columns[columns] - return df[columns] + return df[columns] return typing.cast( bigframes.dataframe.DataFrame, @@ -283,94 +286,40 @@ def _loc_getitem_series_or_dataframe( pd.Series, bigframes.core.scalar.Scalar, ]: - if isinstance(key, bigframes.series.Series) and key.dtype == "boolean": - return series_or_dataframe[key] - elif isinstance(key, bigframes.series.Series): - temp_name = guid.generate_guid(prefix="temp_series_name_") - if len(series_or_dataframe.index.names) > 1: - temp_name = series_or_dataframe.index.names[0] - key = key.rename(temp_name) - keys_df = key.to_frame() - keys_df = keys_df.set_index(temp_name, drop=True) - return _perform_loc_list_join(series_or_dataframe, keys_df) - elif isinstance(key, bigframes.core.indexes.Index): - block = key._block - block = block.select_columns(()) - keys_df = bigframes.dataframe.DataFrame(block) - return _perform_loc_list_join(series_or_dataframe, keys_df) - elif pd.api.types.is_list_like(key): - key = typing.cast(List, key) - if len(key) == 0: - return typing.cast( - Union[bigframes.dataframe.DataFrame, bigframes.series.Series], - series_or_dataframe.iloc[0:0], - ) - if pd.api.types.is_list_like(key[0]): - original_index_names = series_or_dataframe.index.names - num_index_cols = len(original_index_names) - - entry_col_count_correct = [len(entry) == num_index_cols for entry in key] - if not all(entry_col_count_correct): - # pandas usually throws TypeError in these cases- tuple causes IndexError, but that - # seems like unintended behavior - raise TypeError( - "All entries must be of equal length when indexing by list of listlikes" - ) - temporary_index_names = [ - guid.generate_guid(prefix="temp_loc_index_") - for _ in range(len(original_index_names)) - ] - index_cols_dict = {} - for i in range(num_index_cols): - index_name = temporary_index_names[i] - values = [entry[i] for entry in key] - index_cols_dict[index_name] = values - keys_df = bigframes.dataframe.DataFrame( - index_cols_dict, session=series_or_dataframe._get_block().expr.session - ) - keys_df = keys_df.set_index(temporary_index_names, drop=True) - keys_df = keys_df.rename_axis(original_index_names) - else: - # We can't upload a DataFrame with None as the column name, so set it - # an arbitrary string. - index_name = series_or_dataframe.index.name - index_name_is_none = index_name is None - if index_name_is_none: - index_name = "unnamed_col" - keys_df = bigframes.dataframe.DataFrame( - {index_name: key}, - session=series_or_dataframe._get_block().expr.session, - ) - keys_df = keys_df.set_index(index_name, drop=True) - if index_name_is_none: - keys_df.index.name = None - return _perform_loc_list_join(series_or_dataframe, keys_df) - elif isinstance(key, slice): + if isinstance(key, slice): if (key.start is None) and (key.stop is None) and (key.step is None): return series_or_dataframe.copy() raise NotImplementedError( f"loc does not yet support indexing with a slice. {constants.FEEDBACK_LINK}" ) - elif callable(key): + if callable(key): raise NotImplementedError( f"loc does not yet support indexing with a callable. {constants.FEEDBACK_LINK}" ) - elif pd.api.types.is_scalar(key): - index_name = "unnamed_col" - keys_df = bigframes.dataframe.DataFrame( - {index_name: [key]}, session=series_or_dataframe._get_block().expr.session - ) - keys_df = keys_df.set_index(index_name, drop=True) - keys_df.index.name = None - result = _perform_loc_list_join(series_or_dataframe, keys_df) - pandas_result = result.to_pandas() - # although loc[scalar_key] returns multiple results when scalar_key - # is not unique, we download the results here and return the computed - # individual result (as a scalar or pandas series) when the key is unique, - # since we expect unique index keys to be more common. loc[[scalar_key]] - # can be used to retrieve one-item DataFrames or Series. - if len(pandas_result) == 1: - return pandas_result.iloc[0] + elif isinstance(key, bigframes.series.Series) and key.dtype == "boolean": + return series_or_dataframe[key] + elif ( + isinstance(key, bigframes.series.Series) + or isinstance(key, indexes.Index) + or (pd.api.types.is_list_like(key) and not isinstance(key, tuple)) + ): + index = indexes.Index(key, session=series_or_dataframe._session) + index.names = series_or_dataframe.index.names[: index.nlevels] + return _perform_loc_list_join(series_or_dataframe, index) + elif pd.api.types.is_scalar(key) or isinstance(key, tuple): + index = indexes.Index([key], session=series_or_dataframe._session) + index.names = series_or_dataframe.index.names[: index.nlevels] + result = _perform_loc_list_join(series_or_dataframe, index, drop_levels=True) + + if index.nlevels == series_or_dataframe.index.nlevels: + pandas_result = result.to_pandas() + # although loc[scalar_key] returns multiple results when scalar_key + # is not unique, we download the results here and return the computed + # individual result (as a scalar or pandas series) when the key is unique, + # since we expect unique index keys to be more common. loc[[scalar_key]] + # can be used to retrieve one-item DataFrames or Series. + if len(pandas_result) == 1: + return pandas_result.iloc[0] # when the key is not unique, we return a bigframes data type # as usual for methods that return dataframes/series return result @@ -385,7 +334,8 @@ def _loc_getitem_series_or_dataframe( @typing.overload def _perform_loc_list_join( series_or_dataframe: bigframes.series.Series, - keys_df: bigframes.dataframe.DataFrame, + keys_index: indexes.Index, + drop_levels: bool = False, ) -> bigframes.series.Series: ... @@ -393,31 +343,38 @@ def _perform_loc_list_join( @typing.overload def _perform_loc_list_join( series_or_dataframe: bigframes.dataframe.DataFrame, - keys_df: bigframes.dataframe.DataFrame, + keys_index: indexes.Index, + drop_levels: bool = False, ) -> bigframes.dataframe.DataFrame: ... def _perform_loc_list_join( series_or_dataframe: Union[bigframes.dataframe.DataFrame, bigframes.series.Series], - keys_df: bigframes.dataframe.DataFrame, + keys_index: indexes.Index, + drop_levels: bool = False, ) -> Union[bigframes.series.Series, bigframes.dataframe.DataFrame]: # right join based on the old index so that the matching rows from the user's # original dataframe will be duplicated and reordered appropriately - original_index_names = series_or_dataframe.index.names if isinstance(series_or_dataframe, bigframes.series.Series): original_name = series_or_dataframe.name name = series_or_dataframe.name if series_or_dataframe.name is not None else "0" result = typing.cast( bigframes.series.Series, - series_or_dataframe.to_frame()._perform_join_by_index(keys_df, how="right")[ - name - ], + series_or_dataframe.to_frame()._perform_join_by_index( + keys_index, how="right" + )[name], ) result = result.rename(original_name) else: - result = series_or_dataframe._perform_join_by_index(keys_df, how="right") # type: ignore - result = result.rename_axis(original_index_names) + result = series_or_dataframe._perform_join_by_index(keys_index, how="right") # type: ignore + + if drop_levels and series_or_dataframe.index.nlevels > keys_index.nlevels: + # drop common levels + levels_to_drop = [ + name for name in series_or_dataframe.index.names if name in keys_index.names + ] + result = result.droplevel(levels_to_drop) # type: ignore return result diff --git a/bigframes/core/indexes/index.py b/bigframes/core/indexes/index.py index c8cb07d339..958b742636 100644 --- a/bigframes/core/indexes/index.py +++ b/bigframes/core/indexes/index.py @@ -49,6 +49,7 @@ def __init__( dtype=None, *, name=None, + session=None, ): import bigframes.dataframe as df import bigframes.series as series @@ -75,7 +76,7 @@ def __init__( else: pd_index = pandas.Index(data=data, dtype=dtype, name=name) pd_df = pandas.DataFrame(index=pd_index) - block = df.DataFrame(pd_df)._block + block = df.DataFrame(pd_df, session=session)._block self._query_job = None self._block: blocks.Block = block diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index c10a0c2456..c0f602a598 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -2310,7 +2310,9 @@ def join( return left._perform_join_by_index(right, how=how) - def _perform_join_by_index(self, other: DataFrame, *, how: str = "left"): + def _perform_join_by_index( + self, other: Union[DataFrame, indexes.Index], *, how: str = "left" + ): block, _ = self._block.join(other._block, how=how, block_identity_join=True) return DataFrame(block) diff --git a/bigframes/series.py b/bigframes/series.py index d01ee88cf5..6128238057 100644 --- a/bigframes/series.py +++ b/bigframes/series.py @@ -151,6 +151,10 @@ def T(self) -> Series: def _info_axis(self) -> indexes.Index: return self.index + @property + def _session(self) -> bigframes.Session: + return self._get_block().expr.session + def transpose(self) -> Series: return self diff --git a/tests/system/small/test_multiindex.py b/tests/system/small/test_multiindex.py index e0b9164315..4a293526df 100644 --- a/tests/system/small/test_multiindex.py +++ b/tests/system/small/test_multiindex.py @@ -169,15 +169,34 @@ def test_concat_multi_indices_ignore_index(scalars_df_index, scalars_pandas_df_i pandas.testing.assert_frame_equal(bf_result.to_pandas(), pd_result) -def test_multi_index_loc(scalars_df_index, scalars_pandas_df_index): +@pytest.mark.parametrize( + ("key"), + [ + (2), + ([2, 0]), + ([(2, "capitalize, This "), (-2345, "Hello, World!")]), + ], +) +def test_multi_index_loc_multi_row(scalars_df_index, scalars_pandas_df_index, key): bf_result = ( - scalars_df_index.set_index(["int64_too", "bool_col"]).loc[[2, 0]].to_pandas() + scalars_df_index.set_index(["int64_too", "string_col"]).loc[key].to_pandas() ) - pd_result = scalars_pandas_df_index.set_index(["int64_too", "bool_col"]).loc[[2, 0]] + pd_result = scalars_pandas_df_index.set_index(["int64_too", "string_col"]).loc[key] pandas.testing.assert_frame_equal(bf_result, pd_result) +def test_multi_index_loc_single_row(scalars_df_index, scalars_pandas_df_index): + bf_result = scalars_df_index.set_index(["int64_too", "string_col"]).loc[ + (2, "capitalize, This ") + ] + pd_result = scalars_pandas_df_index.set_index(["int64_too", "string_col"]).loc[ + (2, "capitalize, This ") + ] + + pandas.testing.assert_series_equal(bf_result, pd_result) + + def test_multi_index_getitem_bool(scalars_df_index, scalars_pandas_df_index): bf_frame = scalars_df_index.set_index(["int64_too", "bool_col"]) pd_frame = scalars_pandas_df_index.set_index(["int64_too", "bool_col"]) From 4fbf938c200a3e0e6b592aa4a4e18b59f2f34082 Mon Sep 17 00:00:00 2001 From: TrevorBergeron Date: Tue, 19 Mar 2024 16:08:16 -0700 Subject: [PATCH 26/27] fix: groupby aggregates no longer check if grouping keys are numeric (#472) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [ ] Make sure to open an issue as a [bug/issue](https://togithub.com/googleapis/python-bigquery-dataframes/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [ ] Ensure the tests and linter pass - [ ] Code coverage does not decrease (if any source code was changed) - [ ] Appropriate docs were updated (if necessary) Fixes # 🦕 --- bigframes/core/groupby/__init__.py | 4 ++-- bigframes/dataframe.py | 1 + tests/system/small/test_groupby.py | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/bigframes/core/groupby/__init__.py b/bigframes/core/groupby/__init__.py index 837eb28f68..2b447a0190 100644 --- a/bigframes/core/groupby/__init__.py +++ b/bigframes/core/groupby/__init__.py @@ -358,8 +358,8 @@ def _convert_index(self, dataframe: df.DataFrame): def _raise_on_non_numeric(self, op: str): if not all( - dtype in dtypes.NUMERIC_BIGFRAMES_TYPES_PERMISSIVE - for dtype in self._block.dtypes + self._column_type(col) in dtypes.NUMERIC_BIGFRAMES_TYPES_PERMISSIVE + for col in self._selected_cols ): raise NotImplementedError( f"'{op}' does not support non-numeric columns. " diff --git a/bigframes/dataframe.py b/bigframes/dataframe.py index c0f602a598..0f99a3e4db 100644 --- a/bigframes/dataframe.py +++ b/bigframes/dataframe.py @@ -2337,6 +2337,7 @@ def groupby( blocks.Label, bigframes.series.Series, typing.Sequence[typing.Union[blocks.Label, bigframes.series.Series]], + None, ] = None, *, level: typing.Optional[LevelsType] = None, diff --git a/tests/system/small/test_groupby.py b/tests/system/small/test_groupby.py index 2919c167ef..b38dcaf5d1 100644 --- a/tests/system/small/test_groupby.py +++ b/tests/system/small/test_groupby.py @@ -371,3 +371,20 @@ def test_series_groupby_agg_list(scalars_df_index, scalars_pandas_df_index): pd.testing.assert_frame_equal( pd_result, bf_result_computed, check_dtype=False, check_names=False ) + + +def test_dataframe_groupby_nonnumeric_with_mean(): + df = pd.DataFrame( + { + "key1": ["a", "a", "a", "b"], + "key2": ["a", "a", "c", "c"], + "key3": [1, 2, 3, 4], + "key4": [1.6, 2, 3, 4], + } + ) + pd_result = df.groupby(["key1", "key2"]).mean() + bf_result = bpd.DataFrame(df).groupby(["key1", "key2"]).mean().to_pandas() + + pd.testing.assert_frame_equal( + pd_result, bf_result, check_index_type=False, check_dtype=False + ) From 4727563c3c619e9336b6138b1ec54794b40fd44a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 21:32:26 -0700 Subject: [PATCH 27/27] chore(main): release 0.26.0 (#445) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- CHANGELOG.md | 40 ++++++++++++++++++++++++++++++++++++++++ bigframes/version.py | 2 +- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4edd37bed3..3bca26e361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,46 @@ [1]: https://pypi.org/project/bigframes/#history +## [0.26.0](https://github.com/googleapis/python-bigquery-dataframes/compare/v0.25.0...v0.26.0) (2024-03-20) + + +### ⚠ BREAKING CHANGES + +* exclude remote models for .register() ([#465](https://github.com/googleapis/python-bigquery-dataframes/issues/465)) + +### Features + +* (Series|DataFrame).plot ([#438](https://github.com/googleapis/python-bigquery-dataframes/issues/438)) ([1c3e668](https://github.com/googleapis/python-bigquery-dataframes/commit/1c3e668ceb26fd0f1377acbf6b95e8f4bcef40d6)) +* `read_gbq_table` supports `LIKE` as a operator in `filters` ([#454](https://github.com/googleapis/python-bigquery-dataframes/issues/454)) ([d2d425a](https://github.com/googleapis/python-bigquery-dataframes/commit/d2d425a93aa9e96f3b71c3ca3b185f4b5eaf32ef)) +* Add DataFrame.pipe() method ([#421](https://github.com/googleapis/python-bigquery-dataframes/issues/421)) ([95f5a6e](https://github.com/googleapis/python-bigquery-dataframes/commit/95f5a6e749468743af65062e559bc35ac56f3c24)) +* Set `force=True` by default in `DataFrame.peek()` ([#469](https://github.com/googleapis/python-bigquery-dataframes/issues/469)) ([4e8e97d](https://github.com/googleapis/python-bigquery-dataframes/commit/4e8e97d661078ed38d77be93b0bc1ad0fd52949c)) +* Support datetime related casting in (Series|DataFrame|Index).astype ([#442](https://github.com/googleapis/python-bigquery-dataframes/issues/442)) ([fde339b](https://github.com/googleapis/python-bigquery-dataframes/commit/fde339b71c754e617c61052940215b77890b59e4)) +* Support Series.dt.strftime ([#453](https://github.com/googleapis/python-bigquery-dataframes/issues/453)) ([8f6e955](https://github.com/googleapis/python-bigquery-dataframes/commit/8f6e955fc946db97c95ea012659432355b0cd12c)) + + +### Bug Fixes + +* Any() on empty set now correctly returns False ([#471](https://github.com/googleapis/python-bigquery-dataframes/issues/471)) ([f55680c](https://github.com/googleapis/python-bigquery-dataframes/commit/f55680cd0eed46ee06cd9baf658de792f4a27f31)) +* Df.drop_na preserves columns dtype ([#457](https://github.com/googleapis/python-bigquery-dataframes/issues/457)) ([3bab1a9](https://github.com/googleapis/python-bigquery-dataframes/commit/3bab1a917a5833bd58b20071a229ee95cf86a251)) +* Disable to_json and to_csv related tests ([#462](https://github.com/googleapis/python-bigquery-dataframes/issues/462)) ([874026d](https://github.com/googleapis/python-bigquery-dataframes/commit/874026da612bf08fbaf6d7dbfaa3325dc8a61500)) +* Exclude remote models for .register() ([#465](https://github.com/googleapis/python-bigquery-dataframes/issues/465)) ([73fe0f8](https://github.com/googleapis/python-bigquery-dataframes/commit/73fe0f89a96557afc4225521654978b96a2291b3)) +* Fix broken link in covid notebook ([#450](https://github.com/googleapis/python-bigquery-dataframes/issues/450)) ([adadb06](https://github.com/googleapis/python-bigquery-dataframes/commit/adadb0658c35142fed228abbd9baa42f9372f44b)) +* Fix broken multiindex loc cases ([#467](https://github.com/googleapis/python-bigquery-dataframes/issues/467)) ([b519197](https://github.com/googleapis/python-bigquery-dataframes/commit/b519197d51cc098ac4981a9a57a9d6988ba07d03)) +* Fix grouping series on multiple other series ([#455](https://github.com/googleapis/python-bigquery-dataframes/issues/455)) ([3971bd2](https://github.com/googleapis/python-bigquery-dataframes/commit/3971bd27c96b68b859399564dbb6abdb93de5f14)) +* Groupby aggregates no longer check if grouping keys are numeric ([#472](https://github.com/googleapis/python-bigquery-dataframes/issues/472)) ([4fbf938](https://github.com/googleapis/python-bigquery-dataframes/commit/4fbf938c200a3e0e6b592aa4a4e18b59f2f34082)) +* Raise `ValueError` when `read_pandas()` receives a bigframes `DataFrame` ([#447](https://github.com/googleapis/python-bigquery-dataframes/issues/447)) ([b28f9fd](https://github.com/googleapis/python-bigquery-dataframes/commit/b28f9fdd9681b3c9783a6e52322b70093e0283ec)) +* Series.(to_csv|to_json) leverages bq export ([#452](https://github.com/googleapis/python-bigquery-dataframes/issues/452)) ([718a00c](https://github.com/googleapis/python-bigquery-dataframes/commit/718a00c1fa8ac44b0d3a79a2217e5b12690785fb)) +* Warn when `read_gbq` / `read_gbq_table` uses the snapshot time cache ([#441](https://github.com/googleapis/python-bigquery-dataframes/issues/441)) ([e16a8c0](https://github.com/googleapis/python-bigquery-dataframes/commit/e16a8c0a6fb46cf1a7be12eec9471ae95d6f2c44)) + + +### Documentation + +* Add code samples for `ml.metrics.r2_score` ([#459](https://github.com/googleapis/python-bigquery-dataframes/issues/459)) ([85fefa2](https://github.com/googleapis/python-bigquery-dataframes/commit/85fefa2f1d4dbe3e0c9d4ab8124cea88eb5df38f)) +* Add the docs for loc and iloc indexers ([#446](https://github.com/googleapis/python-bigquery-dataframes/issues/446)) ([14ab8d8](https://github.com/googleapis/python-bigquery-dataframes/commit/14ab8d834d793ac7644f066145912e6d50966881)) +* Add the pages for at and iat indexers ([#456](https://github.com/googleapis/python-bigquery-dataframes/issues/456)) ([340f0b5](https://github.com/googleapis/python-bigquery-dataframes/commit/340f0b5b41fc5150d73890c7f27ae68dc308e160)) +* Add version information to bug template ([#437](https://github.com/googleapis/python-bigquery-dataframes/issues/437)) ([91bd39e](https://github.com/googleapis/python-bigquery-dataframes/commit/91bd39e8b194ddad09d53fca96201eee58063bb9)) +* Indicate that project and location are optional in example notebooks ([#451](https://github.com/googleapis/python-bigquery-dataframes/issues/451)) ([1df0140](https://github.com/googleapis/python-bigquery-dataframes/commit/1df014010652e7827a2720a906d0afe482a30ca9)) + ## [0.25.0](https://github.com/googleapis/python-bigquery-dataframes/compare/v0.24.0...v0.25.0) (2024-03-14) diff --git a/bigframes/version.py b/bigframes/version.py index 708390a7cd..8066f4353a 100644 --- a/bigframes/version.py +++ b/bigframes/version.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -__version__ = "0.25.0" +__version__ = "0.26.0"