# How to Use the OpenBB OBBject for Data Frame Conversion

> Easily convert OpenBB OBBject to pandas DataFrames with to_dataframe or to_df. This function handles BaseModel dict list and existing DataFrame results seamlessly.

- Repository: [OpenBB/OpenBB](https://github.com/OpenBB-finance/OpenBB)
- Tags: how-to-guide
- Published: 2026-03-06

---

**You can convert any OpenBB OBBject to a pandas DataFrame using the `to_dataframe()` or `to_df()` method, which automatically handles BaseModel, dict, list, and existing DataFrame results.**

The **OpenBB OBBject** is the core container class in the OpenBB-finance/OpenBB repository that standardizes results returned by any data provider or extension. Located in [`openbb_platform/core/openbb_core/app/model/obbject.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_platform/core/openbb_core/app/model/obbject.py), this type-agnostic wrapper provides robust utilities to transform your financial data into analysis-ready pandas DataFrames with a single method call.

## Understanding the OpenBB OBBject Structure

The `OBBject` class acts as the universal return type for all OpenBB queries and provider responses. It stores raw results in the `results` attribute, which can contain Pydantic **BaseModel** instances, nested dictionaries, lists of scalars, or existing pandas DataFrames. Because the container is deliberately designed to be format-agnostic, the conversion layer must inspect the underlying Python structure at runtime and select the appropriate pandas constructor.

## Converting OBBject Results to DataFrames

The class exposes two public methods for tabular conversion. Both reside in [`openbb_platform/core/openbb_core/app/model/obbject.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_platform/core/openbb_core/app/model/obbject.py) and provide identical output, differing only in naming convention.

### The to_dataframe() Method

The `to_dataframe()` method (lines 121–169) is the primary implementation for **OpenBB OBBject data frame conversion**. It accepts optional parameters for `index`, `sort_by`, and `ascending` to customize the output structure. The internal conversion flow follows four distinct stages:

1. **Guard clause** (lines 68–70): Raises `OpenBBError("Results not found.")` if `self.results` is empty or None.
2. **Fast-path** (lines 71–73): If `results` is already a pandas DataFrame, it returns the object unchanged without copying.
3. **Type dispatch** (lines 74–149): A series of `isinstance` checks determines whether the data contains `BaseModel` objects, dictionaries, lists of lists, or raw strings. Each branch uses the most efficient pandas constructor (e.g., `DataFrame.from_dict`, `Series.to_frame`, or `concat`).
4. **Post-processing** (lines 155–171): Applies the optional `index` column, column sorting, NaN removal, and `sort_by` ordering.

For lists of Pydantic models, the method delegates to `basemodel_to_df`, a utility defined in [`openbb_platform/core/openbb_core/app/utils.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_platform/core/openbb_core/app/utils.py).

### The to_df() Shortcut

`to_df()` (lines 81–89) is a thin alias that forwards all arguments directly to `to_dataframe()`. This method exists solely for backward compatibility and convenience, allowing you to access **OpenBB OBBject data frame conversion** functionality with shorter syntax.

## Complete Code Examples

### Converting BaseModel Lists

When providers return validated Pydantic objects, you can wrap them manually or receive them from a query:

```python
from pydantic import BaseModel
from openbb_core.app.model.obbject import OBBject

class PricePoint(BaseModel):
    date: str
    close: float

data = [
    PricePoint(date="2024-01-01", close=150.25),
    PricePoint(date="2024-01-02", close=152.10)
]

obb = OBBject(results=data)
df = obb.to_df()  # Automatically uses 'date' as index

print(df.head())

```

### Converting Dictionary Results

Dictionary-of-lists structures common in JSON API responses convert seamlessly:

```python
api_response = {
    "timestamp": ["2024-01-01", "2024-01-02", "2024-01-03"],
    "open": [100.0, 101.5, 102.0],
    "close": [101.5, 102.0, 101.0]
}

obb = OBBject(results=api_response)
df = obb.to_dataframe(index="timestamp")
print(df)

```

### Handling Existing DataFrames

If you pass an existing DataFrame into an OBBject, the conversion returns the original object by reference:

```python
import pandas as pd

original = pd.DataFrame({"symbol": ["AAPL", "MSFT"], "price": [150, 250]})
obb = OBBject(results=original)
result = obb.to_df()

assert result is original  # True; no copy made

```

### Query Results to DataFrame

The typical workflow involves fetching data via the `Query` class and converting immediately:

```python
from openbb_core.app.query import Query
from openbb_core.app.model.obbject import OBBject

query = Query("equity_historical", symbol="AAPL", provider="yfinance")
obbject = await OBBject.from_query(query)
df = obbject.to_dataframe()

```

The `from_query` class method executes the provider logic, wraps the raw output in an OBBject, and `to_dataframe()` normalizes the provider-specific schema into a standard DataFrame.

### Advanced Options

Control the final DataFrame structure using the optional parameters:

```python
obb = OBBject(results=api_response)

# Use 'open' as the DataFrame index and sort by 'close' descending

df = obb.to_dataframe(index="open", sort_by="close", ascending=False)

```

## Conversion Logic and Architecture

The robustness of **OpenBB OBBject data frame conversion** stems from its runtime type inspection system. Unlike rigid serializers, the implementation handles:

- **Single or list of BaseModel**: Flattens nested Pydantic validation errors and converts to records.
- **Nested dictionaries**: Recursively normalizes keys into column names.
- **List of lists**: Assumes homogenous row-based data.
- **Raw strings**: Wraps single values in a single-row DataFrame.
- **Arbitrary objects**: Falls back to `pandas.DataFrame(res)` coercion.

This architecture ensures that provider extensions in `openbb_platform/providers/` (e.g., the yFinance implementation at [`openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_platform/providers/yfinance/openbb_yfinance/models/equity_historical.py)) can return domain-specific models without requiring explicit conversion code in the user pipeline.

## Summary

- **Primary method**: `OBBject.to_dataframe()` in [`openbb_platform/core/openbb_core/app/model/obbject.py`](https://github.com/OpenBB-finance/OpenBB/blob/main/openbb_platform/core/openbb_core/app/model/obbject.py) handles all type dispatch logic (lines 121–169).
- **Shortcut alias**: `to_df()` provides identical functionality for concise syntax.
- **Zero-copy optimization**: Existing DataFrames pass through unchanged (lines 71–73).
- **Type support**: Automatically converts BaseModel, dict, list, and scalar results without manual intervention.
- **Customization**: Use `index`, `sort_by`, and `ascending` parameters to shape the final DataFrame structure.

## Frequently Asked Questions

### What data types can the OpenBB OBBject convert to a DataFrame?

The `to_dataframe()` method supports `BaseModel` (single instances or lists), nested or flat `dict` objects, lists of dictionaries or lists, native pandas DataFrames (passed through), raw strings (wrapped as single-row data), and any object that pandas can coerce via `DataFrame()`.

### What is the difference between `to_df()` and `to_dataframe()`?

`to_df()` is a thin alias defined at lines 81–89 that forwards all arguments to `to_dataframe()`. They produce identical output; `to_df()` exists for backward compatibility and brevity.

### How does the OBBject handle existing pandas DataFrames?

If the `results` attribute already contains a pandas DataFrame, the conversion logic at lines 71–73 returns the object by reference without copying or transformation, ensuring minimal memory overhead.

### Can I specify a custom index column during conversion?

Yes. Pass the `index` parameter to either method with the name of the column you want to set as the DataFrame index. For example: `obb.to_dataframe(index="date")` will move the "date" column to the index and drop it from the columns.