def dataframe_to_bigquery_fields(
    dataframe,
    override_bigquery_fields=None,
    default_type="STRING",
    index=False,
) -> Tuple[schema.SchemaField]:
    """Convert a pandas DataFrame schema to a BigQuery schema.

    Args:
        dataframe (pandas.DataFrame):
            DataFrame for which the client determines the BigQuery schema.
        override_bigquery_fields (Sequence[Union[ \
            :class:`~google.cloud.bigquery.schema.SchemaField`, \
            Mapping[str, Any] \
        ]]):
            A BigQuery schema. Use this argument to override the autodetected
            type for some or all of the DataFrame columns.

    Returns:
        Optional[Sequence[google.cloud.bigquery.schema.SchemaField]]:
            The automatically determined schema. Returns None if the type of
            any column cannot be determined.
    """
    if override_bigquery_fields:
        override_bigquery_fields = pandas_gbq.schema.bigquery.to_schema_fields(
            override_bigquery_fields
        )
        override_fields_by_name = {
            field.name: field for field in override_bigquery_fields
        }
        override_fields_unused = set(override_fields_by_name.keys())
    else:
        override_fields_by_name = {}
        override_fields_unused = set()

    bq_schema_out = []
    unknown_type_fields = []

    # TODO(tswast): Support index=True in to_gbq.
    for column, dtype in pandas_gbq.core.pandas.list_columns_and_indexes(
        dataframe, index=index
    ):
        # Use provided type from schema, if present.
        bq_field = override_fields_by_name.get(column)
        if bq_field:
            bq_schema_out.append(bq_field)
            override_fields_unused.discard(bq_field.name)
            continue

        # Try to automatically determine the type based on the pandas dtype.
        bq_field = dtype_to_bigquery_field(column, dtype)
        if bq_field:
            bq_schema_out.append(bq_field)
            continue

        # Try to automatically determine the type based on a few rows of the data.
        values = dataframe.reset_index()[column]
        bq_field = values_to_bigquery_field(column, values, default_type=default_type)

        if bq_field:
            bq_schema_out.append(bq_field)
            continue

        # Try to automatically determine the type based on the arrow conversion.
        try:
            arrow_value = pyarrow.array(values)
            bq_field = (
                pandas_gbq.schema.pyarrow_to_bigquery.arrow_type_to_bigquery_field(
                    column,
                    arrow_value.type,
                    default_type=default_type,
                )
            )

            if bq_field:
                bq_schema_out.append(bq_field)
                continue
        except pyarrow.lib.ArrowInvalid:
            # TODO(tswast): Better error message if conversion to arrow fails.
            pass

        # Unknown field type.
        bq_field = schema.SchemaField(column, default_type)
        bq_schema_out.append(bq_field)
        unknown_type_fields.append(bq_field)

    # Catch any schema mismatch. The developer explicitly asked to serialize a
    # column, but it was not found.
    if override_fields_unused:
        raise ValueError(
            "Provided BigQuery fields contain field(s) not present in DataFrame: {}".format(
                override_fields_unused
            )
        )

    # If schema detection was not successful for all columns, also try with
    # pyarrow, if available.
    if unknown_type_fields:
        msg = "Could not determine the type of columns: {}".format(
            ", ".join(field.name for field in unknown_type_fields)
        )
        warnings.warn(msg)

    return tuple(bq_schema_out)
Convert a pandas DataFrame schema to a BigQuery schema.

    Args:
        dataframe (pandas.DataFrame):
            DataFrame for which the client determines the BigQuery schema.
        override_bigquery_fields (Sequence[Union[             :class:`~google.cloud.bigquery.schema.SchemaField`,             Mapping[str, Any]         ]]):
            A BigQuery schema. Use this argument to override the autodetected
            type for some or all of the DataFrame columns.

    Returns:
        Optional[Sequence[google.cloud.bigquery.schema.SchemaField]]:
            The automatically determined schema. Returns None if the type of
            any column cannot be determined.
    
pandas_gbq/schema/pandas_to_bigquery.py