# Mito Documentation

Automate your repetitive Excel reports. No computer science degree required.

[Mito](https://www.trymito.io) is a set of Jupyter extensions desgined to help you write Python code faster. There are 3 main pieces of Mito.&#x20;

1. **Mito AI**: Tools like context-aware AI Chat and error debugging to help you get the most from LLMs. No more copying and pasting between Jupyter and ChatGPT/Claude.&#x20;
2. **Mito Spreadsheet**: Explore your data in an interactive spreadsheet interface. Write spreadsheet formulas like VLOOKUP, apply filters, build pivot tables, and create graphs all in the spreadsheet.  Every edit you make in the Mito spreadsheet is automatically converted to production-ready Python code
3. **Mito for Streamlit and Dash**: Add a fully-featured spreadsheet to your dashboards in just two lines of code. &#x20;

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Data Copilot</strong></td><td>Collaborate with an AI that understands your data and code.</td><td></td><td><a href="/pages/sVf98WL7Dlj3ndNEdRXB">/pages/sVf98WL7Dlj3ndNEdRXB</a></td><td><a href="/files/z3VKgb7UkKjTJy8AugVw">/files/z3VKgb7UkKjTJy8AugVw</a></td></tr><tr><td><strong>Install Mito for Jupyter</strong></td><td>Write Python code 4x faster. Automate your Excel reports.</td><td></td><td><a href="/pages/-MSdkU28P6QFwsfUkYXU">/pages/-MSdkU28P6QFwsfUkYXU</a></td><td><a href="/files/8qAtvyPDGAQnVjuWgvLi">/files/8qAtvyPDGAQnVjuWgvLi</a></td></tr><tr><td><strong>Build a Mito Streamlit App</strong></td><td>Add Excel-like functionality to a Streamlit app in 2 lines of code.</td><td></td><td><a href="/pages/qfxH4aAR7HX7xnbmJtCl">/pages/qfxH4aAR7HX7xnbmJtCl</a></td><td><a href="/files/pBXXRHaLEcPN6N9GtLFL">/files/pBXXRHaLEcPN6N9GtLFL</a></td></tr></tbody></table>

## How to use these docs

1. [Getting Started](/getting-started/installing-mito) provides you with basic info on installing the Mito spreadsheet.
2. [Mito AI](/mito-ai/data-copilot) explains how to use AI Chat and error debugging to increase your productivity
3. [The Mito spreadsheet feature reference](/how-to/overview-of-the-mitosheet) explains how to use each and every button, spreadsheet formula, and keyboard shortcut in the Mito spreadsheet.
4. [Mito for Streamlit ](/mito-for-streamlit/getting-started-with-mito-for-streamlit)contains a tutorial on building your first Mito Streamlit app, API references, and sample apps.&#x20;
5. [Mito for Dash](/mito-for-dash/getting-started) contains instructions on adding Mito to your Dash applications, as well as a tutorial for building a Dash app with Mito from scratch.
6. [Tutorials](/how-to-1/pass-a-dataframe-into-mito) are step by step guides on how to accomplish specific, common tasks.&#x20;
7. [Misc](/misc/release-notes) contains our release notes, terms of service, and more.

Just getting started with Mito? Here's what we'd reccomend.

1. Follow the instructions for [installing Mito.](/getting-started/installing-mito)
2. Start your work by [importing data into Mito](/how-to/importing-data-to-mito).
3. Then use [Mito AI](/mito-ai/data-copilot) to write some Python code.

## Questions?

Want help? Get in contact with our support team through [Discord](https://discord.gg/XdJSZyejJU), [Slack](https://join.slack.com/t/trymito/shared_invite/zt-1h6t163v7-xLPudO7pjQNKccXz7h7GSg), or by emailing <jake@sagacollab.com>


# Installing Mito

How to install the Mito spreadsheet and Mito AI for Jupyter.

Mito is an AI-powered coding assistant built directly into Jupyter, designed for data analysts who have outgrown Excel and are moving into Python. It brings the familiarity of spreadsheets into the Jupyter environment while adding automation, code generation, and AI support to make analysis faster and more accessible.

## Quick Start

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-cover data-type="image">Cover image</th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><a href="http://trymito.io/downloads"><strong>Desktop App</strong></a></td><td><mark style="color:$info;">The easiest way to get started with Mito.</mark></td><td data-object-fit="fill"><a href="/files/dXy4uR2cdWvVd8YIBGJj">/files/dXy4uR2cdWvVd8YIBGJj</a></td><td><a href="http://trymito.io/downloads">http://trymito.io/downloads</a></td></tr><tr><td><a href="/pages/anZvgY1RuXlJwt2MLIbC"><strong>Pip Package</strong></a></td><td><mark style="color:$info;">Best for Jupyter users that want to integrate Mito into their existing setups.</mark></td><td data-object-fit="fill"><a href="/files/xwTLPYmdZtRVooFPmtI1">/files/xwTLPYmdZtRVooFPmtI1</a></td><td><a href="/pages/anZvgY1RuXlJwt2MLIbC">/pages/anZvgY1RuXlJwt2MLIbC</a></td></tr><tr><td><a href="/pages/F0NfO7gwL1a4m734HEGk"><strong>MCP Server</strong></a></td><td>Connect and use the Mito Agent in your application of choice</td><td><a href="/files/RrH6np9FjqbhJI7c3s9T">/files/RrH6np9FjqbhJI7c3s9T</a></td><td><a href="/pages/F0NfO7gwL1a4m734HEGk">/pages/F0NfO7gwL1a4m734HEGk</a></td></tr></tbody></table>


# Installing Mito Using Pip

Instructions for install Mito using the command line and the pip package manager.

Start by [creating a virtual environment](/getting-started/installing-mito/setting-up-a-virtual-environment), then run:&#x20;

```
python -m pip install mitosheet mito-ai
```

Launch Juypyter Lab&#x20;

```
jupyter lab
```

Then, follow these instructions to [create a mitosheet](/how-to/creating-a-mitosheet) and [use AI](/mito-ai/chat).

{% hint style="warning" %}
Want help? Get in contact with our support team through [Discord](https://discord.gg/XdJSZyejJU), [Slack](https://join.slack.com/t/trymito/shared_invite/zt-1h6t163v7-xLPudO7pjQNKccXz7h7GSg), or by emailing <jake@sagacollab.com>
{% endhint %}

## Requirements

1. Check that you have **Python 3.9** **or above, and Python 3.13 or below** by opening a terminal and running `python --version`
2. By installing Mito, you are agreeing to Mito's [Terms of Service](/misc/terms-of-service) and [Privacy Policy](/misc/privacy-policy).
3. In addition, by using Mito's AI features, you are agreeing to our [AI data usage policy](/mito-ai/ai-data-usage-faq).&#x20;


# Fixing Common Install Errors

The most Mito installation issues and how to fix them.

{% hint style="info" %}
Want help? Get in contact with our support team through [Discord](https://discord.gg/XdJSZyejJU), [Slack](https://join.slack.com/t/trymito/shared_invite/zt-1h6t163v7-xLPudO7pjQNKccXz7h7GSg), or by emailing <jake@sagacollab.com>
{% endhint %}

## How to fix most install errors

Most install errors are a result of conflicting Python packages within your base environment. Thus, most install errors can be fixed by installing Mito inside of a virtual environment. If you are having any trouble with installing Mito, [**we reccomend you attempt to install Mito inside a virtual environment!**](/getting-started/installing-mito)

## Common Installation Issues

#### The Sheet does not render when I call mitosheet.sheet().

This is the most common error, and it is likely because you have failed to refresh your Jupyter. This is usually fixable through the following steps:

1. Shut down all of the currently running Jupyter instances.&#x20;
2. Close all browser tabs with Jupyter open.
3. Relaunch Jupyter.&#x20;
4. Retry calling `mitosheet.sheet()`

If this does not work, try rerunning the installer and repeating the above steps.

#### The installer hit a Permission Error during install.

If your installation fails with a `PermissionError`, then you likely will be able to successfully install Mito by rerunning the installation commands with adminstrator privileges.

For Windows, this means[ running the command prompt as an admin](https://grok.lsu.edu/article.aspx?articleid=16850), and for Mac/Linux means using the sudo command for the installation commands.

#### I'm getting an SSL error on MacOSX.

You're probably receiving this error because you need to install the SSL certificates.

* If you downloaded Python from the official website, then run `/Applications/Python\ 3.9/Install\ Certificates.command` in a terminal (change `3.9` to whatever version you installed).
* If you installed Python using MacPorts, run `sudo port install curl-ca-bundle` in a terminal.

If you have any other issues installing Mito, or you're looking to install Mito on JupyterHub or Kuberenetes, get in touch through our [Discord](https://discord.gg/XdJSZyejJU). We'd love to help.

#### I'm getting an "externally managed environment" error.

This error usually occurs when trying to install a Python package outside of a virtual environment. To resolve this error follow the instructions on the [Setting Up a Virtual Environment](/getting-started/installing-mito/setting-up-a-virtual-environment). &#x20;

#### I do not have Python installed.

Follow this [Guide to downloading Python](https://wiki.python.org/moin/BeginnersGuide/Download).

{% hint style="info" %}
Still having installation issues? Get in contact with our support team through [Discord](https://discord.gg/XdJSZyejJU), [Slack](https://join.slack.com/t/trymito/shared_invite/zt-1h6t163v7-xLPudO7pjQNKccXz7h7GSg), or by emailing <jake@sagacollab.com>
{% endhint %}


# Mito Desktop FAQ

Advice for getting started with the Mito Desktop app.

### Where can I get the desktop app?

The desktop app can be downloaded from the [downloads page](http://trymito.io/downloads).

### What is the difference between the desktop app and the pip package?

* **Desktop app**: Self-contained and handles setup for you, including installing Python and the required packages.
* **Pip package**: Best if you already use Jupyter Lab and just want to add Mito to your environment.

### So which should I go with (desktop or pip)?

* **Desktop app**: If you’re starting from scratch or aren’t comfortable with the command line and virtual environments.
* **Pip package**: If you already have Jupyter Lab and want a quick install.

### What is a workspace?

When you first download the desktop app, you’ll be prompted to set up a workspace. This workspace is a managed environment that comes with a specific version of Python and a set of data science tools to get you started.&#x20;

### The workspace is taking a long time to setup.

On some systems (like Windows), setting up the workspace may take longer. It's difficult to say how long this process will take, considering that internet speeds and computer's specs vary.&#x20;

However, if you don't receive a failure message, rest assured the installation is working as expected. The good news is that you only need to setup the workspace once. &#x20;


# Upgrading Mito Desktop

Notes on upgrading the desktop app and Mito AI packages.

### How can I update the desktop app?

You can check for updates, by using the hamburger icon in the upper right corner, and selecting the *Check for updates* menu item. Download, and install the update as you normally would.

<figure><img src="/files/Pz8TEvDs4RXVn3bpLQsW" alt=""><figcaption></figcaption></figure>

### How can I update Mito AI?

Its an easy three step process:&#x20;

1. Open a notebook in the desktop app, and in a new cell run:

   ```
   pip install --upgrade mito-ai
   ```
2. Once the install is completed you can delete this cell.&#x20;
3. Close and reopen the desktop app.&#x20;

### Why are there separate update instructions for the desktop app and Mito AI?

The **desktop app** and **Mito AI** are updated differently because they’re technically separate parts of the same tool.

* **The desktop app** is the graphical program that makes it easy to use Mito on your computer. When you update the desktop app, you’re updating the user interface and bundled workspace.
* **Mito AI**, on the other hand, is the underlying Python package that powers the app. It’s installed inside the included workspace and can be updated independently using `pip`.

In most cases, the desktop app already includes the latest version of Mito AI. However, if you want early access to new features or bug fixes that haven’t yet shipped in the desktop app, you can manually upgrade the Mito AI package using `pip install --upgrade mito-ai`.


# Installing Mito in JupyterHub

Step by step instructions for using Mito in JupyterHub

Adding Mito to your JupyterHub user servers is a great way to enable your users to take advantage of AI and Spreadsheet features that Mito provides

JupyterHub uses many different spawners and installation instructions will depend on the chosen spawner. Here we provide the instructions for most common cases.&#x20;

{% hint style="warning" %}
Your custom JupyterHub use case not covered below? Reach out to <jake@sagacollab.com> to get help
{% endhint %}

## Container-based Servers

If you use a container to run your user servers, add installation command somewhere in your Docker file.

```
RUN pip install --no-cache-dir mito-ai mitosheet
```

Common scenarios for this are:

* Docker with [DockerSpawner](https://github.com/jupyterhub/dockerspawner)
* K8s with [KubeSpawner](https://github.com/jupyterhub/kubespawner)
* Z2JH distribution — see instructions [here](https://z2jh.jupyter.org/en/stable/jupyterhub/customizing/user-environment.html#customize-an-existing-docker-image)

## The Littlest JupyterHub (TLJH)

In line with the official [guide](https://tljh.jupyter.org/en/latest/howto/user-env/user-environment.html#installing-pip-packages), run the following command

```
sudo -E pip install mito-ai mitosheet
```


# Installing Mito in a Docker Container

Step by step instructions for installing Mito with a Docker file.

## Before Installing Mito

Verify that the Docker image is using **Python 3.9** or greater and **JupyterLab 4.1** or greater.

## Installing Mito

Add the following command to your docker file:

```
RUN pip install --no-cache-dir mito
```

Then, after you launch this container, you can run a classic Jupyter Notebook or JupyterLab instance and create a mitosheet with the following standard instructions.

### Example

Here is a minimal example of a Dockerfile which you can use to build an image with Mito

```
# Use the official Jupyter minimal notebook as the base image
FROM quay.io/jupyter/minimal-notebook:latest

# Install Python packages
RUN pip install --no-cache-dir mito-ai mitosheet
```

### Best practices

It is a best practice to pin the version of Mito that you are installing in a Docker container, for example

```
RUN pip install --no-cache-dir mito-ai==0.1.52
```

{% content-ref url="/pages/-MSFWSHvT14R-vec2dxe" %}
[Creating a Mitosheet](/how-to/creating-a-mitosheet)
{% endcontent-ref %}


# Installing Mito for Streamlit

Step by step instructions for installing Mito and Streamlit

## Requirements

1. Check that you have **Python 3.6** **or above** by opening a terminal and running `python --version`
2. By installing Mito, you are agreeing to Mito's [Terms of Service](/misc/terms-of-service) and [Privacy Policy](/misc/privacy-policy).&#x20;

## Installing Mito

First open a **terminal, command prompt, or Anaconda Prompt**. Then, install the mitosheet and streamlit packages.

```
pip install mitosheet streamlit
```

This will install **Mito for Streamlit** - you are now ready to use Mito in your dashboards.&#x20;

{% hint style="info" %}
Mito is compatible with Streamlit versions `>=1.2` and `<=1.31`.
{% endhint %}

{% content-ref url="/pages/qfxH4aAR7HX7xnbmJtCl" %}
[Getting Started with Mito for Streamlit](/mito-for-streamlit/getting-started-with-mito-for-streamlit)
{% endcontent-ref %}


# Installing Mito for Dash

Step by step instructions for installing Mito and Dash

## Requirements

1. Check that you have **Python 3.6** **or above** by opening a terminal and running `python --version`
2. By installing Mito, you are agreeing to Mito's [Terms of Service](/misc/terms-of-service) and [Privacy Policy](/misc/privacy-policy).&#x20;

## Installing Mito

First open a **terminal, command prompt, or Anaconda Prompt**. Then, install the mitosheet and streamlit packages.

```
pip install mitosheet dash
```

This will install **Mito for Dash** - you are now ready to use Mito in your Dash dashboards.&#x20;

{% content-ref url="/pages/g941q2x1H704Yg8aQU9e" %}
[Mito for Dash](/mito-for-dash/getting-started)
{% endcontent-ref %}


# Installing Mitosheet in VS Code

Instructions for getting your first Mitosheet open is VS Code or Cursor

Mitosheet is an interactive spreadsheet interface for Python that integrates seamlessly with editors like Visual Studio Code and Cursor. Follow the steps below to install and start using Mitosheet.

### Installation

Before using Mitosheet, you need to install the Python package:

```
pip install mitosheet
```

In addition, install the [**Mitosheet extension**](https://marketplace.visualstudio.com/items?itemName=MitoLabs.mitosheet-vscode) in your editor:

* Open your editor’s Extensions panel
* Search for **Mitosheet**
* Click **Install**

### Getting Started

To create your first Mitosheet, open a new Jupyter Notebook and run the following code:

```python
import mitosheet
import pandas as pd

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6]
})

mitosheet.sheet(df)
```

### Notes

* Restart your kernel if the extension does not load correctly.
* This extension is actively being developed, if you find any bugs we encourage you to submit a [ticket](https://github.com/mito-ds/mito/issues).&#x20;


# Setting Up a Virtual Environment

Installing Mito in a virtual environment reduces dependency issues and ensures that Mito will not impact any of your other Python projects.&#x20;

Setting up a virtual environment is dependent on your Python installation method/package manager. Below are several of the most common methods. &#x20;

### Default Python Virtual Environments&#x20;

Create a new environment:

```
python -m venv mitoenv
```

Activate the environment:&#x20;

* **On Windows** in command prompt:

```
mitoenv\Scripts\activate.bat
```

* **On Mac**:

```
source mitoenv/bin/activate
```

### Anaconda Navigator

To install Mito within an Anaconda Navigator virtual environment:

1. Select `Environments` in the left navigation
2. Select the `Create` button to create a new environment
3. Give your new environment a descriptive name like `Mito`
4. Make sure it is configured to use Python >3.8
5. Click `create`
6. After the environment is created, switch to `Home`, and select the `Mito` environment you just created.
7. Select the "▶" icon next to your new environment. Then select "Open terminal".
8. In the terminal, install the Mito Jupyter Lab extensions by running the command:

```
python -m pip install mitosheet mito-ai
```

**Use Mito**

1. Click on the `Home` button&#x20;
2. Find the `Juptyer Lab` tile, make sure it is running JupyterLab ≥ 4.1 and press `Launch`
3. Then, follow these instructions to [create a mitosheet](/how-to/creating-a-mitosheet) and [use AI](/mito-ai/chat).

### Conda&#x20;

#### Installing Mito in a Conda virtual environment <a href="#installing-mito-in-a-conda-virtual-environment" id="installing-mito-in-a-conda-virtual-environment"></a>

Create a new conda environment:

<pre><code><strong>conda create -n mitoenv python=3.10
</strong></code></pre>

Activate your new environment:

```
conda activate mitoenv
```


# Mito AI Core Concepts

Make your Python environment intelligent.

**Installing Data Copilot**

Start by [creating a virtual environment](/getting-started/installing-mito/setting-up-a-virtual-environment), then run:&#x20;

```
 pip install mito-ai mitosheet
```

Then, follow these instructions to [create a mitosheet](/how-to/creating-a-mitosheet) and [use AI](/mito-ai/chat).

## Features

Mito AI is a suite of  context-aware AI Chat and error debugging tools to help you get the most from LLMs. No more copying and pasting between Jupyter and ChatGPT/Claude, or wasting time looking up Python syntax. Data Copilot integrates all of the tools you need directly into Jupyter.&#x20;

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Agent</strong> can build and edit full notebooks for you!</td><td><a href="/files/7aCJTmsgooHIyYWL2yzq">/files/7aCJTmsgooHIyYWL2yzq</a></td><td><a href="/pages/JoqiePdF2O4kZGF6DkqK">/pages/JoqiePdF2O4kZGF6DkqK</a></td></tr><tr><td><strong>Chat</strong> is like collaborating with a colleague who sees your code, knows your data, and is a Python expert.</td><td><a href="/files/PfKhydue8EYTI5oAjjBG">/files/PfKhydue8EYTI5oAjjBG</a></td><td><a href="/pages/sVf98WL7Dlj3ndNEdRXB">/pages/sVf98WL7Dlj3ndNEdRXB</a></td></tr><tr><td><strong>Smart Debugging</strong> identifies and fixes your errors so you can focus on your data and code, not the typos.</td><td><a href="/files/bgqAVeOUPofoukcWGi1k">/files/bgqAVeOUPofoukcWGi1k</a></td><td><a href="/pages/rPIB7E4wi8O7Nt9FujkS">/pages/rPIB7E4wi8O7Nt9FujkS</a></td></tr></tbody></table>


# Agent

Agents take automation to the next level—helping you plan and execute tasks step by step. From just a single prompt, the agent can discover and report important insights, build presentation-ready graphs, and generate a clean, well documented notebook.&#x20;

### Agent Capabilities&#x20;

This is an overview of the tools that the Mito AI Data Copilot can use when responding to your prompts. When you ask a question or request help, the AI agent automatically selects the appropriate tools to assist you, without requiring you to specify which one to use.

<table data-view="cards"><thead><tr><th></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><strong>Create/Update Code Cells:</strong> Generate new code or modify existing code in your notebook. Perfect for data analysis tasks, visualization creation, or implementing algorithms without writing code from scratch.</td><td><a href="/files/UrmQYQYR1XAPK5IXBGqY">/files/UrmQYQYR1XAPK5IXBGqY</a></td></tr><tr><td><strong>Check Cell Output:</strong> Examine the results of executed cells so the agent can help you interpret and construct presentation-ready graphs, diagnose issues, and verify your analysis is on the right track.                                                 </td><td><a href="/files/2K60BAWpZcCe6NPzYMRE">/files/2K60BAWpZcCe6NPzYMRE</a></td></tr><tr><td><strong>Code Citation:</strong> Link the agent's observations to specific lines of code, so you can verify its work. This transparency builds trust, clarifies recommendations, and helps you learn from the agent's reasoning. </td><td><a href="/files/1pVeFsRYzX37EJzPIugN">/files/1pVeFsRYzX37EJzPIugN</a></td></tr><tr><td><strong>Query your data:</strong> Connect the agent to your database, then query it in natural language. Mito understands the schema of your data so it will find the right tables for the right query.</td><td><a href="/files/doGKN3Ow18ivc3BZ6Kwf">/files/doGKN3Ow18ivc3BZ6Kwf</a></td></tr><tr><td><strong>Check existing variables:</strong> View variables currently available in your notebook's memory. Quickly inspect variable types, shapes, and values so it can generate insights and working code.</td><td><a href="/files/foX1CH73wvEKHzynWPit">/files/foX1CH73wvEKHzynWPit</a></td></tr><tr><td><strong>Search file paths in current working directory:</strong> Find files  in your current directory. Useful for locating CSV and Excel files to import as dataframes for your analysis.</td><td><a href="/files/C2jZTbbkOlKFeNIvpXQ7">/files/C2jZTbbkOlKFeNIvpXQ7</a></td></tr><tr><td><p><strong>Write Markdown:</strong> Document section of code, highlight key results and conclusions. Make it easier for yourself and your colleagues to understand the notebook. </p><p></p></td><td><a href="/files/d3Qo5gChMVe2VQW78gqr">/files/d3Qo5gChMVe2VQW78gqr</a></td></tr><tr><td><strong>Automatically fix errors:</strong> Identify and resolve errors in your notebook. The agent analyzes error messages, codes solutions, and checks that they fix your bugs to get your code running. </td><td><a href="/files/XJnWzR1pLw0Fhpuxi1Ev">/files/XJnWzR1pLw0Fhpuxi1Ev</a></td></tr></tbody></table>

### How to use Agent?

1. You can toggle Agent mode from the chat sidebar. &#x20;
2. Once in Agent mode, enter your prompt. This should describe a goal state you would like to accomplish. Be sure to include any additional details highlighting constraints or requirements.&#x20;
3. Once it receives this initial prompt, the agent will begin to think through the problem, and immediately start to write code.
4. The agent will continue to work until the task is complete.

⚠️ The Mito Agent will execute code on your behalf.

#### &#x20; <a href="#smart-debug" id="smart-debug"></a>


# Chat

Chat is like collaborating with a colleague who sees your code, knows your data, and is a Python expert. Its ChatGPT integrated directly into Jupyter. It knows the current code cell you are editing and the column headers of your data, so it can generate code that runs in your analysis without copying and pasting or editing variable names.&#x20;

<figure><img src="/files/WViR2veOXF4sm6ziGVAI" alt=""><figcaption></figcaption></figure>

### How to use Chat?

1. **Open the chat taskpane** by clicking the <img src="/files/dNKQdNk1ptViGnUBUwYm" alt="" data-size="line">  icon in the toolbar on the left hand side of JupyterLab or by pressing `cmd / ctrl + E`.&#x20;
2. **Instruct the AI to write code for you.** Talk to it like you would a colleague who is looking at your computer screen. Mito provides the AI with context about your code and currently defined variables. For example, if you want the AI to filter the column `loan_amount` in datframe `loans_df`, the instruction "Filter loan amount to greater than 100k" should get the job done."
3. **Review the AI generated code.** New code created by the AI is highlighted in green. Code deleted by the AI is highlighted in red. Review the code to make sure the AI has not made any unwanted changes and that you understand the new code.&#x20;
4. **Accept or Reject the AI generated code.**&#x20;
   1. Press `cmd / ctrl + Y` to accept the AI generated code and write it to the current active code cell
   2. Press `cmd / ctrl + U` to reject the AI generated code and return the code cell to its previous state.  &#x20;

### Using Variable Mentions&#x20;

<figure><img src="/files/8xDuMTGdDF99ylkYbcJC" alt="" width="375"><figcaption></figcaption></figure>

To mention a specific variable in chat, enter the @ symbol.&#x20;

You'll then see a list of variables. If you don't see the variable you're looking for, keep tying to filter.&#x20;

### Chat History

You can select an existing chat history, or start a new chat thread by using the icons in the Mito AI sidebar. Use new chat threads to work on isolated problems, or switch to an existing conversation to pick up where you left off.&#x20;


# Autocomplete

When writing code, autocomplete helps you work faster. There's no need to switch tabs or search through documentation—autocomplete completes your thoughts and seamlessly fills in your code.

<figure><img src="/files/YDwhCXGKMuJPSX8rKbCu" alt=""><figcaption></figcaption></figure>

### Using Autocomplete

Just start coding as usual. When you want a suggestion, pause typing, and autocomplete will do the rest. It's that simple!

To accept a code suggestion, use the **Tab** key.&#x20;

### Updating Keyboard Shortcuts

By default, the **Tab** key is used to accept a code suggestion. If this shortcut is not active or if you'd like to customize it, follow these steps:

1. Open **JupyterLab**.
2. Navigate to **Settings > Settings Editor**.
3. In the sidebar, select **Keyboard Shortcuts**.
4. Use the search bar to find **Accept Inline Completion**.
5. Select the current shortcut and update it to your desired keybinding.


# Smart Debugging

Is your code erroring because you typed a variable name incorrectly? Maybe you mixed up your single and double quotes? Or maybe it's something more complicated and nuanced like accidentally running Jupyter code cells out of order. Debugging errors like these can be challenging and frustrating, taking you out of the flow of exploring and analyzing your data.&#x20;

Mito makes it easy to debug these errors using AI. Just ask for help.&#x20;

<figure><img src="/files/eSaCH7RHT1p293N4Suiz" alt=""><figcaption><p>Debugging with AI</p></figcaption></figure>

### How to debug errors using AI?

When a code cell errors, click the `Fix Error in AI Chat` button to have Mito AI automatically try to fix your error. It will use the context of the code cell and variables that you have defined to figure out why your code is erroring and suggest a fix.&#x20;


# Chart Wizard

{% embed url="<https://www.loom.com/share/af38d95fca1e474a95c6c57396a41dee>" %}

Sometimes you just need to make a small tweak to a chart—change a color, update a title, or adjust a label. Routing these quick edits through the AI can slow you down. The **Chart Wizard** is designed to keep you in the flow.

Hover over any chart and you’ll see the **Chart Wizard** button in the upper-right corner.

### Chart Wizard Basics

The Chart Wizard is a set of configurable fields that control the visual appearance of a chart. These fields work together to define things like colors, labels, sizing, and layout.

Instead of prompting the AI, you can adjust these values directly and preview changes in real time.

### Adding Fields

If you don’t see a chart element you want to edit, use the **Add a Field** button at the bottom of the Chart Wizard.

Describe what you’d like to change, and the Wizard will generate a new editable field for that aspect of the chart.

### Converting Charts

The Chart Wizard expects charts to follow a specific code format. Charts generated with recent versions of Mito AI already meet this requirement.

Charts created with older versions of Mito — or sourced externally — may need to be converted first. When this happens, the **Convert** tool will automatically appear.

Running the conversion updates the chart to the expected format while keeping its visual output identical.


# Rules

Control how Mito AI behaves with reusable instructions.

Rules allow you to provide system-level guidance to Mito AI Agent and Chat. Use them to share coding preferences and project details with the AI so it can be a better collaborator.&#x20;

Rules are applied at the start of the user message. This gives Mito AI the opportunity to follow your provided rules as it is writing code, suggesting next steps, or analyzing your data.&#x20;

### How to use rules?

Using rules is a two step process: First create the rule, then reference it in your chats.&#x20;

1. To create a rule, open the Mito AI settings, click on rules, and select Add Rule.&#x20;
2. Then, to share them with your AI assistant, select them from the @ dropdown.

<figure><img src="/files/NJ3ynj2dZVFD4PY4ZCIm" alt=""><figcaption></figcaption></figure>


# Configuring AI Provider Keys

This page explains how to configure Mito Data Copilot to use your own AI API keys instead of the Mito server.

By default, Mito uses our server to send AI requests to the model provider. If instead you want to use your own AI API keys, you can set the following configuration options.&#x20;

### Available Model Providers (Open Source)

If you want to use your own API key instead of ours, you can set the following environment variables depending on which model you want to use. By setting your own API key, you can send unlimited AI requests with Mito without hitting the 150 completion request limit. &#x20;

If you're not sure how to set an environment variable, [read our instructions here](#setting-up-environment-variables).&#x20;

#### OpenAI

* Set `OPENAI_API_KEY` to your OpenAI API key

#### Anthropic (Claude)

* Set `ANTHROPIC_API_KEY` to your Anthropic API key

#### Gemini (Google)

* Set `GEMINI_API_KEY` to your Google API key

### Available Model Providers (Enterprise)&#x20;

If you are a [Mito Enterprise](https://www.trymito.io/plans) user, you can configure Mito to use your enterprise LLM providers. If you have questions about Mito Enterprise, please contact [jake@sagacollab.com](mailto:undefined).&#x20;

There are several benefits to using enterprise model providers:

1. **LLM Model Lockdown**: AI calls ONLY go to IT-approved LLM models. End users cannot change to unapproved LLM models
2. **Telemetry Elimination**: No telemetry is sent to Mito servers

#### Azure Open AI

Set the following environment variables:

* Set `AZURE_OPENAI_API_KEY` to your Azure OpenAI API key
* Set `AZURE_OPENAI_API_VERSION` to specify the API version
* Set `AZURE_OPENAI_ENDPOINT` to your Azure OpenAI endpoint URL
* Set `AZURE_OPENAI_MODEL` to specify the deployed model name

#### Lite LLM

To use LiteLLM, you must set the following environment variables:&#x20;

* Set `LITELLM_BASE_URL` to your LiteLLM server endpoint. ex: `https://my-litellm-server.com`
* Set `LITELLM_MODELS` as a comma-separated list of approved model names for users to select from. ex: `"litellm/openai/gpt-4o,litellm/anthropic/claude-4-5-sonnet"`
  * Model names must be formatted as `litellm/<provider>/<model>` (e.g., `"litellm/openai/gpt-4o"`)
  * Users will default to the first model that you provide.&#x20;
* Set `LITELLM_API_KEY` to the user's API key for authentication with the LiteLLM server.

#### Abacus AI

To use LiteLLM, you must set the following environment variables:&#x20;

* Set `ABACUS_BASE_URL` to your Abacus endpoint. For most users, this will be `https://routellm.abacus.ai/v1`
* Set `ABACUS_MODELS` as a comma-separated list of approved model names for users to select from. ex: `"abacus/gpt-4.1,abacus/abacus/gpt-5"`
  * Model names must be prefixed by `abacus` (e.g., `"abacus/gpt-4o"`)
  * Users will default to the first model that you provide.&#x20;
  * **For best performance with Abacus, use OpenAI models only.**&#x20;
* Set `ABACUS_API_KEY` to the user's API key for authentication with the Abacus AI.

### Setting Up Environment Variables

**The following steps are only for the mito-ai pip package. If you are using Mito Desktop, please see the instructions below.**&#x20;

**Note that** environment variables must be set **before** launching JupyterLab, as they are read when the Mito server extension initializes during startup.

#### Method 1: System Environment Variables

Set environment variables at the system level before starting JupyterLab:

**On Windows:**

```
set GEMINI_API_KEY=your-api-key-here
```

**On macOS/Linux:**

```
export GEMINI_API_KEY=your-api-key-here
```

#### Method 2: .env File with jupyter\_server\_config.py

1. Create a `.env` file in your Jupyter config directory:

```
GEMINI_API_KEY=your-api-key-here
```

2. Create or modify your `jupyter_server_config.py` file to load these variables on startup:

```python
import os
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv('/path/to/your/.env')
```

#### Method 3: Shell Configuration

Add the environment variables to your shell's configuration file for permanent setup:

**On Windows:**

Add environment variables through System Properties > Environment Variables.

**On macOS/Linux:**

Add to your `.bashrc`, `.zshrc`, or equivalent:

```
export GEMINI_API_KEY=your-api-key-here
```

### Setting Environment Variables on Mito Desktop

When using **Mito Desktop**, the steps for setting environment variables vary by operating system. Follow the instructions below for your platform.

**macOS**

On macOS, environment variables can be configured directly through Mito Desktop’s Jupyter settings.

1. Open the Jupyter config directory:

   ```bash
   ~/.jupyter
   ```
2. Open (or create) the file:

   ```
   desktop-settings.json
   ```
3. Update the main JSON object to include your environment variables under `serverEnvVars`:

   ```json
   {
     "serverEnvVars": {
       "GEMINI_API_KEY": "your-api-key-here"
     }
   }
   ```
4. Launch **Mito Desktop**.
5. In a new notebook cell, verify the variable was set:

   ```python
   !printenv
   ```

**Windows**

**Option 1: Using the Windows GUI (recommended)**

From the **Start Menu**, search for **“Edit the system environment variables”** and open it.

1. Click **Environment Variables…**.
2. In the **Environment Variables** window, under **User variables for \<your username>**, click **New…**.
3. Enter the variable name and value, then click **OK** to save.
4. Fully restart **Mito Desktop**.

To verify the variable was set, open a notebook and run:

```python
!set
```

<figure><img src="/files/WGseZjJ1yr0UGU1rQriS" alt=""><figcaption><p>Steps for adding a new environment variable on Windows</p></figcaption></figure>

**Option 2: Using the terminal**

If you prefer the command line, you can set the environment variable using PowerShell or Command Prompt:

```powershell
setx GEMINI_API_KEY "your-api-key-here"
```

After running this command:

1. Close any open terminals.
2. Restart **Mito Desktop**.
3. Verify the variable in a notebook cell:

   ```python
   !set
   ```

### Data Protection Considerations

Remember that when using external AI providers:

* Private data in dataframe names, column headers, or the first five rows of data might be shared with the AI provider
* To maximize data protection, Mito Enterprise users can connect to a self-hosted model


# Using Github Copilot with Mito AI

To use GitHub Copilot with Mito AI:

1. [Install](/getting-started/installing-mito) the Mito AI package.
2. Install the helper package:

   ```bash
   pip install mito-ai-helper-github-copilot
   ```
3. Launch your Jupyter server.

Once the server is running, you should see the Mito AI chat task pane along with instructions for authenticating with GitHub. Follow the on-screen steps to complete the authentication process.

To confirm that Copilot is successfully connected, check the list of available models in the chat task pane. The dropdown should display only Copilot models.


# Database Connectors

Use Mito AI to query you databases in natural language.

With Mito AI, you can get answers from your database without writing a single line of SQL.

### Initial Setup

{% embed url="<https://www.youtube.com/watch?v=sJgphOrmZb4>" %}

You can connect your database from the **Settings** page, under the **Database** tab.&#x20;

The first time you connect, it may take a few seconds while Mito AI analyzes your tables and columns.

### Using Your Database in Chat&#x20;

In the chat task pane, you can ask questions about your database. Mito AI will usually detect and use the connected database automatically, even if you don’t mention it explicitly.

That said, being specific—such as naming a table or column—often improves the accuracy of responses.

Alternatively, you can use the **@** key to bring up the variable dropdown menu, where you can search for you database (using its alias), and explicitly reference the database.&#x20;

### FAQs

#### **What databases are supported?**

Currently Mito AI supports:

* Microsoft SQL Server
* MySQL
* Oracle
* PostgreSQL
* Snowflake
* SQLite

#### **Do you store my database credentials?**&#x20;

No. Your database credentials are stored locally on your machine. Mito AI references your credentials through a local config file when establishing a connection.

Your credentials are never sent to our servers or stored remotely.


# Database Drivers

### What is a Driver?

A driver is a piece of software that enables communication between your computer and a database. Each database provider (e.g., PostgreSQL, Snowflake, MySQL) requires a specific driver to function correctly.

### How Mito AI Handles Drivers

Mito AI manages database drivers for you automatically. When you attempt to connect to a database through Mito AI:

1. **Driver Check**: Mito AI checks whether the required driver is already installed in your environment.
2. **Automatic Installation**: If the driver is not found, Mito AI will automatically install the correct pip package.
3. **Environment Awareness**: If you're working within a virtual environment (such as a venv or conda environment), the driver will be installed into the currently active environment.

This process ensures you can focus on your analysis instead of dependency management.

### Which Drivers Are Installed?

Below is a list of drivers Mito AI installs, based on the database you're connecting to:

| Database             | Driver (pip package)  |
| -------------------- | --------------------- |
| Microsoft SQL Server | pyodbc                |
| MySQL                | PyMySQL               |
| Oracle               | oracledb              |
| PostgreSQL           | psycopg2-binary       |
| Snowflake            | snowflake-sqlalchemy  |
| SQLite               | Built-in (no install) |


# Microsoft SQL Server

To connect to a Microsoft SQL Server, you must have the **ODBC Driver for SQL Server** installed on your local machine. Installation instructions vary by operating system and can be found on [Microsoft's website](https://learn.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver17).

### Windows

For users on Windows, the ODBC driver can be [downloaded here](https://learn.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver17#download-for-windows).

### macOS

For users on a Mac, the easiest option is to use Homebrew:

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release
brew update
HOMEBREW_ACCEPT_EULA=Y brew install msodbcsql18 mssql-tools18
```

This will install Homebrew, and the ODBC driver. More info can be found on [Microsoft's website](https://learn.microsoft.com/en-us/sql/connect/odbc/linux-mac/install-microsoft-odbc-driver-sql-server-macos?view=sql-server-ver17).


# Snowflake

### How to Find Your Snowflake Credentials

1. Log in to your Snowflake account.
2. In the sidebar, click your **username**.
3. Hover over **Account** and select **View Account Details**.

   <figure><img src="/files/r0AMguFawYp8oh3SGcpt" alt=""><figcaption></figcaption></figure>
4. In the **Account Details** window, go to the **Config File** tab.

   <figure><img src="/files/Kq6x3nx0GhOyyceY1B8B" alt=""><figcaption></figcaption></figure>
5. From the dropdown, select the appropriate **warehouse** (see arrow 0 in the screenshot).
6. Your **account name** (labeled #1) and **warehouse** (labeled #2) will now be visible.

### Troubleshooting

#### Failed to install snowflake drivers **error**

This error is most likely occurring because you're using Python 3.13. The official Snowflake database drivers currently support only up to Python 3.12. To fix the issue, downgrade to Python 3.12 or earlier.


# Mito AI MCP Server

Connect and use the Mito Agent in your application of choice using an MCP server

This server enables LLMs to perform better data analysis and visualization, including best-in-class Excel-to-Python workflows.

### Prerequisites&#x20;

To use the Mito AI MCP server the only requirement is uv. You can find installation instructions [here](https://docs.astral.sh/uv/getting-started/installation/).

### Cursor

**One-click install**

For quick installation, use the one-click install:

[![Install in Cursor](https://img.shields.io/badge/Cursor-UV-000000?style=flat-square\&logo=cursor\&logoColor=white)](https://trymito.io/install/cursor?method=uv)

<details>

<summary>Manual install instructions</summary>

To manually add the server to Cursor, open the Command Palette (`Ctrl + Shift + P`) and go to `Cursor Settings: Tools & MCPs`. Scroll to *Install MCP Server* and select *Add Custom MCP*. This will open a JSON file with an `mcpServers` object, add the appropriate config there:

```json
{
  "mcpServers": {
    "mito-ai": {
      "command": "uvx",
      "args": [
        "mito-ai-mcp"
      ]
    }
  }
}
```

</details>

### VS Code

**One-click install**

For quick installation, use the one-click install:

[![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-UV-0098FF?style=flat-square\&logo=visualstudiocode\&logoColor=white)](https://trymito.io/install/vs-code?method=uv)

<details>

<summary>Manual install instructions</summary>

For manual installation, add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.

Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace. This will allow you to share the configuration with others.

> Note that the `mcp` key is needed when using the `mcp.json` file.

Add the following MCP config:

```json
{
  "mcp": {
    "servers": {
      "mito-ai": {
        "command": "uvx",
        "args": ["mito-ai-mcp"]
      }
    }
  }
}
```

</details>

### Claude Desktop

**One-click install**

1. Download the mcp bundle: [![mito-ai-mcp.mcpb](https://img.shields.io/badge/Claude-mcpb-DE7356?style=flat-square\&logo=claude\&logoColor=white)](https://github.com/mito-ds/mito/releases/latest/download/mito-ai-mcp.mcpb)
2. Double-click the `.mcpb` file. This should open Claude; follow the directions on screen.

### Claude Code

In your terminal enter:

```bash
claude mcp add --transport stdio mito-ai -- uvx mito-ai-mcp
```

You should see a success message on submit. You can also enter `claude` from the terminal, and use the `/mcp` command to make sure the mito-ai MCP server is connected.

### Other Applications

To connect the to this server in another MCP-compatible app, find its MCP settings page in the docs.

Then add:

* **Name**: mito-ai
* **Type**: stdio
* **Command**: uvx
* **Arguments**: mito-ai-mcp

\ <br>


# AI Data Usage FAQ

### What data does Mito AI use?

Mito AI uses the instructions you provide (the prompt) and information about your dataframe and variables to generate code that works in the context of your analysis. Without this information, the AI generated code will require additional customization.

Private data that is contained in the dataframe name, column headers, or first five rows of data might be shared with Mito and OpenAI.

### How is my data used?

The data collected by Mito AI is used to construct a prompt for OpenAI. Mito supplements the prompt you provide with additional information about your data to give OpenAI the best chance of generating helpful code.

The data collected is also used to improve Mito AI. Such uses include:

* Evaluating Mito AI to determine its effectiveness.
* Conducting research to improve Mito AI.
* Detecting potential abuse of Mito AI.

Read [Mito](https://privacy.trymito.io/privacy-policy) and [OpenAI’s](https://openai.com/policies/privacy-policy) privacy policy for more information.

### How can I further protect my data?

Mito AI uses OpenAI to generate code by default. Doing so requires sending your information to OpenAI. To further protect your data, Mito Enterprise users can connect Mito AI to a self-hosted large language model. As a result, Mito would not need to collect or share any information about your data with OpenAI. Your data will never leave your system.

To learn more about this option, send an email to <jake@sagacollab.com>

### Can I use my own OpenAI API key?

If you want to route your completion through OpenAI servers directly, you can provide your own OpenAI API key.

#### Using Public OpenAI

If you want to use the public OpenAI API, you can set the environment variable OPENAI\_API\_KEY to your OpenAI key. You can [create an api key here](https://platform.openai.com/api-keys) and [follow these instructions to set it as an environment variable](https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety).&#x20;

#### Using Enterprise OpenAI&#x20;

If you have an enterprise account with OpenAI and you would like to use it, please reach out to <jake@sagacollab.com> who can explain how to set it up.&#x20;


# Mito Apps

Deploy your Jupyter notebooks as Streamlit apps with the click of a button.

### How to deploy your app?

1. Create a new directory for your app. The directory should only contain:
   1. **The jupyter notebook** you want to deploy as a streamlit app
   2. **Any required data or config files** that are required to execute the jupyter notebook.
2. Give the directory a useful name. This name will be used to generate your Streamlit app url.&#x20;
3. Turn on beta features by:
   1. Opening the Mito AI taskpane&#x20;
   2. Clicking on the `gear icon` in the top left hand corner
   3. Selecting the `General` tab
   4. Toggling `Beta mode` on
   5. Refresh your browser. You should now see a purple button in the top right hand corner of your Jupyter notebook toolbar that says `Deploy App`.
4. Once you are ready to convert your notebook, click the `Deploy App` button. Watch for status updates in the bottom ride hand corner of your sceen. In about 3 minutes, your app will be deployed and ready to share with your colleagues.&#x20;

{% hint style="info" %}
Mito Apps is in beta. As we continue to develop the Mito App infrastructure, your existing apps are likely to be taken offline without notice.&#x20;
{% endhint %}


# Core Concepts

Introduces you to the high-level concepts helpful in understanding how the Mitosheet works.

### The mito spreadsheet in a notebook

Mito is a spreadsheet that exists inside of a Jupyter Notebook, and helps you do Python data analytics. You can use Mito to explore and edit data like you would in Excel or Python.

<figure><img src="/files/CGfGKS8Rf492bbXzBhHc" alt=""><figcaption><p>A Mito spreadsheet inside of a JupyterLab notebook.</p></figcaption></figure>

### Pandas dataframes and the Mito Spreadsheet

Pandas is the most popular data analysis and manipulation tool in Python. It is based around the core concept of a "dataframe," which is a rectangular table of data with columns and rows.

Normally, you would write pandas code directly to manipulate your data, but by using Mito, you can explore and manipulate your dataframes in the mitosheet, directly within your notebook. Every tab inside of your Mitosheet represents a different Pandas dataframe.

Click the `Add Column` button in Mito? A column gets added to your dataframe. Pivot your data to create aggregate statistics? A new, tab with an aggregated dataframe is created.

### Generating Pandas Code

For each edit you make to the Mitosheet, Mito generates pandas code below that corresponds to this edit, and puts this code directly below the mitosheet in the next code cell.

<figure><img src="/files/XsfiGju6DoxyvUd0V2VC" alt=""><figcaption><p>Code generated by Mito: importing a CSV file and adding a column.</p></figcaption></figure>

### Rerunning an analysis

When you run `mitosheet.sheet()`, Mito will automatically generate a unique ID to store the set of edits make to this mitosheet. This ID will appear as an automatically generated `analysis_to_replay` parameter to the `mitosheet.sheet()` function call.

As long as you pass this `analysis_to_replay` parameter to the `mitosheet.sheet()` call, Mito will attempt to replay that analysis to the mitosheet. Replaying an analysis means applying the same edits that you did in Mito again.&#x20;

Since Mito will try and apply the same edits when an `analysis_to_replay` parameter is passed, *differently structured datasets* might make these edits invalid and Mito will error. For example, if you change the location of the file that you imported in an analysis, and then attempt to replay this analysis, it will fail (as it can no longer find the file to import).

If you want to start a fresh mitosheet, simply make a new `mitosheet.sheet()` call in a new code cell.


# Creating a Mitosheet

Use Mito to generate Python code, start automating your Excel processes.

{% hint style="warning" %}
Before creating a Mitosheet, make sure [you've installed Mito](/getting-started/installing-mito). If you just installed Mito, **make sure to restart your kernel + refresh your browser.**
{% endhint %}

### Create a new mitosheet

1. Open the Notebook where you want to create the mitosheet. If you installed Mito in a virutal environment, make sure to [launch the notebook from the same virtual environment](/how-to/creating-a-mitosheet/open-existing-virtual-environments).&#x20;
2. Copy and paste this code into a cell:

```python
import mitosheet
mitosheet.sheet()
```

3. Run the code by clicking on the code cell that contains it and pressing **Shift + Enter**.
4. Follow the instructions to [import data into Mito](/how-to/importing-data-to-mito).

### Reopen an existing mitosheet

If you've already created a mitosheet that you want to continue working from:

1. Open the Notebook where you previously created the mitosheet. If you installed Mito in a virutal environment, make sure to [launch the notebook from the same virtual environment](/how-to/creating-a-mitosheet/open-existing-virtual-environments).&#x20;
2. Click on the code cell that contains the `mitosheet.sheet(...)` call that you want to reload, and press **Shift+Enter**.

If you want to learn more about reopening an existing mitosheet, read [this section](/how-to/overview-of-the-mitosheet#rerunning-an-analysis) of the Core Concepts overview. &#x20;

### Common Errors

#### First time creating a mitosheet

If this is the first mitosheet you are creating after installing Mito, view these [common install errors](/getting-started/installing-mito/common-install-errors).

#### ModuleNotFoundError

<figure><img src="/files/Hwk77ampLK7o7M71KwN4" alt=""><figcaption></figcaption></figure>

If you've previously created a mitosheet, and you see this **ModuleNotFoundError** after running the above code, its likely because the mitosheet package is not installed in your current environment.&#x20;

Make sure to launch [launch the notebook from the same virtual environment](/how-to/creating-a-mitosheet/open-existing-virtual-environments) that you installed Mito in.&#x20;

**NameError**

<figure><img src="/files/I4JnN0z1Uj8f9lLzHRbu" alt=""><figcaption></figcaption></figure>

If after running the `mitosheet.sheet()` code, you see this **NameError**, you have to first import the mitosheet package.&#x20;

1. Copy this code into your notebook above the `mitosheet.sheet()` call

```
import mitosheet
```

2. Click on the `import mitosheet` code and press **Shift + Enter**&#x20;
3. Click on the `mitosheet.sheet()` code and press **Shift + Enter**

{% hint style="info" %}
Want help? Get in contact with our support team through [Discord](https://discord.gg/XdJSZyejJU), [Slack](https://join.slack.com/t/trymito/shared_invite/zt-1h6t163v7-xLPudO7pjQNKccXz7h7GSg), or by emailing <jake@sagacollab.com>
{% endhint %}


# Open Existing Virtual Environments

Reopen your existing virtual environments to keep working where you left off.

If you installed Mito in a virtual environment, follow these instructions to relaunch your Mito environmnet.&#x20;

## How to open open an Existing Virtual Environment&#x20;

{% tabs %}
{% tab title="Python Virtual Environment" %}
Activate your environment&#x20;

* **On Windows** in command prompt:

{% code fullWidth="true" %}

```
mitoenv\Scripts\activate.bat
```

{% endcode %}

* **On Mac**:

```
source mitoenv/bin/activate
```

Launch JupyterLab

```
jupyter lab
```

Then either create a new mitosheet or rerun an existing mitosheet.sheet() call
{% endtab %}

{% tab title="Anaconda Navigator" %}

1. Open Anaconda Navigator
2. Click on the `Home` button
3. Select your Mito environment

<figure><img src="/files/pMo953YEWm6CtN2JRyKv" alt=""><figcaption></figcaption></figure>

4. Find the `JupyterLab` title and press `Launch`
   {% endtab %}

{% tab title="Conda Virtual Environment" %}
Activate your environment

```
conda activate mitoenv
```

Launch Jupyter Lab

```
jupyter lab
```

Then, follow these instructionst to [create a new mitosheet](/how-to/creating-a-mitosheet).&#x20;
{% endtab %}
{% endtabs %}


# Importing Data

Mito supports any tabular data, like what you find in a pandas dataframe, an SQL database, a table on a website, or a table in a spreadsheet. Getting this data into Mito is a breeze.

Like other spreadsheets, you can import *multiple* tabular dataframes from mulitple sources into Mito, and each of them are displayed as a seperate tab. This allows you to work with and manipulate multiple pieces of data at once.

## Import Methods

{% content-ref url="/pages/f7Y5nAfnp5AbjMyYOJj2" %}
[Importing CSV Files](/how-to/importing-data-to-mito/importing-csv-files)
{% endcontent-ref %}

{% content-ref url="/pages/oNmt0V4IR1OnAzDnX883" %}
[Importing from Excel Files](/how-to/importing-data-to-mito/importing-from-excel-files)
{% endcontent-ref %}

{% content-ref url="/pages/j3IxecQBTPTIPbvEu9i1" %}
[Importing Dataframes](/how-to/importing-data-to-mito/importing-dataframes)
{% endcontent-ref %}

{% content-ref url="/pages/7r2ByTtVflMUSvDl1ae0" %}
[Importing from a remote drive](/how-to/importing-data-to-mito/importing-from-a-remote-drive)
{% endcontent-ref %}

{% content-ref url="/pages/RYSqqCta5GoNRCujrzbW" %}
[Importing from other sources](/how-to/importing-data-to-mito/importing-from-other-sources)
{% endcontent-ref %}


# Importing CSV Files

How to import a CSV file into Mito.

1. Click on the `Import` button in the Mito toolbar.
2. Select the **Import Files** option that appears in the dropdown.
3. Use the file browser to navigate to the directory and CSV file you want to import.
4. Click on the file, and then click the `Import` button.
5. The CSV file should appear as a tab in your mitosheet.

<figure><img src="/files/nbgmwb70pJpkfbMuBrVj" alt=""><figcaption></figcaption></figure>

### Importing a CSV file from a different directory

If your CSV file is in a different directory that the current notebook, you might need to navigate the file browser to find it.

1. Double click on a folder to enter the folder and see it's contents.
2. Double click on the `<- Parent Folder` to navigate to the parent of this folder.

### Importing multiple CSV files

To import mulitple CSV files, simply repeat the process of importing a single CSV. Each of the imported CSVs will appear as a separate tab in your mitosheet.

### Configuring a CSV import

Mito automatically the correct parameters to import your CSV file in over 90% of cases. In the case that Mito cannot correctly guess the delimeter or encoding of your file, or there are some invalid lines, you can manually configure the CSV import to get your data imported.

1. Click on the `Import` button in the Mito toolbar.
2. Use the file browser to navigate to the directory and CSV file you want to import.
3. Click on the file, and then click the `Configure` button.
4. If necessary, update the config options:
   1. `Delimiter`: The seperator that seperates one column from another.
   2. `Encoding`: The encoding used to save this file.
   3. `Decimal Separator`: The character used to separate the decimal places in numbers.
   4. `Number of Rows to Skip`: The number of rows at the top of the file to skip when reading data into the dataframe.
   5. `Skip Invalid Lines`: Turn on to skip any lines that error when being read in.
5. Click the `Import` button, and your dataframe should appear as a tab in your mitosheet.

   <figure><img src="/files/kSbp0Q0XaJ4w2z88xvYo" alt="" width="375"><figcaption><p>Configuring a CSV Import.</p></figcaption></figure>

#### Importing a CSV from a remote drive <img src="/files/DmUTL0R5lIJX6fWCGuJs" alt="" data-size="line">

Mito supports importing CSV files from remote drives, including shared drives, network drives, Dropbox, etc.&#x20;

[Upgrade to **Mito Pro**](https://trymito.io/plans) to access this feature.


# Importing from Excel Files

How to import a Excel file into Mito.

*Version requirements: Importing XLSX files is only supported on Python version greater than 3.6, and Pandas version greater than or equal to 1.0.*&#x20;

## Importing multiple tabs from a single Excel file

1. Click on the `Import` button in the Mito toolbar.
2. Select the `Import Files` option that appears in the dropdown.
3. Use the file browser to navigate to the directory and XLSX file you want to import.
4. Click on the file, and then click the `Import` button. This will open a configuration screen.
5. Configure which tabs you want to import from the Excel file.
6. Set any additional configuration necessary for your import:
   1. `Has Header Row`: Select "Yes" if Mito should set the first non-skipped row as the column headers. Select "No" if Mito should generate column headers
   2. `Number of Rows to Skip`: The number of rows at the top of the file to skip when reading data into the dataframe.
   3. `Decimal Separator`: The character used to separate the decimal places in numbers.
7. Click `Import Selected Sheets`. For each tab you selected to import, a tab will appear in the mitosheet with this data.

<figure><img src="/files/XqyQeBQj8D2qSkvtckta" alt="" width="375"><figcaption></figcaption></figure>

### Importing Specific Ranges from a single Excel Sheet

1. Click on the file, and then click the `Import` button. This will open a configuration screen.
2. Use the file browser to navigate to the directory and XLSX file you want to import.
3. Select the `Import Files` option that appears in the dropdown.
4. Click on the `Import` button in the Mito toolbar.
5. Select the *single* sheet you wish to import specific ranges from. An additional option will appear in the taskpane asking if you want to import multiple ranges from this sheet, click this.
6. Click the `+ Add` button to add additional ranges.

#### Configure the imported range

1. Name the dataframe you are importing.
2. Configure how to locate th start of the dataframe:
   1. `Exact Range`: Import based on address like A10:C100, where you give the exact location of the dataframe.
   2. `Upper Left Corner`: Input the value at the upper left corner of the dataframe. Mito will keep taking columns until an empty cell is hit.
3. If you selected `Upper Left Corner`, configure how to find the end of the dataframe:
   1. `First Empty Cell`: Mito will scan the column where the `Upper Left Corner` is found until the first empty cell is found. This will determine the end of the dataframe.
   2. `Bottom Left Corner`: Mito will scan the column where the `Upper Left Corner` is found until the `Bottom Left Corner` value is found.
4. Click import to read in the specific ranges you have configured above.

<figure><img src="/files/GTTjCJipWbSzp8enmQ2b" alt="" width="375"><figcaption><p>The Excel Range Import interface.</p></figcaption></figure>


# Importing Dataframes

How to import dataframes file into Mito.

### Importing Dataframes through the Mitosheet

If you have a dataframe you created with Python, and you want to import it into your Mitosheet:

1. Click the **Import** button in the toolbar.
2. Click the **Import Dataframes** options in the dropdown that appears.
3. Click the **+ Add** button to add a dataframe that is exists.
4. Click **Import Dataframes** to impor these dataframes into your sheet.

<figure><img src="/files/Dv1QuHaJoziwm7HNYq0x" alt=""><figcaption></figcaption></figure>

### Importing Dataframes through Mitosheet.sheet()

Importing a dataframe into Mito is as simple as adding the dataframe as a parameter to the `mitosheet.sheet` call.

If we are attempting to import a dataframe named `sales_data:`

1. Create a new code cell with the code:

```python
import mitosheet
mitosheet.sheet(sales_data) # Change sales_data to the name of your dataframe
```

Then, run this cell. A mitosheet will appear with a single tab that contains this dataframe, which you can now begin exploring, editing, and more.

### Importing multiple dataframes at once

Mito allows you to import as many dataframes as you want. Each dataframe you import will be displayed in the mitosheet as a separate tab.

Imagine if we want to import `sales_data` and `customer_metadata` into the same mitosheet, so we can work with both of them at the same time.

```python
import mitosheet
mitosheet.sheet(sales_data, customer_metadata) # Change to your dataframes
```


# Importing from a remote drive

How to import CSV and Excel files from a remote file system.

<img src="/files/9xRk4lkMXj0q5fU8ccAw" alt="" data-size="line"> [*Mito Pro*](https://www.trymito.io/plans) *users are able to import data from external drives like mapped network drives, OneDrive, and USB sticks.* [*Upgrade to access this feature.*](https://www.trymito.io/plans)

## How to import from a remote drive

To import from an external drive:

1. Click on the `Drive` icon in the Import Taskpane's path navigator.
2. Double click the drive you want to import from to see it's contents.
3. Find the file you want to import, and import it as a you would a [CSV file](/how-to/importing-data-to-mito/importing-csv-files) or [Excel file](/how-to/importing-data-to-mito/importing-from-excel-files).

<img src="/files/kszxO4JFfIGY4FXUUUdl" alt="" width="375">


# Import: Generated UI from any Python Function

Automatically generate UI's to import data from your enterprise's databases.

{% hint style="info" %}
&#x20;This is a [Mito Enterprise](https://trymito.io/plans) feature. [Upgrade](https://www.trymito.io/plans) to extend your spreadsheet with additional spreadsheet functions.
{% endhint %}

The Mito spreadsheet is built to be extensible to your teams use case. Mito users can augment the data analysis capabilities of their team by incorporating existing Python functions into their sheet.&#x20;

Namely, any function that returns a dataframe can be exposed to a Mito user within a spreadsheet, automatically. **This allows less-technical teammates to benefit from all the Python code written by the programmers in your org, without these less-technical folks needing to learn to code! Also, it requires no additional UI building by you!**

See also: [bring your own spreadsheet functions.](/how-to/interacting-with-your-data/bring-your-own-spreadsheet-functions)

## How to add a custom importer into Mito

Imagine we have a function that takes some inputs and returns a dataframe:

```python
def get_loan_data(date: str, include_duplicates: bool) -> pd.DataFrame:
    ...
```

You can simply pass this to the mitosheet call in a notebook or Streamlit:

```python
# In a notebook
mitosheet.sheet(importers=[get_loan_data])

# In Streamlit
spreadsheet(importers=[get_loan_data])
```

Then, this function will be accessible in the **Import** dropdown within the mitosheet, where an option for **Get Loan Data** will appear.

<figure><img src="/files/rI8KtWpaPYQgABLjdpov" alt="" width="188"><figcaption><p>The new import option is created.</p></figcaption></figure>

Selecting this option will open a UI this is automatically generated for this function:

<figure><img src="/files/4Re54AqwHamQrsKoioLn" alt="" width="375"><figcaption><p>The interface generated automatically by this Python function.</p></figcaption></figure>

## Adding a custom importer to Mito in Streamlit

Simply use the `importers` parameter to the `spreadsheet` component in Streamlit. See more in the [Streamlit API reference.](/mito-for-streamlit/api-reference)

## Supported Types

For Mito to automatically generate the correct UI for your function, it should have Python types attached to it. The currently supported types:

<table><thead><tr><th width="161">Type</th><th>UI Element</th></tr></thead><tbody><tr><td>str</td><td>A string input.</td></tr><tr><td>int</td><td>A number input. The input will be cast with the <code>int</code> function.</td></tr><tr><td>float</td><td>A number input. The input will be cast with the <code>float</code> function.</td></tr><tr><td>bool</td><td>A toggle. The input will be cast with the <code>bool</code> function.</td></tr><tr><td>pd.DataFrame</td><td>A dataframe select, allowing users to select from the dataframes in Mito.</td></tr><tr><td>List[int]</td><td>A list of number inputs. Each input will be cast with the int function.</td></tr><tr><td>Dict[str, str]</td><td>A pair of string inputs.</td></tr><tr><td>ColumnHeader</td><td>A column select, referencing the nearest pd.DataFrame type. <a href="#columnheader">See below.</a></td></tr><tr><td><em>unlabeled</em></td><td>An input that will be evaluated with the Python <code>eval</code> function.</td></tr></tbody></table>

#### Understanding the ColumnHeader type

The `ColumnHeader` type can be imported from the Mito extension package, and tells Mito to generate a UI that allows a user to select a specific column from the preceding dataframe in the auto-generated UI.

```python
import pandas as pd
from mitosheet.extensions.v1 import ColumnHeader

def extension_function(df: pd.DataFrame, column_header: ColumnHeader):
    # insert function here
```

Notably, any ColumnHeader parameter will error if it is not preceeded by a `pd.DataFrame` parameter -- as it is unclear which dataframe the `ColumnHeader` is referencing!

## Examples

**Using the List\[int] data type to let users filter a dataframe to relevant rows.**

```python
import mitosheet
import pandas as pd
from typing import List

def get_fund_data(fund_ids: List[int]):
    fund_performances = pd.DataFrame({
        'Fund ID': [1,2,3,4,5,6,7,8,9],
        'June Returns': [.1,.2,.3,.4,.5,.6,.7,.8,.9],
        'July Returns': [.1,.2,.3,.4,.5,.6,.7,.8,.9]
    })
    
    # Filter the dataframe to only include the fund_ids set by the user
    filtered_fund_data = fund_performances[fund_performances['Fund ID'].isin(fund_ids)]
    
    return filtered_fund_data
    
mitosheet.sheet(importers=[get_fund_data])
```

<figure><img src="/files/SF7xeHvr29CZ4sLy8X0r" alt=""><figcaption></figcaption></figure>


# Importing from other sources

Import any pandas dataframe into Mito.

Because Mito works seamlessly with Pandas dataframes, with only a bit of custom code, you can get any data you want into a mitosheet.

### Importing from a database

Here, we provide some internal links for reading from common databases into Pandas dataframes:

* [MySQL](https://pynative.com/python-mysql-select-query-to-fetch-data/)
* [Oracle](https://blogs.oracle.com/connect/post/run-sql-data-queries-pandas)
* [Sqlite](https://www.sqlite.org/index.html)
* [PostgresSQL](https://naysan.ca/2020/05/31/postgresql-to-pandas/)
* etc. Simply google "Reading {database name} into pandas dataframe" to get a tutorial for your database!

After getting the data from your database into a dataframe, simply [import the dataframe](/how-to/importing-data-to-mito/importing-dataframes) into Mito.

### Importing from a webpage

Pandas provides an easy solution for getting data from a webpage into a pandas dataframe, which you can then pass to Mito. See a tutorial that uses the `pd.read_html` function [here.](https://pbpython.com/pandas-html-table.html)

After getting this webpage data into a dataframe, simply [import the dataframe](/how-to/importing-data-to-mito/importing-dataframes) into Mito.

### Other connections

If you have data from a different data source you're looking to read into Mito, the first step is to get it into a pandas dataframe. Simply google "Reading {data source} into pandas dataframe," and you will most likely find an easy three-step tutorial for doing just this.

Then, after getting the data from your data source into a dataframe, simply [import the dataframe](/how-to/importing-data-to-mito/importing-dataframes) into Mito to begin to work with it.

{% content-ref url="/pages/j3IxecQBTPTIPbvEu9i1" %}
[Importing Dataframes](/how-to/importing-data-to-mito/importing-dataframes)
{% endcontent-ref %}


# Graphing

This documentation explains how to create presentation-ready graphs in Mito.

Graphing in Mito is designed to help you build intuition about your data and create presentation-ready graphs to communicate insights. Mito creates interactive and customizable graphs using the [Plotly Express](https://plotly.com/python/plotly-express/) open source graphing library.

Like everything in Mito, when you create a graph, Mito generates the equivalent Python code so have complete control of your analysis.

<figure><img src="/files/6b4w1pyH132JRJdUAWOM" alt=""><figcaption><p>Creating a graph in Mito</p></figcaption></figure>

### How to create a graph in Mito

There are a few steps to creating a graph in Mito:

{% content-ref url="/pages/hSvqYlWsHGvcWhWwlhye" %}
[Graph Creation](/how-to/graphing/graph-creation)
{% endcontent-ref %}

{% content-ref url="/pages/f9l4UvyTihoN7Sd7pJEz" %}
[Graph Styling](/how-to/graphing/graph-styling)
{% endcontent-ref %}

{% content-ref url="/pages/Kg1h6EFLTOoI12UsEZMf" %}
[Graph Export](/how-to/graphing/graph-export)
{% endcontent-ref %}


# Graph Creation

Generate interactive, presentation-ready graphs using Mito's point and click interface.

### Opening a new graph

To begin creating a graph, click the `Graph` button in `Home` tab of the Mito toolbar. This will open up a blank graph that you can then begin to configure.

### Setting up the graph

`Data Source`: The sheet that contains the data that you want to graph.

`Chart Type`: The type of graph that you want to create. Mito supports:

* [Scatter plots](https://plotly.com/python/line-and-scatter/)
* [Line charts](https://plotly.com/python/line-charts/)
* [Bar charts](https://plotly.com/python/bar-charts/)
* [Histograms](https://plotly.com/python/histograms/)
* [Box plots](https://plotly.com/python/box-plots/)
* [Violin plots](https://plotly.com/python/violin/)
* [Strip plots](https://plotly.com/python/strip-charts/)
* [Density heatmaps](https://plotly.com/python/2D-Histogram/)
* [Density Countour maps](https://plotly.com/python/2d-histogram-contour/)
* [ECDF (Emprical Cumulative Distribution Function) graphs](https://plotly.com/python/ecdf-plots/)

`X Axis`: The data to graph along the x axis.

* You can select multiple series either along the x or y axis (not both) as long as the series have similar dtypes.

`Y Axis`: The data to graph along the y axis.

* You can select multiple series either along the x or y axis (not both) as long as the series have similar dtypes.

`Color by Column`: An additional column to further breakdown the graphed data using the color attribute.

* For best results, select a column with few unique values.
* This option is selectable for all graphs expect the `Density heatmap`.

`Filter to safe size`: By default, Mito only graphs the first 1000 rows of data to ensure that the browser tab doesn't crash while attempting to load too much data into the graph. Turning off filter to save size graphs the entire dataframe and may slow down or crash your browser tab.

<figure><img src="/files/oifXVZU0vOBnPsKOMeT2" alt=""><figcaption><p>Setting up a graph in Mito</p></figcaption></figure>

### Graph Specific Configurations

Configure specific graph parameters: for Histograms, set the number of bins, for line plots, define how the line is build, etc.

### Facet Plot

Configure the graph by splitting into multiple subplots (or facet plots) based on a column in your dataframe.


# Graph Styling

Set graph titles, axises, colors and more to create presentation-ready graphs.

### Styling a graph

Click the `Style` tab in the toolbar to configure your graphs styling options.

#### Titles

`Graph Title`: The main title of the graph.

`X-axis Title`: The title of the X axis.

`Y-axis Title`: The title of the Y axis.

`Display Title`: Toggle to OFF to remove the title from the graph. Toggle to ON to display the title of the graph.

`Display X-Axis Title`: Toggle to OFF to remove the title from the X axis. Toggle to ON to display the title on the X axis.

`Display Y-Axis Title`: Toggle to OFF to remove the title from the X axis. Toggle to ON to display the title on the X axis.

**Transformations**

`X Axis Transform`:  The type of axis to use. Select from: default Plotly behavior, linear, log, date, or categorical.&#x20;

Y `Axis Transform:` The type of axis to use. Select from: default Plotly behavior, linear, log, date, or categorical.&#x20;

**Legends:**

`Display Legend`:  Toggle to turn of a legend, if it is displayed.

`Orientation`:  Put the legend horizontially or vertically.

`Legend Title`:  The title of the legend.

`X position`:  Where to place the legend horizontally in the graph (-2 to 3) .

`Y position`:  Where to place the legend vertically in the graph (-2 to 3) .

**Grid Lines:**&#x20;

`Show vertical grid`:  Toggle to turn off vertical grid lines.

`Show horizontal grid`:  Toggle to turn off horizontal grid lines.

`Vertical grid width`:  The width of the vertical grid lines.

`Horizontal grid width`:  The width of the horizontal grid lines.

**Colors**

`Plot Background Color`:  The background color of the area inside of the graph. (only available in Mito Pro)

`Paper Background Color`:  The background color of the area outside the graph. (only available in Mito Pro)

`Title Color`:  The color of the title (only availabe in Mito Pro).

`X axis title color`:  The color of the x axis title (only available in Mito Pro).

`Y axis title color`:  The color of the y axis title (only available in Mito Pro).

**Facet Styling**

`Number of columns`:  The number of columns to display the facet plot with.

`Column spacing`:  Distance between columns of the facet plot.

`Row spacing`:  Distance between rows of the facet plot.

**Range Slider**

`Display range slider`: The range slider is a horizontal bar underneath the x axis of the graph that can be used to zoom in on specific ranges of the graph. Toggle to OFF to remove the range slider. Toggle on ON to display the range slider


# Graph Export

Export your graphs as Python code, images or HTML files to share your insights with your peers.

### Exporting a graph

1. Click the `Export` button in the Chart Design tab.
2. Click the export method you want:
   1. `Copy Show Graph Code`: Copy the Plotly graph code that **displays the graph in the notebook** to your clipboard so you can paste it into a code cell.
   2. `Copy Export HTML Graph Code`: Copy the Plotly graph code that **exports the graph as an interactive HTML file** to your clipboard so you can paste it into a code cell. Executing the code will create the html file in the same folder the notebook is in.
   3. `Download as PNG`: Download the graph as a PNG to your Downloads folder.

### How to use the Exported HTML graph code

Interactive graphs are a fantastic way to share analyses with colleagues. It allows them to zoom in on specific sections of the graph and identify specific data points.&#x20;

To create an HTML graph file:

1. Create a graph using Mito
2. Click the **Copy Export HTML Graph Code** button in the Export dropdown on the Chart Design tab of the toolbar.&#x20;
3. Paste the code into a new code cell and execute the code.&#x20;
4. The html file will appear in the the same folder as your notebook.&#x20;

The file contains all of the libraries and data needed to repopulate the graph, so you can attatch the file to an email or post it on an internal wiki without anything else.&#x20;


# Graphing with AI

Create graphs in a single click using AI suggestions.

### Suggested Graphs

<figure><img src="/files/lme3RBkYaXOYIL0BBI0L" alt=""><figcaption></figcaption></figure>

Not sure where to start with a large dataset?

Mitosheet can scan your data and recommend visualizations to help you get oriented quickly. The *suggested graphs* button can be found in the upper right corner of the home ribbon.&#x20;

### Visualize Selection

<figure><img src="/files/aSamFl6Y3eyyUyit8EIF" alt=""><figcaption></figcaption></figure>

Highlight a few columns, and Mitosheet instantly suggests the most useful charts.

No more guessing which columns belong on the X or Y axis. No more trial and error. Just select your data and see it come to life in seconds.


# Pivoting/Group By

Create Excel-like pivot tables using a spreadsheet interface.

## What is a pivot table?

A pivot table is a method of aggregating a dataframe within one or more discrete categories you create. This aggregation might include sums, averages, or other statistics, which the pivot table groups together using a chosen aggregation function applied to the grouped values.

If you're used to doing "group bys" in Pandas, or using Excel Pivot Tables, then you're looking for Pivoting in Mito!

## Creating a pivot table

* Click on the `Pivot` icon in the `Home` tab of the Mito toolbar.
* Add a column to the `Rows` section to construct a key to group the dataframe by.
  * Optionally, to stratify the groups into individual cells, add a column to the `Columns` section.
* Add a column to the the `Values` section to aggregate data within the buckets defined by `Rows` and `Columns` above.
  * Optionally, switch the aggregation method of the column in the `Values` section.
* Optionally, add and configure `Filters` on the pivot table. Notably, these filters are applied to the source dataset before it is pivoted.&#x20;

<figure><img src="/files/BIH4EQPhJVwZl4EUSLyU" alt=""><figcaption></figcaption></figure>

### Group Dates within in Pivot Tables

If you're aggregating based on a `datetime` column (aka: you have a `datetime` column in either the `Rows` or `Columns` section), you can select how to group the date.&#x20;

By default, Mito will group dates by exact time. This means that two rows will be put in the same bucket within the pivot table if the `datetime` column matches to the exact second.&#x20;

However, if you wish to aggregate based on the `year`, then you can change the `group date by` to `year`. This will ignore months, days, minutes, and seconds, and combine all rows in the same year into the same bucket. Create a pivot table to explore all the ways to group dates.

{% hint style="info" %}
If the `group date by` option does not appear after adding a column to the Rows or Columns section of a pivot table, ensure that you have changed the dtype of that column to a `datetime` first.
{% endhint %}


# Filter

This documentation will teach you how to filter datasets in Mito.

There are multiple ways to filter rows out of your dataframe within Mito.&#x20;

If you are looking to filter out rows through the user of conditions (greater than, less than, contains, etc), see:

{% content-ref url="/pages/gE3O0X8pEWQPC1SH96Vn" %}
[Filter By Condition](/how-to/filter-data/filter-by-condition)
{% endcontent-ref %}

If you are looking to filter out specific values:

{% content-ref url="/pages/ZZmiq86eitdJCtFlHBFl" %}
[Filter By Value](/how-to/filter-data/filter-by-value)
{% endcontent-ref %}

If you are looking to just delete specific rows from your dataframe, see [Deleting Rows.](/how-to/deleting-rows)


# Filter By Condition

Use filter conditions like greater than, contains, starts with and much more to filter and explore your data.

Filter by condition allows you to apply filters to a specific column that remove rows from the dataframe by comparing these conditions to the values in the column you are filtering. To filter rows by condition.

1. Click on the `Filter` icon in the header you want to filter.
2. Click the `Filter/Sort` tab in the taskpane that opens.
3. Click the `+ Add Filter` button, and then click `Add a Filter`.
4. Set the condition you want to filter on. Different filter conditions are available for different datatypes.
5. If you add multiple figures, optionally set the `Operator` to `And` or `Or` to change how these filters are combined.
6. Only rows where the filter conditions are met will remain in the dataframe.

<figure><img src="/files/Qzpa4ZhEcaqxuTA99sD1" alt=""><figcaption><p>Filtering to all values > 20.</p></figcaption></figure>

### Filter Groups

Filter Groups are aggregations of filters combined with an **And/Or**. This allows for more complex filters on the specific column.

1. Click on the `Filter` icon in the header you want to filter.
2. Click the `Filter/Sort` tab in the taskpane that opens.
3. Click the `+ Add Filter` button, and then click `Add a Filter Group`.
4. Within the filter group, set the filter conditions and operator.
5. This filter group will be applied to your dataset.


# Filter By Value

View the unique values in your dataset and filter them in/out.

Mito's filtering by value is designed to help you identify all of the unique values in your column, and easily remove the ones you don't want. To filter by value:

1. Click on the `Filter` icon in the header you want to filter.
2. Click the `Values` tab in the taskpane.
3. Optionally, search for the value you want to remove, or change how the values are sorted.&#x20;
4. Toggle a value to filter it out of your dataset.

The values tab displays the count of each element, as well as the percentage of the full dataset this value makes up.

![The values tab allows you to filter by value.](/files/aDgoWC5APkCbrnvDhbF0)


# Mito AI

Mito AI is one of the fastest ways to transform your data. This documentation explains how.

## What is Mito AI?

Mito AI is ChatGPT for your pandas dataframes. Its the easiest way to apply simple edits, like adding filters or parsing strings, to your data.&#x20;

Like ChatGPT, Mito AI is a chat interface for interacting with OpenAI. Unlike ChatGPT:

1. When you use Mito AI to transform your data, it automatically executes the code in the context of your analysis so you'll immediately see the effects on your data. This makes it easier to decide if the code generated by OpenAI was correct or whether you want to undo the edit and try again.
2. Mito AI has context about your data and your analysis. This additional information, which Mito automatically provides to OpenAI without you having to type it out, helps OpenAI generate code that is useful to you right away.

## Using Mito AI

1. Open the AI taskpane by clicking the `AI` button in the toolbar.
2. Describe the transformation that you want the AI to make, press `Enter`, and wait for the result.
3. Use the results section within the chat, and the difference highlighting within the sheet to understand how the generated code effected your data.
   * Modified dataframes, columns and column headers are colored <mark style="color:yellow;">yellow</mark>.&#x20;
   * Created dataframes and columns are colored <mark style="color:green;">green</mark>.
   * Deleted dataframes and columns are not colored, but are listed in the results section of the chat interface.
4. If the results are incorrect, press the `Undo` button in the Mito toolbar and try updating your command.&#x20;
5. If the results are correct, give Mito AI another command.

And remeber, every edit you make in Mito (including through Mito AI) generates code in the code cell directly below the Mito spreadsheet. Scroll down to see your new Python code.

<figure><img src="/files/ZglmfTmZIqNo0pPHvINc" alt=""><figcaption><p>Conversationally using Mito AI to edit data.</p></figcaption></figure>

{% hint style="info" %}
Mito AI is currently in open beta. As such, Mito collects additional usage data: including dataframe names, column names, and some values in the dataframe. By using Mito AI, you are agreeing to our [privacy policy](http://privacy.trymito.io) as well as OpenAI's [privacy policy](https://openai.com/policies/privacy-policy).&#x20;
{% endhint %}

## What tasks is Mito AI good for?

Mito AI excels at two types of tasks:

1. Edits to dataframes. This includes adding columns, removing columns, filtering, aggregating, merging, and any other edits that manipulate the underlying data.&#x20;
2. Answering questions about the data. This includes questions like "how many unique values are in column X" or "what is the highest value after this aggregation."

Mito AI does not currently handle formatting changes to the sheet, and may not perform correctly when generating graph code.&#x20;

## Auto Error Correction

When the code generated by Mito AI errors, **Mito feeds your original request, the code it generated, and the error back to OpenAI so that it can try again**. Often this will resolve simple errors. Things like: columns having different dtypes than the generated code orginally assumed or the generated code relying on a package that was not yet imported in the notebook.

If the Mito AI is not able to automatically resolve the error, try breaking your request into small chunks. For example, if you initially asked Mito AI to `Calculate the difference between the start and end times for each trip`, you might instead first tell Mito AI to `Convert the start and end time columns to datetimes`, then `Calculate the difference between the start and end time`. &#x20;

## Mito AI Plans

**Mito AI usage limits**

Mito AI uses the ChatGPT API in order to turn your commands into Python code. To make interacting with ChatGPT a seamless experience for our users, we automatically use our own OpenAI API key. And as a result, Mito incures a charge for each user prompt. Therefore, the following applies:

1. Open Source Mito AI users are allowed 100 free Open AI completions.
2. Mito [Pro](https://www.trymito.io/plans) and [Enterprise](https://www.trymito.io/plans) users are allowed unlimited Open AI completions.
3. All Mito users are able to provide their own OpenAI API key instead of using Mito's. This allows them to generate unlimited AI completions through the Mito interface.&#x20;

#### Providing Your Own OpenAI Key

All Mito users are able to provide their own OpenAI API key instead of using Mito's. This allows them to generate unlimited AI completions through the Mito interface. Simply add the following code above where you create Mito spreadsheet:

```
import os
os.environ['OPENAI_API_KEY'] = '<Key Here>'
```

#### On-Prem AI&#x20;

Some enterprises are uncomfortable sending any data to OpenAI and instead choose to build their own On-Prem AI. [Mito Enterprise](https://www.trymito.io/plans) users are able to configure Mito to connect to On-Prem LLMs instead of OpenAI, giving them unlimited AI completions and complete control over their data.&#x20;

Configuring Mito to use a different LLM is as simple as setting a couple of environment variables.&#x20;


# AI Alerts

Mitosheet can audit your data, and surface issues and fixes.

<figure><img src="/files/zu7PXRqJGQLb9TLfLabk" alt=""><figcaption></figcaption></figure>

Using the *AI Alerts* feature, Mitosheet will scan your data and look for issues and abnormalities. The *AI Alerts* button can be found in the upper right corner of the home ribbon.

Once activated the alerts panel will display issues found in the open dataset. You may choose to apply the suggested fix, or ignore the suggestion. &#x20;

&#x20;


# Suggested Columns

Get AI suggestions for new columns in your dataset.

<figure><img src="/files/qCLlvN5u6TOCRRdurVjJ" alt=""><figcaption></figcaption></figure>

Some of the most valuable insights aren’t in your data yet, they’re hidden in the relationships within it.

Mitosheet’s *Suggest Columns* feature acts like an intelligent assistant. It analyzes your data and proposes new columns that could unlock deeper insights, saving you from having to manually figure out what to create next.

The *Suggest* button can be found in the the *Home* ribbon.&#x20;


# Summary Statistics

This documentation will teach you how to access the summary statistics and frequency chart for any data column.

Mito's column summary statistics are a quick and easy way of understanding column data. By default, Mito displays a histogram of the frequency of values in the column along with the result of using the .describe pandas function.

To access Mito's Summary Statistics, open the **column control panel** by clicking on the **filter icon** in the column header, and then selecting the **Summary Statistics tab**.

<figure><img src="/files/IrlYEN5IXMd3e6yTOJFa" alt=""><figcaption><p>Click on the Filter Icon, and then the Stats tab.</p></figcaption></figure>


# Type Changes

This documentation explains how to change the data type of data and formula columns using Mito's type casting features.

Mito's point and click type changes make it easy to identify the data type of each column in your dataframe, and cast those columns to a different type.

#### Identifying Data Types

For each column in your dataframe, the datatype is displayed in the column header. The icon will help you distinguish between int, floats, strings, booleans, and dates/time deltas.

#### Changing Data Types

There are two ways to change the data type of columns inside Mito.

Firstly, you can use the **Dtpye** dropdown in the Mito toolbar:&#x20;

1. Select the columns you want to cast to a new dtype.
2. Click on the Dtype dropdown in the Mito toolbar and select a new dtype.

<figure><img src="/files/CU4xaQzULCi1Veelbqad" alt=""><figcaption><p>Changing a string column to a datetime.</p></figcaption></figure>

Secondly, you can use the typecasting spreadsheet formulas. To do so, add the VALUE, TEXT BOOL, or DATEVALUE function to your formula to convert your column to a number, string, boolean, or datetime respectively.

For example, to convert the result of an IF statement to a boolean, wrap the if statement in the BOOL function.

```
=BOOL(IF(A > 100, 1, 0))
```

The resulting column will have `true` for each row where A is greater than 100 and `false` for each row where A is less than or equal to 100.


# Spreadsheet Formulas

Write Excel-like spreadsheet formulas to edit your dataframes using Python.

### Why Spreadsheet Formulas&#x20;

The ability to write formulas to manipulate columns of data is a hallmark of any good spreadsheet tool. They allow you to create unique data transformations that are not easily captured in other point and click interfaces.&#x20;

### Mito Spreadsheet Formulas are different

Mito spreadsheet formulas work differently from Excel formulas in three keys ways:

1. Mito formulas can self-reference. For example, if you want to convert the column `Name` to Uppercase, you can write the formula `=UPPER(Name)` in the `Name` column itself. Not having to use helper columns helps you keep your dataframes clean.&#x20;
2. Mito formulas do not automatically refresh. If the data that a column formula references changes, simply resubmit the column in order to recalculate it on the most up to date data.&#x20;
3. By default, formulas apply to the entire column. If you enter a formula in a column, then it will autofill for all cells in that column.&#x20;

### Writing Spreadsheet Formulas

You can either write a spreadsheet formula in the formula bar or directly in the cells of the column you're looking to edit.

To write a spreadsheet formula in the formula bar:

1. Click on a cell in the column you want to set the formula of.
2. Double click on the formula bar to open it.&#x20;
3. Make sure that `Edit entire column` is set to `On`.
4. Write the formula and press `enter` to submit the formula.

You can also write a spreadsheet formula by double clicking on a cell in a specific column that you want to edit. The editing process is the same otherwise.

You can see a full list of the Mito Spreadsheet Formulas [here](/how-to/interacting-with-your-data/mito-spreadsheet-formulas). You can also learn how to add your own functions to the Mito spreadsheet [here](/how-to/interacting-with-your-data/bring-your-own-spreadsheet-functions).

![Writing a formula using the MONTH function from Excel.](/files/nxQCb1wdPJ5EcHi2kxnF)


# Custom Spreadsheet Functions

Create your own spreadsheet functions and share them with your entire organization.

{% hint style="info" %}
&#x20;This is a [Mito Enterprise](https://trymito.io/plans) feature. [Upgrade](https://www.trymito.io/plans) to extend your spreadsheet with additional spreadsheet functions.
{% endhint %}

The Mito spreadsheet is built to be extensible to your teams use case. Mito users or infrastructure administrators can the data analysis capabilities of their team by incorporating custom Python functions directly into the sheet.&#x20;

Bringing your own functions enables organizations to maintain their proprietary algorithms, calculations, and domain-specific knowledge right within Mito Spreadsheet. Stop your internal Python code from rotting on the shelf, and get it to end users in the most intuitive interface -- a spreadsheet.&#x20;

## How to Write Custom Spreadsheet Functions&#x20;

Let's say that we want to use a custom spreadsheet function called `ADD_ONE` that adds 1 to the input number.&#x20;

```python
def ADD_ONE(series):
    return series + 1
```

Custom spreadsheet functions must:

1. Have a fully capitalized function name
2. Support the correct input types

Optionally, spreadsheet functions can use a a docstring to configure spreadsheet syntax hints.

### Custom functions must be fully capitalized &#x20;

Custom spreadsheet functions are required to have fully upercase names.&#x20;

If you have `my_function` you wish to add, simply wrap it in a wrapper to use it in the Mitosheet.&#x20;

```python
def MY_FUNCTION(*args, **kwargs):
    return my_functions(*args, **kwargs)
```

### Custom functions must support the correct input types

When writing formulas in a Mito spreadsheet, there are a few ways to reference other pieces of data in the spreadsheet. Let's consider each reference type, and the data type you receive in return.

Imagine we're writing a formula on the dataframe `df`, and we write formulas in example formula. The passed type to the function will be:

| Reference Type                       | Example Formula         | Passed Type                      |
| ------------------------------------ | ----------------------- | -------------------------------- |
| Single cell reference, same row      | B1 = MY\_FORMULA(A1)    | df\['A']                         |
| Single cell reference, different row | B2 = MY\_FORMULA(A1)    | df\['A'].shift(1)                |
| Entire column reference              | C1 = MY\_FORMULA(A:B)   | df.loc\[:, 'A':'B']              |
| Range reference                      | B3 = MY\_FORMULA(A1:A2) | RollingRange(df\[\['A']], 2, -2) |

For the first two references types of single-cell references, the passed through type will be a `pd.Series`. For the entire column reference, a `pd.DataFrame` will be passed. Finially, the `RollingRange` is a Mito-specific object that has the following interface.&#x20;

#### Rolling Range Object

A rolling range is a helper object that is passed to sheet functions when the user references a range within the sheet. For example, consider how the following references transpile:

```python
- A0 = SUM(B0:B0) => SUM(RollingRange(df[['B']], 1, 0))
- A0 = SUM(B0:B1) => SUM(RollingRange(df[['B']], 2, 0))
- A1 = SUM(B0:B1) => SUM(RollingRange(df[['B']], 2, -1))
- A1 = SUM(B0:B2) => SUM(RollingRange(df[['B']], 3, -1))
```

To support range references in your custom functions, you can use the `RollingRange.apply` function, which has the following type:

```python
"""
Calls the passed func with each of the ranges defined all the way down
the series, and returns a series with the same index as the original
dataframe. 
"""
rolling_range.apply(
    func: Callable[[pd.DataFrame], Union[str, float, int, bool, datetime, timedelta]], 
    default_value: Union[str, float, int, bool, datetime, timedelta]=0
) -> pd.Series:
```

### Displaying syntax hints inside of Mito&#x20;

Displaying syntax support to the user inside of the Mito spreadsheet makes it easy for them to use your custom functions.&#x20;

If you want to add syntax support for your custom functions, you can do so by writing a docstring for your function that adheres to the following structure. Mito will automatically detect the docstring and convert it into useful syntax support.

```python
def ADD_ONE(series):    
    """
    {
        "function": "ADD_ONE",
        "description": "Returns the series with 1 added to each value.",
        "search_terms": ["my_function"],
        "examples": [
            "ADD_ONE(A)",
            "ADD_ONE(4)"
        ],
        "syntax": "ADD_ONE(value)",
        "syntax_elements": [{
                "element": "value",
                "description": "The number or series to add one to"
            }
        ]
    }
    """
    return series + 1
```

This will display the syntax support:

<figure><img src="/files/5wFOXwTRX875dWMt08V9" alt=""><figcaption></figcaption></figure>

## How to add spreadsheet functions to the Mitosheet

There are two ways to make the custom functions accessible in Mito:&#x20;

#### Passing the spreadsheet functions as a parameters&#x20;

In Jupyter, you can make spreadsheet functions accessible using the following code:

```python
mitosheet.sheet(sheet_functions=[MY_FUNCTION])
```

If you're using Streamlit, you can instead pass the spreadsheet functions as a paramter to the [spreadsheet component](/mito-for-streamlit/api-reference).&#x20;

#### Setting an environment variable

If your spreadsheet functions are importable from a .py file, you can set the following environment variables, to make those spreadsheet functions accessible in Mito.&#x20;

```
MITO_CONFIG_VERSION = '2'
MITO_CONFIG_CUSTOM_SHEET_FUNCTIONS_PATH = 'path/to/custom_sheet_functions.py'
```

## Examples of Sheet Functions

To see how sheet functions are implemented in practice, you can view example sheet functions here:

1. <https://github.com/mito-ds/monorepo/blob/0be44bedf7626baaa9eea6868ddb47c57d0a1d07/mitosheet/mitosheet/public/v3/sheet_functions/number_functions.py#L34>
2. <https://github.com/mito-ds/monorepo/blob/0be44bedf7626baaa9eea6868ddb47c57d0a1d07/mitosheet/mitosheet/public/v3/sheet_functions/string_functions.py#L86>


# Formula Reference

Mito supports 75+ of the most common Excel spreadsheet formulas, implemented in Python.

## Formula Reference

{% hint style="info" %}
Missing a formula, or what to add a formula of your own design? Check out [bring-your-own spreadsheet functions](/how-to/interacting-with-your-data/bring-your-own-spreadsheet-functions), which allow you to add additional functionality directly into the mitosheet.&#x20;
{% endhint %}

## ABS

Returns the absolute value of the passed number or series.

### Examples

* ABS(-1.3)
* ABS(A)

### Syntax

ABS(value)

#### Syntax Elements

* **value**: The value or series to take the absolute value of.

## AND

Returns True if all of the provided arguments are True, and False if any of the provided arguments are False.

### Examples

* AND(True, False)
* AND(Nums > 100, Nums < 200)
* AND(Pay > 10, Pay < 20, Status == 'active')

### Syntax

AND(boolean\_condition1, \[boolean\_condition2, ...])

#### Syntax Elements

* **boolean\_condition1**: An expression or series that returns True or False values. See IF documentation for a list of conditons.
* **boolean\_condition2 ... \[OPTIONAL]**: An expression or series that returns True or False values. See IF documentation for a list of conditons.

## AVG

Returns the numerical mean value of the passed numbers and series.

### Examples

* AVG(1, 2)
* AVG(A, B)
* AVG(A, 2)

### Syntax

AVG(value1, \[value2, ...])

#### Syntax Elements

* **value1**: The first number or series to consider when calculating the average.
* **value2, ... \[OPTIONAL]**: Additional numbers or series to consider when calculating the average.

## BOOL

Converts the passed arguments to boolean values, either True or False. For numberic values, 0 converts to False while all other values convert to True.

### Examples

* BOOL(Amount\_Payed)
* AND(BOOL(Amount\_Payed), Is\_Paying)

### Syntax

BOOL(series)

#### Syntax Elements

* **series**: An series to convert to boolean values, either True or False.

## CLEAN

Returns the text with the non-printable ASCII characters removed.

### Examples

* CLEAN(A)

### Syntax

CLEAN(string)

#### Syntax Elements

* **string**: The string or series whose non-printable characters are to be removed.

## CONCAT

Returns the passed strings and series appended together.

### Examples

* CONCAT('Bite', 'the bullet')
* CONCAT(A, B)

### Syntax

CONCAT(string1, \[string2, ...])

#### Syntax Elements

* **string1**: The first string or series.
* **string2, ... \[OPTIONAL]**: Additional strings or series to append in sequence.

## CORR

Computes the correlation between two series, excluding missing values.

### Examples

* \=CORR(A, B)
* \=CORR(B, A)

### Syntax

CORR(series\_one, series\_two)

#### Syntax Elements

* **series\_one**: The number series to convert to calculate the correlation.
* **series\_two**: The number series to convert to calculate the correlation.

## DATEVALUE

Converts a given string to a date series.

### Examples

* DATEVALUE(date\_column)
* DATEVALUE('2012-12-22')

### Syntax

DATEVALUE(date\_string)

#### Syntax Elements

* **date\_string**: The date string to turn into a date object.

## DAY

Returns the day of the month that a specific date falls on, as a number.

### Examples

* DAY(date\_column)
* DAY('2012-12-22')

### Syntax

DAY(date)

#### Syntax Elements

* **date**: The date or date series to get the day of.

## ENDOFBUSINESSMONTH

Given a date, returns the end of the buisness month. E.g. the last weekday.

### Examples

* ENDOFBUSINESSMONTH(date\_column)
* ENDOFBUSINESSMONTH('2012-12-22')

### Syntax

ENDOFBUSINESSMONTH(date)

#### Syntax Elements

* **date**: The date or date series to get the end of the business month of.

## ENDOFMONTH

Given a date, returns the end of the month, as a date. E.g. input of 12-22-1997 will return 12-31-1997.

### Examples

* ENDOFMONTH(date\_column)
* ENDOFMONTH('2012-12-22')

### Syntax

ENDOFMONTH(date)

#### Syntax Elements

* **date**: The date or date series to get the last day of the month of.

## EXP

Returns e, the base of the natural logarithm, raised to the power of passed series.

### Examples

* \=EXP(data)
* \=EXP(A)

### Syntax

EXP(series)

#### Syntax Elements

* **series**: The series to raise e to.

## FILLNAN

Replaces the NaN values in the series with the replacement value.

### Examples

* FILLNAN(A, 10)
* FILLNAN(A, 'replacement')

### Syntax

FILLNAN(series, replacement)

#### Syntax Elements

* **series**: The series to replace the NaN values in.
* **replacement**: A string, number, or date to replace the NaNs with.

## FIND

Returns the position at which a string is first found within text, case-sensitive. Returns 0 if not found.

### Examples

* FIND(A, 'Jack')
* FIND('Ben has a friend Jack', 'Jack')

### Syntax

FIND(text\_to\_search, search\_for)

#### Syntax Elements

* **text\_to\_search**: The text or series to search for the first occurrence of search\_for.
* **search\_for**: The string to look for within text\_to\_search.

## FLOAT

Converts a string series to a float series. Any values that fail to convert will return NaN.

### Examples

* \=FLOAT(Prices\_string)
* \=FLOAT('123.123')

### Syntax

FLOAT(string\_series)

#### Syntax Elements

* **string\_series**: The series or string to convert to a float.

## GETPREVIOUSVALUE

Returns the value from series that meets the condition.

### Examples

* GETPREVIOUSVALUE(Max\_Balances, Max\_Balances > 0)

### Syntax

GETPREVIOUSVALUE(series, condition)

#### Syntax Elements

* **series**: The series to get the previous value from.
* **condition**: When condition is True, a new previous value is set, and carried forward until the condition is True again.

## HOUR

Returns the hour component of a specific date, as a number.

### Examples

* HOUR(date\_column)
* HOUR('2012-12-22 09:45:00')

### Syntax

HOUR(date)

#### Syntax Elements

* **date**: The date or date series to get the hour of.

## IF

Returns one value if the condition is True. Returns the other value if the conditon is False.

### Examples

* IF(Status == 'success', 1, 0)
* IF(Nums > 100, 100, Nums)
* IF(AND(Grade >= .6, Status == 'active'), 'pass', 'fail')

### Syntax

IF(boolean\_condition, value\_if\_true, value\_if\_false)

#### Syntax Elements

* **boolean\_condition**: An expression or series that returns True or False values. Valid conditions for comparison include ==, !=, >, <, >=, <=.
* **value\_if\_true**: The value the function returns if condition is True.
* **value\_if\_false**: The value the function returns if condition is False.

## INT

Converts a string series to a int series. Any values that fail to convert will return 0.

### Examples

* \=INT(Prices\_string)
* \=INT('123')

### Syntax

INT(string\_series)

#### Syntax Elements

* **string\_series**: The series or string to convert to a int.

## KURT

Computes the unbiased kurtosis, a measure of tailedness, of a series, excluding missing values.

### Examples

* \=KURT(A)
* \=KURT(A \* B)

### Syntax

KURT(series)

#### Syntax Elements

* **series**: The series to calculate the unbiased kurtosis of.

## LEFT

Returns a substring from the beginning of a specified string.

### Examples

* LEFT(A, 2)
* LEFT('The first character!')

### Syntax

LEFT(string, \[number\_of\_characters])

#### Syntax Elements

* **string**: The string or series from which the left portion will be returned.
* **number\_of\_characters \[OPTIONAL, 1 by default]**: The number of characters to return from the start of string.

## LEN

Returns the length of a string.

### Examples

* LEN(A)
* LEN('This is 21 characters')

### Syntax

LEN(string)

#### Syntax Elements

* **string**: The string or series whose length will be returned.

## LOG

Calculates the logarithm of the passed series with an optional base.

### Examples

* LOG(e) = 1
* LOG(100, 10) = 2

### Syntax

LOG(series, \[base])

#### Syntax Elements

* **series**: The series to take the logarithm of.
* **base \[OPTIONAL]**: The base of the logarithm to use. Defaults to the natural logarithm if no base is passed.

## LOWER

Converts a given string to lowercase.

### Examples

* \=LOWER('ABC')
* \=LOWER(A)
* \=LOWER('Nate Rush')

### Syntax

LOWER(string)

#### Syntax Elements

* **string**: The string or series to convert to lowercase.

## MAX

Returns the maximum value among the passed arguments.

### Examples

* MAX(10, 11)
* MAX(Old\_Data, New\_Data)

### Syntax

MAX(value1, \[value2, ...])

#### Syntax Elements

* **value1**: The first number or column to consider for the maximum value.
* **value2, ... \[OPTIONAL]**: Additional numbers or columns to compute the maximum value from.

## MID

Returns a segment of a string.

### Examples

* MID(A, 2, 2)
* MID('Some middle characters!', 3, 4)

### Syntax

MID(string, starting\_at, extract\_length)

#### Syntax Elements

* **string**: The string or series to extract the segment from.
* **starting\_at**: The index from the left of string from which to begin extracting.
* **extract\_length**: The length of the segment to extract.

## MIN

Returns the minimum value among the passed arguments.

### Examples

* MIN(10, 11)
* MIN(Old\_Data, New\_Data)

### Syntax

MIN(value1, \[value2, ...])

#### Syntax Elements

* **value1**: The first number or column to consider for the minumum value.
* **value2, ... \[OPTIONAL]**: Additional numbers or columns to compute the minumum value from.

## MINUTE

Returns the minute component of a specific date, as a number.

### Examples

* MINUTE(date\_column)
* MINUTE('2012-12-22 09:45:00')

### Syntax

MINUTE(date)

#### Syntax Elements

* **date**: The date or date series to get the minute of.

## MONTH

Returns the month that a specific date falls in, as a number.

### Examples

* MONTH(date\_column)
* MONTH('2012-12-22')

### Syntax

MONTH(date)

#### Syntax Elements

* **date**: The date or date series to get the month of.

## MULTIPLY

Returns the product of two numbers.

### Examples

* MULTIPLY(2,3)
* MULTIPLY(A,3)

### Syntax

MULTIPLY(factor1, \[factor2, ...])

#### Syntax Elements

* **factor1**: The first number to multiply.
* **factor2, ... \[OPTIONAL]**: Additional numbers or series to multiply.

## OR

Returns True if any of the provided arguments are True, and False if all of the provided arguments are False.

### Examples

* OR(True, False)
* OR(Status == 'success', Status == 'pass', Status == 'passed')

### Syntax

OR(boolean\_condition1, \[boolean\_condition2, ...])

#### Syntax Elements

* **boolean\_condition1**: An expression or series that returns True or False values. See IF documentation for a list of conditons.
* **boolean\_condition2 ... \[OPTIONAL]**: An expression or series that returns True or False values. See IF documentation for a list of conditons.

## POWER

The POWER function can be used to raise a number to a given power.

### Examples

* POWER(4, 1/2)
* POWER(Dose, 2)

### Syntax

POWER(value, exponent)

#### Syntax Elements

* **value**: Number to raise to a power.
* **exponent**: The number to raise value to.

## PROPER

Capitalizes the first letter of each word in a specified string.

### Examples

* \=PROPER('nate nush')
* \=PROPER(A)

### Syntax

PROPER(string)

#### Syntax Elements

* **string**: The value or series to convert to convert to proper case.

## QUARTER

Returns the quarter (1-4) that a specific date falls in, as a number.

### Examples

* QUARTER(date\_column)
* QUARTER('2012-12-22')

### Syntax

QUARTER(date)

#### Syntax Elements

* **date**: The date or date series to get the quarter of.

## RIGHT

Returns a substring from the beginning of a specified string.

### Examples

* RIGHT(A, 2)
* RIGHT('The last character!')

### Syntax

RIGHT(string, \[number\_of\_characters])

#### Syntax Elements

* **string**: The string or series from which the right portion will be returned.
* **number\_of\_characters \[OPTIONAL, 1 by default]**: The number of characters to return from the end of string.

## ROUND

Rounds a number to a given number of decimals.

### Examples

* ROUND(1.3)
* ROUND(A, 2)

### Syntax

ROUND(value, \[decimals])

#### Syntax Elements

* **value**: The value or series to round.
* **decimals**: The number of decimals to round to. Default is 0.

## SECOND

Returns the seconds component of a specific date, as a number.

### Examples

* SECOND(date\_column)
* SECOND('2012-12-22 09:23:05')

### Syntax

SECOND(date)

#### Syntax Elements

* **date**: The date or date series to get the seconds of.

## SKEW

Computes the skew of a series, excluding missing values.

### Examples

* \=SKEW(A)
* \=SKEW(A \* B)

### Syntax

SKEW(series)

#### Syntax Elements

* **series**: The series to calculate the skew of.

## STARTOFBUSINESSMONTH

Given a date, returns the most recent start of the business month, as a state. E.g. the first weekday.

### Examples

* STARTOFBUSINESSMONTH(date\_column)
* STARTOFBUSINESSMONTH('2012-12-22 09:23:05')

### Syntax

STARTOFBUSINESSMONTH(date)

#### Syntax Elements

* **date**: The date or date series to get the most recent beginning of month business day of.

## STARTOFMONTH

Given a date, returns the start of the month, as a date. E.g. input of 12-22-1997 will return 12-1-1997.

### Examples

* STARTOFMONTH(date\_column)
* STARTOFMONTH('2012-12-22 09:23:05')

### Syntax

STARTOFMONTH(date)

#### Syntax Elements

* **date**: The date or date series to get the first day of the month of.

## STDEV

Computes the standard deviation of a series, excluding missing values.

### Examples

* \=STDEV(A)
* \=STDEV(A \* B)

### Syntax

STDEV(series)

#### Syntax Elements

* **series**: The series to calculate the standard deviation of.

## STRIPTIMETODAYS

Returns the date with a seconds, minutes, and hours component of 00:00:00.

### Examples

* STRIPTIMETODAYS(date\_column)
* STRIPTIMETODAYS('2012-12-22 09:23:05')

### Syntax

STRIPTIMETODAYS(date)

#### Syntax Elements

* **date**: The date or date series to reset the seconds, minutes, and hours component of.

## STRIPTIMETOHOURS

Returns the date with a seconds and minutes component of 00:00.

### Examples

* STRIPTIMETOHOURS(date\_column)
* STRIPTIMETOHOURS('2012-12-22 09:23:05')

### Syntax

STRIPTIMETOHOURS(date)

#### Syntax Elements

* **date**: The date or date series to reset the seconds and minutes component of.

## STRIPTIMETOMINUTES

Returns the date with a seconds component of 00.

### Examples

* STRIPTIMETOMINUTES(date\_column)
* STRIPTIMETOMINUTES('2012-12-22 09:23:05')

### Syntax

STRIPTIMETOMINUTES(date)

#### Syntax Elements

* **date**: The date or date series to reset the seconds component of.

## STRIPTIMETOMONTHS

Returns the date adjusted to the start of the month.

### Examples

* STRIPTIMETOMONTHS(date\_column)
* STRIPTIMETOMONTHS('2012-12-22 09:23:05')

### Syntax

STRIPTIMETOMONTHS(date)

#### Syntax Elements

* **date**: The date or date series to reset the seconds, minutes, hours, and days of.

## STRIPTIMETOYEARS

Returns the date adjusted to the start of the year.

### Examples

* STRIPTIMETOYEARS(date\_column)
* STRIPTIMETOYEARS('2012-12-22 09:23:05')

### Syntax

STRIPTIMETOYEARS(date)

#### Syntax Elements

* **date**: The date or date series to reset the seconds, minutes, hours, days, and month components of.

## SUBSTITUTE

Replaces existing text with new text in a string.

### Examples

* SUBSTITUTE('Better great than never', 'great', 'late')
* SUBSTITUTE(A, 'dog', 'cat')

### Syntax

SUBSTITUTE(text\_to\_search, search\_for, replace\_with, \[count])

#### Syntax Elements

* **text\_to\_search**: The text within which to search and replace.
* **search\_for**: The string to search for within text\_to\_search.
* **replace\_with**: The string that will replace search\_for.
* **count**: The number of times to perform the substitute. Default is all.

## SUM

Returns the sum of the given numbers and series.

### Examples

* SUM(10, 11)
* SUM(A, B, D, F)
* SUM(A, B, D, F)

### Syntax

SUM(value1, \[value2, ...])

#### Syntax Elements

* **value1**: The first number or column to add together.
* **value2, ... \[OPTIONAL]**: Additional numbers or columns to sum.

## TEXT

Turns the passed series into a string.

### Examples

* \=TEXT(Product\_Number)
* \=TEXT(Start\_Date)

### Syntax

TEXT(series)

#### Syntax Elements

* **series**: The series to convert to a string.

## TRIM

Returns a string with the leading and trailing whitespace removed.

### Examples

* \=TRIM(' ABC')
* \=TRIM(' ABC ')
* \=TRIM(A)

### Syntax

TRIM(string)

#### Syntax Elements

* **string**: The value or series to remove the leading and trailing whitespace from.

## TYPE

Returns the type of each element of the passed series. Return values are 'number', 'str', 'bool', 'datetime', 'object', or 'NaN'.

### Examples

* TYPE(Nums\_and\_Strings)
* IF(TYPE(Account\_Numbers) != 'NaN', Account\_Numbers, 0)

### Syntax

TYPE(series)

#### Syntax Elements

* **series**: The series to get the type of each element of.

## UPPER

Converts a given string to uppercase.

### Examples

* \=UPPER('abc')
* \=UPPER(A)
* \=UPPER('Nate Rush')

### Syntax

UPPER(string)

#### Syntax Elements

* **string**: The string or series to convert to uppercase.

## VALUE

Converts a string series to a number series. Any values that fail to convert will return an NaN.

### Examples

* \=VALUE(A)
* \=VALUE('123')

### Syntax

VALUE(string)

#### Syntax Elements

* **string**: The string or series to convert to a number.

## VAR

Computes the variance of a series, excluding missing values.

### Examples

* \=VAR(A)
* \=VAR(A - B)

### Syntax

VAR(series)

#### Syntax Elements

* **series**: The series to calculate the variance of.

## VLOOKUP

Looks up a value in a range and returns the value in the same row from a column you specify. Notably, this formula can be used to lookup values between different sheets.

### Examples

* VLOOKUP(Names0, Other\_Dataframe!Ids:Ages, 1)
* VLOOKUP('John Smith', Names:Ages, 2)
* VLOOKUP(Names0, Ids:Ages, Column Indexes0)

### Syntax

VLOOKUP(lookup\_value, where, index)

#### Syntax Elements

* **lookup\_value**: The value to look up.
* **where**: The range to look up in.
* **index**: The column index to return.

## WEEK

Returns the week (1-52) of a specific date, as a number.

### Examples

* WEEK(date\_column)
* WEEK('2012-12-22 09:23:05')

### Syntax

WEEK(date)

#### Syntax Elements

* **date**: The date or date series to get the week of.

## WEEKDAY

Returns the day of the week that a specific date falls on. 1-7 corresponds to Monday-Sunday.

### Examples

* WEEKDAY(date\_column)
* WEEKDAY('2012-12-22')

### Syntax

WEEKDAY(date)

#### Syntax Elements

* **date**: The date or date series to get the weekday of.

## YEAR

Returns the day of the year that a specific date falls in, as a number.

### Examples

* YEAR(date\_column)
* YEAR('2012-12-22')

### Syntax

YEAR(date)

#### Syntax Elements

* **date**: The date or date series to get the month of.

{% hint style="info" %}
Missing a formula? [Let us know](mailto:aarondr77@gmail.com?subject=Missing%20Functionality) if your workflow requires formulas that Mito does not yet support. We prioritize adding functionality for active Mito users!
{% endhint %}


# Using VLOOKUP

Joining dataframes using a Python VLOOKUP formula in Mito.

{% embed url="<https://drive.google.com/file/d/1msuZg5ZQRAhfLtDkZpF3fQUJTcvVk2D2/view?usp=share_link>" %}
A quick example of using VLOOKUP in Mito.
{% endembed %}

#### Instructions for Using VLOOKUP to join dataframes

1. Double click on the first cell in a column where you want to use a VLOOKUP
2. Click on the first cell of the lookup key, in the same dataframe that you are editing.
3. Switch to the dataframe you're looking up in
4. Click on the column header that is the key for your lookup in the new dataframe
5. Holding `Shift`, click on the column header of the value you want.&#x20;
6. Enter the index of that new column as the third argument.


# Editing Individual Cells

Edit your data with the ease of a spreadsheet.

### Editing Individual Cells

You can either edit a cell's value in the formula bar or directly in the cell:

1. Double click on the cell you want to edit it
2. Make sure that `Edit entire column` is set to `Off`.
3. Type the cell's new value and press `enter` to submit.


# Combining Dataframes

Join datasets together by selecting keys, concatenate dataframes on top of each other, or find unique values between datasets.

## Why combine dataframes

If you have mulitple dataframes, it can be useful to combine them into a single dataframe. This may be because they share a key, and you want to analyze the data together, or that the dataframes are each pieces of a larger dataset that were split up for performance reasons, or something else entirely. Mito has tools that make combining these dataframes together incredibly easy!

## Different ways to combine data:

{% hint style="info" %}
Looking to include use VLOOKUP like in Excel? In Mito, you can use the VLOOKUP formula just like Excel. See the formula documentation [here](/how-to/interacting-with-your-data/mito-spreadsheet-formulas#vlookup).&#x20;
{% endhint %}

Merge combines dataframes based on values in shared columns (like a VLOOKUP in Excel):

{% content-ref url="/pages/-MYIPtvCumDYNsdH5-vZ" %}
[Merge (horizontal)](/how-to/combining-dataframes/merging-datasets-together)
{% endcontent-ref %}

Concat is used to stack two dataframes on top of eachother:

{% content-ref url="/pages/UUUgKohLKTlWDonN3VrD" %}
[Concatenate (horizontal)](/how-to/combining-dataframes/concatenate-dataframes)
{% endcontent-ref %}

Dataframe difference calculates the difference between two dataframes:

{% content-ref url="/pages/Gojqxwy80WzankuE6716" %}
[Anti-merge (unique)](/how-to/combining-dataframes/anti-merge-unique)
{% endcontent-ref %}


# Merge (horizontal)

Join the columns of two dataframes together.

### Why Merge Datasets

Mito's merge functionality can be used to combine datasets together horizontally. Merge looks for matches between the key column of the first sheet and the key column of the second sheet.&#x20;

{% hint style="info" %}
Looking to combine datasets vertically by stacking rows on top of each other? You're looking to concatenate. Check out concatenate documentation [here.](/how-to/combining-dataframes/concatenate-dataframes)
{% endhint %}

{% hint style="info" %}
Looking to include use VLOOKUP like in Excel? Checkout the VLOOKUP formula documentation [here](https://docs.trymito.io/how-to/interacting-with-your-data/mito-spreadsheet-formulas#vlookup).&#x20;
{% endhint %}

### How to Merge Datasets

Open the Merge Taskpane through the `Home` tab by clicking `Merge > Merge (horizontal`. Then, configure the merge taskpane:

1. Select the Merge Type:
   1. **Left Merge**: Includes all rows from the first sheet and only matching rows from the second sheet. Includes all matches.
   2. **Right Merge**: Includes all rows from the second sheet and only matching rows from the first sheet. Includes all matches.
   3. **Inner Merge**: Only includes rows that have matches in both sheets.
   4. **Outer Merge**: Includes all rows from both sheets, regardless of if there is a match in the other sheet.
   5. **Lookup Merge**: Left join, but only includes the first match from the second sheet if there are multiple. Just like a Vlookup in Excel.
   6. **Unique in Left:** Includes each row from the first sheet that doesn't have a match in the second sheet.
   7. **Unique in Right:** Includes each row from second sheet that doesn't have a match in the first sheet.
2. Set the merge keys. These are the keys that must match for the rows to be merged. You can create as many merge keys as you want.
3. Then, optionally choose which columns from each dataset you want to keep in the final merge dataframe.

<figure><img src="/files/jRJRDXphDWe7zjPS1jPb" alt=""><figcaption><p>Opening and configuring a dataframe merge.</p></figcaption></figure>


# Concatenate (horizontal)

Concatenating dataframes allows you to combine two or more dataframes by stacking their rows on top of each other.

Concatenating dataframes allows you to combine two or more dataframes by stacking the rows on top of eachother. To concatenate multiple dataframes together into a new dataframe, in the `Home` tab, click the `Merge` dropdown and then select `Concat`

<figure><img src="/files/jdxYng8L53fXSO5Lbx0f" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Are you looking to combine two dataframes side by side using a shared key? You're looking to merge these datasets. Check out our documentation on merging datasets [here.](/how-to/combining-dataframes/merging-datasets-together)
{% endhint %}

Then, choose the **Join Type** you'd like to use in your concatenate. There are two different types of joins possible when concatenating dataframes:

* **Inner:** Only includes columns that have matches in all sheets.
* **Outer**: Includes all columns from all sheets, regardless of if there is a match in the other sheets. Fills non-matching rows with NaN values automatically.

Next, you have the option to ignore or keep the original indexes in the original dataframes. By default, Mito will reset the indexes in your newly merged dataframe.

Finially, set the dataframes you want to concatenate into a single new dataframe. Mito will automatically create a new sheet that represents this concatenate.


# Anti-merge (unique)

Find records unique to one dataframe.

## How to find the difference between datasets

Mito's dataframe difference functionality lets you find unique records across two different dataframes.  You can access this functionality on the `Home` tab, by select the `Merge` dropdown and then selecting `Anti Merge`.

<figure><img src="/files/Hd5hXQG1jdlHJm9zZgz9" alt=""><figcaption><p>Finding unique rows between multiple datasets.</p></figcaption></figure>

* **Unique in Left:** Includes each row from the first sheet that doesn't have a match in the second sheet.
* **Unique in Right:** Includes each row from the second sheet that doesn't have a match in the first sheet.

Just like the other types of merges, Mito uses the merge key that you select for each sheet to detect matches.


# Sort Data

This documentation will teach you how to sort data columns in Mito.

To sort your dataset, click on the **filter icon** in the column header to open the **column control panel**, then select either **Ascending** or **Descending** to sort the column in that order.

<figure><img src="/files/Oshoa6EWw00uuIUMxB83" alt=""><figcaption><p>Sorting a column Ascending.</p></figcaption></figure>


# Split Text to Columns

Split a column into multiple based on a delimiter.

### Why Split Text to Columns

Splitting text to columns takes the text in one column and splits it into multiple columns based on a delimiter. It is especially useful when one cell contains multiple pieces of information that you would like to operate on separately.&#x20;

### How to Split Text to Columns

To Split Text to Columns:

1. Select the `Data` tab in the toolbar.&#x20;
2. Click `Text to Columns` button to open the taskpane.&#x20;
3. Select the dataframe that contains the column you want to split.
4. Select the column you want to split.
5. Select the delimiters that you want to use as breakpoints within each cell.&#x20;
6. Use the `Columns Preview` to make sure that the delimiter configuration is correct.
7. Click the `Split on delimiter` button.

![A Mito sheet with the Split Text to Columns Taskpane open.](/files/L4XWW0UMjZelMwaFnPxe)


# Deleting Columns

Remove entire columns from your dataframe just using your keyboard.

Mito supports deleting columns one at a time, or multiple at once! Just select the columns you want to delete and then press the **delete key** on your keyboard or the **delete column** button in the Mito toolbar. To select multiple columns at once:

If you're using Windows:

* `shift + click` to select every column in between your previous selected column and the column you clicked on.
* `control + click` to add the column you just clicked on to your selection.

If you're using Mac:

* `shift + click` to select every column in between your previous selected column and the column you clicked on.
* `cmd + click` to add the column you just clicked on to your selection.


# Deleting Rows

Remove entire rows from your dataframe just using your keyboard.

### Why Delete Rows

Sometimes, when importing a new dataset into Mito, your dataset contains rows that don't fit the format of the rest of the data. In these cases, deleting the offending rows will allow you to continue through the rest of your analysis without encountering other errors!

If you're looking to delete rows that meet certain conditions like `greater than` for numbers, or `contains` a specific string, check out our documentation on:

{% content-ref url="/pages/-MYIS4utYDEqE2OjQTBa" %}
[Filter](/how-to/filter-data)
{% endcontent-ref %}

### How to Delete Rows

Deleting specific rows is very simple.

1. Select the rows you would like to delete. Make sure to click on the index of the row to select the entire row.
2. Click the Delete key on your keyboard.

![Click on the row before pressing delete.](/files/vtZ3UHAXpYUE2Y9nW0US)

You can also delete rows by right clicking on them, and then selecting Delete Rows.&#x20;

### Multiple rows with the same index

Pandas identifies rows by the value in the index, and it is perfectly legal to have two rows with the same index. If you delete a row with an index of **10**, and another row has index **10** as well, then both of these rows will be deleted.

If you do not want to delete both rows, we reccomend taking this dataframe outside Mito and updating the indexes of these rows to be different.


# Column Headers

Column headers identify the specific column within your dataframe. Mito provides a variety of tools for working with column headers directly.

{% content-ref url="/pages/vZOBGb4U6HUg10qojdOU" %}
[Editing Column Headers](/how-to/column-headers/editing-column-headers)
{% endcontent-ref %}

{% content-ref url="/pages/6LD8wAtnGTYqBbmS2Zpl" %}
[Promote Row to Header](/how-to/column-headers/promote-row-to-header)
{% endcontent-ref %}


# Editing Column Headers

Rename your column headers with the ease of a spreadsheet.

## How to edit a column header

1. Double click on the column header you want to edit.
2. Enter the new name of the column header.
3. Press enter.
4. Your column should now be renamed in your dataset.

![An example column header being edited.](/files/ap36kE9c0mY13hABUgQG)


# Promote Row to Header

Select a row of your dataframe to become the new column headers.

## How to Promote a Row to header

To promote a specific row to become the header row:

1. Right click on the index of the row.
2. Click **Promote Row to Header.**

![](/files/pt9AFhRuPnVZUz6UZYRd)


# Deduplicate

Deduplicate repeated entries from your dataframe.

Mito's deduplication feature is a sneakily powerful tool for removing unwanted data. Let's look at how it works, and then look at an example of why its so powerful.

To use the deduplicate feature:

1. Select the `Data` tab in the toolbar.
2. Click on the `Remove Duplicates` button.
3. Select which record of the duplicated data you want to keep: `first`, `last` or `none`
4. Configure which columns to use for looking for duplicated data. **Two rows are considered duplicates of eachother if they have the same value in all of the columns that you select in the Columns to Deduplicate On section.**

<figure><img src="/files/O403enSDcSgr4vGETfrz" alt=""><figcaption></figcaption></figure>

## Example: Using deduplicate and sort together

Deduplicate becomes really powerful when we combine it with [sorting](/how-to/sort-data). In this example, we will use sorting and deduplicating to find the highest scoring NBA player on each team.

The dataset that we're looking at has 3 columns:

* Player -- the name of the player
* Tm -- the team the player is on
* PTS - the average number of points the player has scored in the 2021-2022 NBA basketball season

Our strategy for figuring out the highest scoring player on each team is to sort the data in ascending order of points scored, and then use the dedupe feature to keep only one player from each team, making sure that we keep the last entry of each duplicated row.

#### Sorting the data

The first step is to sort the PTS column in ascending order. To do so, double click on the filter icon in the PTS column header and click the `ascending` sort button in the taskpane.

Sorting the data is a crucial part of this analysis because it ensures that the highest scoring player of each team will be further down in the dataset than any other player on their team.

<figure><img src="/files/KByoznagT0i181z9Lay6" alt=""><figcaption></figcaption></figure>

#### Select the columns used for finding duplicated values

Since we're trying to find the highest scoring player on each team, our answer should only have one player on each team. So we're going to use the toggles to only look for duplicated values in the Tm column.

![Configure which columns to deduplicate on](/files/wf2ZPoL2TTF4sq8FKDzH)

#### Keep the last instance of duplicated data

Let's bring it all together. So far, we've sorted our data in ascending order so that the highest scoring player on each team is at the bottom, and we've told Mito to only look for duplicates in the Tm column. So all that is left to do is tell Mito that when you find duplicates in the Tm column, keep the last instance of the duplicated row.

Since the highest scoring player is always going to be lower down in the data set than any other player on his team, this removal technique will always leave us with the highest scoring player on each team.

![Configure which duplicated entries to keep](/files/INGheptiHB3LrvMMMLjA)

#### Checkout the results!

A quick sanity check tells us that our analysis is correct!

![The highest scoring player on each NBA team](/files/EySKsKl3HTR7KTrBHE30)


# Fill NaN Values

NaN values are one of the most common sources of errors. Use Mito's Fill NaN values taskpane to choose how you handle your missing values.

### Why fill NaN values

NaN stands for **N**ot **A** **N**umber, and is often how missing data is represented with in a dataframe. Dealing with NaN values within your analysis can effect your results in unwanted ways, and as such Mito provides an interface for filling these missing values with appropriate substitutes.

NaN values stand in for missing numbers, but there are also NaT values for **N**ot **A** **T**imestamp for datetime and timedelta columns. Mito will allow you to replace these values as well.

### How to fill NaN values

To fill NaN values:

1. Select the `Data` tab.
2. Click `Fill NaN Values` to open the taskpane.
3. Select the dataframe you wish to fill nan values within.
4. Select the columns you want to fill NaN values within.
5. Configure the `Fill Method` to fill NaN values as you wish.
6. Click the `Fill NaN` button to fill NaN values in these columns.

<figure><img src="/files/jkIrkk2k5lVTYNvbCTVH" alt=""><figcaption><p>Opening the Fill missing values taskpane.</p></figcaption></figure>

#### Different Fill Methods

Depending on your analysis, you may want to fill nan values different. Mito provides a few options for filling NaN values in your dataset.

1. `Values`: Replaces NaN values with a specific value that you input. An input appears and allows you to input a string, number, boolean, or datetime.
2. `Forward Fill`: Replaces NaN values with the value from the same column in the row before in the dataframe.&#x20;
3. `Back Fill`: Replaces NaN values with the value from the same column in the row after in the dataframe.&#x20;
4. `Column Mean`: Replaces NaN values in the column with the mean values from that column. Note that this can only be applied to number, datetime, and timedelta columns. String and boolean columns have no valid defintion of a "mean" value.
5. `Column Median`: Replaces NaN values in the column with the median values from that column. Note that this can only be applied to number, datetime, and timedelta columns. String and boolean columns have no valid defintion of a "median" value.


# Transpose

Convert your columns into rows, and rows into columns.

### Why transpose

Transposing data turns a dataframe's columns into rows, and rows into columns. Usually pandas dataframes are organized such that each row represents a record, transaction, object, etc., and each column represents a different attribute of those records. When your data is organized in the opposite orientation, using transpose is a helpful step in preparing your data.&#x20;

### How to transpose your data

To transpose a dataframe:

1. Select the dataframe that you want to transpose.
2. Select the `Insert` tab.
3. Click `Transpose`.&#x20;

The transpose operation creates a new dataframe in your Mito spreadsheet. It is named the name of the transposed dataframe appended with `_transposed`.

<figure><img src="/files/R3wXTbXSe5hrsImcq1W0" alt=""><figcaption></figcaption></figure>


# Reset Index

Reset your dataframe's Index after sorting, filtering, or importing your data to cleanup your workspace.

### Why reset a dataframes index

By default, dataframes are indexed from `0...n-1`. This means that every row in the dataframe is uniquely identified by an index number.&#x20;

In Mito, much like in Excel, when you filter or sort your dataframe, you rows can get our of order, and so the indexes displayed on the side might not be in order as well. We preserve these indexes until you manually decide to reset them (which might make your formulas easier to parse, etc).&#x20;

### How to Reset a Dataframes Index

1. Right click on the index, and click either `Reset and Drop Index` or `Reset Index`.&#x20;
   1. `Reset and Drop Index` will reset the index to `0...n-1`.
   2. `Reset and Drop Index` will reset the index to `0...n-1`, and adds the index to the dataframe.


# Unpivot a Dataframe (Melt)

Convert a dataframe from wide format to long format.

### Why Unpivot

Unpivoting is useful when you have a dataset in a wide format that you are looking to convert to a long format. Practically, this means that you have columns where you want to maintain their values, but turn them into rows. This is known as a `melt` in Pandas.

For example, imagine you have a dataset with a `product id` column, as well as one column per month for a fiscal year: `Jan`, `Feb`, etc. The first row in the `Jan` column contains the quantity of the first product sold in `Jan`, the second row contains the quantity of the second product sold in `Jan`, etc.

Unpivoting this dataset would allow you to create a dataframe with three columns: one for the product id, one for the month, and one for the number of that product id sold in that month. This, dataset would make it easier for you to filter down to a specific product and compare the quantity sold across months.

### How to Unpivot

Access the Unpivot Taskpane by selecting the  `Insert` tab and then selecting the `Unpivot` button.

1. Select the dataframe to Unpivot.&#x20;
2. Select the `ID Variables`. These columns will be present in the unpivoted dataframe. In our example, you would select the `product_id` column.
3. Select the `Values`. Each column header will go in the variables column, and the column values will go in the values column. In our example, you would select all the month columns.

<figure><img src="/files/XEXGdMg0g4BADbcmCghQ" alt=""><figcaption><p>Opening the Unpivot taskpane.</p></figcaption></figure>


# Formatting

Format your dataframe to generate presentation-ready Excel files.

Mito supports a variety of formatting options, which all allow you to change the display of your data in the mitosheet and within your notebook. See our formatting options below.

## Formatting Options

{% content-ref url="/pages/3WCxxdSHZxSAhUMiCuCj" %}
[Column Formatting](/how-to/formatting/column-formatting)
{% endcontent-ref %}

{% content-ref url="/pages/isI7Xa6pqwe2N21sJFTK" %}
[Dataframe Colors](/how-to/formatting/dataframe-colors)
{% endcontent-ref %}

{% content-ref url="/pages/ZsTGDTClYLe3RN8Qp1CF" %}
[Conditional Formatting](/how-to/formatting/conditional-formatting)
{% endcontent-ref %}


# Column Formatting

Format numbers as currency, percentage, accounting, scientific notation or more.

Mito lets you change the format of numeric columns. This only changes the displayed values in the columns, and does not edit the underlying data.

### Changing the Formatting of Number Columns <a href="#changing-the-formatting-of-a-column-s" id="changing-the-formatting-of-a-column-s"></a>

To change the format of number columns:

1. Select the columns you want to change the format of.&#x20;
2. Select the **Number** dropdown from the toolbar.
3. Select the format you want to change to:
   1. `Default`: Separate every three numbers with commas. It displays integers with no decimal places (1,234), and floats with one decimal place (1,234.5).
   2. `Plain Text`: Don't use commas to separate numbers and display all of the decimal places that exist in the raw data (1234.5678).
   3. `Currency`: Display numbers using a $. For example, -5000 is displayed as -$5,000.00).
   4. `Accounting`: Display numbers using a $ and use parentheses to identify negative numbers. For example, -5000 is displayed as ($5,000.00).
   5. `Percentage`: Display the number as a percentage.
   6. `Scientific Notation`: Display numbers in scientific notation. For example, 9,000,000,000 will be displayed as 9.00e+9.
4. If you want to change the number of decimals displayed in the column, click the **Less** and **More** buttons in the toolbar.

<figure><img src="/files/9Y1w562falVEer6SgaaQ" alt=""><figcaption><p>Select the number formatting from the dropdown</p></figcaption></figure>

<figure><img src="/files/9Oatz71rSDRXkTrUuT7M" alt=""><figcaption><p>Change the number of decimals displayed</p></figcaption></figure>

#### Using the Column Control Panel <a href="#using-the-column-control-panel" id="using-the-column-control-panel"></a>

You can also change a columns format by opening the column control panel:

1. Clicking on the type icon in the column header.
2. Use the **Format** select to pick the formatting to apply to the column.


# Dataframe Colors

Changing the color and style of the dataframe within Mito.

{% hint style="info" %} <img src="/files/4VOWezxnwO2wM4J3bVdr" alt="" data-size="line"> This is a [Mito Pro](https://www.trymito.io/plans) feature. [Upgrade](https://www.trymito.io/plans) to make your dataframes presentation ready. <img src="/files/4VOWezxnwO2wM4J3bVdr" alt="" data-size="line">&#x20;
{% endhint %}

Setting dataframe colors allows you to change the colors of the displayed dataframes headers and rows. Dataframe formatting is the easiest way to make your dataframes presentable to colleages, for example if you are copying them into an email or slide deck.

### Setting a Dataframe Format

1. Click **Format** and then **Set dataframe colors.**
2. In the **Color Dataframe** taskpane that opens, select a **Suggested Style** to change the color of your dataframe.
3. You can also manually configure the **Column Headers, Rows,** or **Dataframe Border** by expanding these sections.

<figure><img src="/files/mOIYJgn4PWhFKLs6kSpu" alt=""><figcaption></figcaption></figure>

### The Generated Styling Code

When you style your dataframe, Mito will generate code that styles this dataframe in your notebook. This code will look something like this:

```python
# Formatted dataframes. Print these styling objects to see the formatted dataframe
forestfires_styler = forestfires.style\
    .set_table_styles([
        {'selector': 'thead', 'props': [('color', '#FFFFFF'), ('background-color', '#8F1B15')]},
        {'selector': 'tbody tr:nth-child(odd)', 'props': [('color', '#494650'), ('background-color', '#F0DADA')]},
        {'selector': 'tbody tr:nth-child(even)', 'props': [('color', '#494650')]},
])
```

To view your formatted dataframe in your notebook, simply display the forestfires\_styler object. You can then copy this formatted dataframe anywhere you please.&#x20;

<figure><img src="/files/p9E0tb8BRrsGCHsadwSG" alt=""><figcaption></figcaption></figure>


# Conditional Formatting

Explore or highlight your data by changing the format of specific cells.

{% hint style="info" %} <img src="/files/4VOWezxnwO2wM4J3bVdr" alt="" data-size="line"> This is a [Mito Pro](https://www.trymito.io/plans) feature. [Upgrade](https://www.trymito.io/plans) to highlight important data with ease. <img src="/files/4VOWezxnwO2wM4J3bVdr" alt="" data-size="line">&#x20;
{% endhint %}

Conditional formatting makes it easy to highlight certain values or make particular cells easy to identify. It changes the appearance of a cell based on a condition. You can use conditional formatting to highlight cells that contain values which meet a certain condition.

### Adding Conditional Formats

1. Open the **Home** tab of the toolbar.
2. Click **Conditional Formatting** in the toolbar.
3. Click **Add Conditional Formatting Rule.**&#x20;
4. Click on the newly added rule to configure it:
   1. Select the **Columns** to apply the conditional format within.
   2. Select the filter condition **Where** the conditional format should apply.
   3. Set the **Text Color** and **Background Color** to apply to the cells identified by this condition.

<figure><img src="/files/ApHhC1jYJztYhwvOFT7N" alt=""><figcaption><p>A conditional format being applied to the column X to highlight values over 7.</p></figcaption></figure>

#### Adding Multiple Conditional Formats

Conditional formatting rules will be applied in-order, with later conditional formatting rules overwriting earlier ones. For example:

1. First conditional format sets cells >= 7 to have a red background color.
2. Second conditional format sets cells >= 8 to have a blue background color.

All cells equal to 7 will have a red background. All cells >= 8 will have a blue background color, as this rule is later, and so will overwrite the first conditional format.

#### Invalid Conditional Formatting Rules

Not all conditions can be applied to all columns. For example, if you are adding a conditional format to a number column, but you use the **string starts with** condition to select cells, this will error.

If the conditional formatting rule cannot be applied, it will display an error message prompting you to update the filter condition.&#x20;

### The Generated Styling Code

To view the dataframe with conditional formats in your notebook, simply display the styling object generated by Mito:

<figure><img src="/files/Yhbqhbw7KUKyCpMspYkt" alt=""><figcaption><p>The styling code generated by Mito, plus a line of code that displays the styled object.</p></figcaption></figure>


# Exporting Data

This documentation explains how to get data out of Mito.

Mito makes it easy to export your data to a large variety of places. Explore our documentation below to export data wherever is useful.

## Downloading Files

If you want to download an immediate snapshot of a dataframe from within Mito, see our instructions for exporting&#x20;

{% content-ref url="/pages/Ebgofc6Lv5zgDzMAUK78" %}
[Download as CSV](/how-to/exporting-to-csv-and-excel/download-as-csv)
{% endcontent-ref %}

{% content-ref url="/pages/yZEYqEf9BUUP8Wjwmss8" %}
[Download as Excel](/how-to/exporting-to-csv-and-excel/download-as-excel)
{% endcontent-ref %}

## Generating Export Code

If you want to generate a repeatible script that exports a dataframe, then you might be looking to generate export code.

{% content-ref url="/pages/BhxC5Ib4ivvUzEzXK45i" %}
[Generate code to create Excel and CSV reports](/how-to/exporting-to-csv-and-excel/generate-code-to-create-excel-and-csv-reports)
{% endcontent-ref %}

If you are looking to export a graph, see our[ Graph Export documentation.](/how-to/graphing/graph-export)


# Download as CSV

Export a single dataframe to a CSV file.

Exporting to csv is the fastest way to download large datasets from Mito. It only supports exporting one sheet at a time. To export a file to a CSV, simply:

1. Open the `Home` tab of the Mito toolbar.
2. Click the `Export` button and select `Download File Now`.
3. Set the `Export Type` to `csv`.
4. Select the dataframe you want to export.
5. Click the `Export` button at the bottom of the toolbar.
6. This CSV will appear in your Downloads folder.

<figure><img src="/files/GqUhV4eTMj2PTFo9qqOP" alt=""><figcaption></figcaption></figure>


# Download as Excel

Export dataframes to an Excel file.

Exporting dataframes to an Excel file allows you to export multiple dataframes at once. To export dataframes to an Excel file.

1. Open the `Home` tab of the Mito toolbar.
2. Click the `Export` button in the Mito toolbar, and select `Download File`.
3. Set the `Export Type` to Excel.
4. Select the dataframes you want to export. You can include multiple.
5. Click the `Download` button at the bottom of the toolbar.
6. This Excel file will appear in your Downloads folder.

<figure><img src="/files/Wegu5EIW4PqtiIJRz2kQ" alt=""><figcaption></figcaption></figure>

### Export with Formatting <img src="/files/Ol9PftUljU8Gw31n8i3w" alt="" data-size="line">

With [Mito Pro](https://www.trymito.io/plans), you can preserve the formatting of your data in your Excel exports. Exporting with formatting allows you to create presentation-ready Excel reports all through Mito and Python.

Before exporting an Excel file, you can set background and text colors using the [Set Dataframe Format](/how-to/formatting) taskpane, and this will be included in the exported Excel file.

*​*


# Generate code to create Excel and CSV reports

Generate an Excel or CSV file each time you run your code.

### Why generate export code

Sometimes, you don't want to just download a snapshot of the current dataframe within Mito - you want to create code that takes one of these dataframes and saves it to a CSV or Excel file. This can be particularly useful if you're automating a full analysis within Mito.

### How to generate export code

1. Open the `Home` tab in the Mito toolbar.
2. Click the `Export` dropdown then select `Download File When Running Code`.
3. Change the `File Name` to the name of the file to save.&#x20;
4. Select the export format, either `CSV` or `Excel` files.
5. Select the dataframes you want to include in the export.&#x20;
   1. Note that if you select multiple dataframes when exporting as a CSV, Mito will automatically create distinct files for each.
6. Click the `Generate Export Code` button.&#x20;
   1. This saves the exported file to disk, and also generates code that will export a file with the same configuration as well.

<figure><img src="/files/9vOoyuCxy9mp9lEeLKZ6" alt=""><figcaption></figcaption></figure>


# Using the Generated Code

Use Mito generated code to complete your analysis or automate your reports.

Each time you transform your data in the Mito spreadsheet, Mito generates the equivalent pandas code in the Jupyter Cell directly below the Mito spreadsheet. The code is production-ready, commented, pandas code that you can use however you wish.

## Use the altered dataframes in your analysis

Because Mito generates pandas code for each edit you make in the Mito spreadsheet, its easy to use the altered dataframes in the rest of your analysis. Mito doesn't lock you in to completing your entire analysis in Mito -- it encourages you to utilize the rest of the powerful Python data analytics ecosystem.

To use the altered dataframes in the rest of your analysis, run the code that Mito generates by clickingon the cell containing the code and press the play button in the Jupyter toolbar (or use the keyboard shortcut `shift + Enter`)

Once you've ran the generated code, you can use the altered dataframes in your analysis as you normally would, just by using the dataframe names.

If you see this error, its probably because you forgot to run the Mito generated code!

![Undefined Variable Error](/files/Bxd5SZ5SaUV3iIoaySSv)

## Automate an Analysis

Once you've created a Python script, its easy to reuse that script on a new data set, so long as the new data set has a similar structure to original data set you used to create the script.

Having a similar structure means:

* The dataframe names are the same in the original data set and the new data
* Any column that your script uses has the same column header and dtype in the original and new data set.

*Note: there are some other use case specific reasons that a script might not be reusable. For example, if you've hardcoded filters that aren't relevant to the new dataset.*

If your data sets meet those requirements, then you're good to go! All you need to do is change the dataframe import statements, and rerun the script.


# Turn generated code into functions

Convert the Mito generated code into a Python function to make it even easier to reuse.

## Why convert the Mito generated code to a function

Functions make it easy to reuse the code you generated over and over again. In particular, they make it easy to apply the same code to multiple data sets.&#x20;

[Functions in Python are similiar to formulas in Excel](https://blog.trymito.io/functions/).&#x20;

## How to convert Mito generated code to a function

If you're a Mito Enterprise user, you can have Mito automatically generate code as Python functions.&#x20;

1. Open the `Code` tab in the toolbar.
2. Click on `Configure Code`
3. In the taskpane, toggle `Generate Function` on
4. Give the function a name&#x20;

<figure><img src="/files/mVAMcGR0MNCaAb9bRLMI" alt=""><figcaption></figcaption></figure>

The Mito generated code will automatically update to generate a function. As you continue to edit the Mito spreadsheet, the function will update.

<figure><img src="/files/ixICtQl6B8qFiAZVZNRI" alt=""><figcaption></figcaption></figure>


# Changing Imported Data

Rerun your Mito analysis on new data to refresh a report.

After creating an analysis in Mito when you import some data and edit, you may want to run this analysis on a new dataset.  For example, you created some pivot tables to analyze stock returns during the month of March on the CSV `march_returns.txt`. Now, you'd like to create the same pivot tables with the CSV `april_returns.txt`.

Mito makes applying your edits to new data extremly easy.&#x20;

### How to change imported data

1. Click the **Dataframes** dropdown in the toolbar, and click **Change imported data**.
2. In the taskpane that opens, for any import you want to change, click on the right arrow, and replace this data with&#x20;
3. Click **Change Imports**.

A success message will appear, and the analysis will now be applied to the updated datasets.

<figure><img src="/files/3Yn0tXiIAqyF3szZnPBe" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
If you are changing your imported data from one dataset to another, make sure that these two datasets have the same data structure. \
\
For example, if `march_returns.txt` contains a column `Open Price` that you delete in your analysis, then the `april_returns.txt` dataset must also contain this column. If it does not contain this column,&#x20;
{% endhint %}


# Code Snippets

This documentation will teach you how to use code snippets and import your own

## Why Code Snippets

Code snippets are Python code that help you do any number of things -- often things that don't easily fit into a spreadsheet. For example, programatically sending an email!&#x20;

## Using Code Snippets&#x20;

To use code snippets in Mito.

1. Open the `Code` tab in the taskpane.&#x20;
2. Click `Code Snippets` to open the taskpane.&#x20;
3. Click on the code snippet you want to use and either select `Copy Code Snippet` to copy the code snippet to your clipboard or `Write to Notebook` to automatically create a new code cell below the Mito generated code that contains the code snippet.&#x20;

<figure><img src="/files/XUNIuHIUmeV9uzXkJPXp" alt=""><figcaption><p>The code snippets taskpane</p></figcaption></figure>

## Custom Code Snippets ![](/files/zzFFlU2lZiJ9o8wTCaEt)&#x20;

Mito Enterprise users and admins can import their own code snippets into Mito, making them available to all Mito users at their organizaiton. For more information on how to import your own code snippets, reach out to the Mito team at: <founders@sagacollab.com>. &#x20;


# Custom Editors: Autogenerate UI from Any Function

Extend Mito with custom dataframe transformations, like proprietary algorithms, calculations, and domain-specific knowledge.

{% hint style="info" %}
&#x20;This is a [Mito Enterprise](https://trymito.io/plans) feature. [Upgrade](https://www.trymito.io/plans) to extend your spreadsheet with additional  functionality.
{% endhint %}

The Mito spreadsheet is built to be extensible for your team's use case. Mito users or infrastructure administrators can extend Mito with custom dataframe editing capabilities, like proprietary algorithms, calculations, and domain-specific knowledge.

Stop your internal Python code from rotting on the shelf, and get it to end users in the most intuitive interface -- a spreadsheet.&#x20;

## How to Write Custom Editor&#x20;

Adding custom editing functionality to the Mito spreadsheet is very simple:

1. Define a Python function that takes a `pd.DataFrame` and returns a `pd.DataFrame`.&#x20;
2. Pass this function to the `editors` parameter when creating the Mito sheet.
3. Use the `Custom Edits` dropdown in the Mito sheet to access this functionality - with an auto-generated UI!

### Example: Calculating Moving Average&#x20;

Imagine we're a financial institution that has implemented the following Python function, and we want to expose it to our users:

```python
import pandas as pd

def calculate_moving_average(df, column_to_average, window_size, exponential=False):
    """
    Calculate moving average for a given financial time series data.
    """
    if exponential:
        df['EMA'] = df[column_to_average].ewm(span=window_size, adjust=False).mean()
    else:
        df['SMA'] = df[column_to_average].rolling(window=window_size).mean()
    return df
```

#### Step 1: Add types to the function

First, we must add types to the parameters of the function. This ensures that Mito can correctly generate a UI for each of these parameters. In this case, we type this function in the following way:

```python
import pandas as pd
from mitosheet.extensions.v1 import ColumnHeader

def calculate_moving_average(df: pd.DataFrame, column_to_average: ColumnHeader, window_size: int, exponential: bool=False):
   """
    Calculate moving average for a given financial time series data.
    """
    if exponential:
        df['EMA'] = df[column_to_average].ewm(span=window_size, adjust=False).mean()
    else:
        df['SMA'] = df[column_to_average].rolling(window=window_size).mean()
    return df
```

#### Step 2: Pass this function to the `editors` parameter

Then, pass this function to the `editors` parameter.&#x20;

{% tabs %}
{% tab title="Jupyter" %}
Pass this custom editor with:

```python
mitosheet.sheet(editors=[calculate_moving_average])
```

{% endtab %}

{% tab title="Streamlit" %}
Pass this custom editor with:

```python
spreadsheet(editors=[calculate_moving_average])
```

{% endtab %}

{% tab title="Dash" %}
Pass this custom editor with:

```python
Spreadsheet(editors=[calculate_moving_average])
```

{% endtab %}
{% endtabs %}

#### Step 3: Pass some good testing data to the Mito sheet

Pass the following data to the Mito spreadsheet, so that we can test our new custom editor:

```python
import pandas as pd

data = {'Date': ['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05'],
        'Price': [100, 102, 105, 101, 98]}
df1 = pd.DataFrame(data)
```

#### Step 4: Access the functionality in Mito with the `Custom Edits` dropdown

In the toolbar, a `Custom Edits` tab option will appear, with the Calculate Moving Average function beneath it:

<figure><img src="/files/5cnfxQW6k56B3eKQ3zWI" alt=""><figcaption></figcaption></figure>

Selecting this option will open a taskpane that allows you to configure this function, and calculate the moving average!

<figure><img src="/files/m1fhljlld0biAjFRtG8a" alt=""><figcaption></figcaption></figure>

## Supported Types

To see all the valid parameter types, check out the [Supported Types](/how-to/custom-editors-autogenerate-ui-from-any-function#supported-types) section of the custom importers page.


# Find and Replace

The quickest way to check if values exist in your data, and substitute them with others.

## Search

The search bar can be used to quickly jump to a column header or cell, or just to see how many matches there are in your sheet.&#x20;

The search bar can be opened by pressing `command+F`, or clicking the `Search` button in the toolbar.&#x20;

<figure><img src="/files/CLdQ8LbaAeEL4cpaMqAW" alt=""><figcaption><p>Search for values in the Mito spreadsheet</p></figcaption></figure>

## Replace

To replace the search value in the open sheet, expand the search bar by clicking on the arrow button to the left of the search bar.&#x20;

You can choose to replace the value in the entire sheet, or just in the selected columns. To select specific columns, click on the column header of that column.

<figure><img src="/files/5gI1ESHCJ07KLxUmAN8z" alt=""><figcaption><p>Using Find and Replace to replace values in Mito</p></figcaption></figure>


# Bulk column header edits

Transform all of the column headers in your dataframe with just one click of a button.

## Why bulk column header edits

Sometimes you need to make the same edit to all of your column headers. If you have many columns, it take a lot of time to update each column header one at a time. For example, after constructing a pivot table, you might want to remove the aggregation type from the column header. Bulk column header edits let you update all of your column headers at once.&#x20;

## How to bulk update column headers

1. Open the `Data` tab.
2. Click `Rename Columns`.
3. Use the taskpane to convert the column headers to uppercase/lowercase, or find and replace text the column headers.&#x20;

<figure><img src="/files/V9km6tLVgJX83R81whGl" alt=""><figcaption></figcaption></figure>


# Code Options

Customize your Mito generated code by converting it to a function, selecting parameters and more.

## Configuring Code Options

Adding code options allows you to configure the code to be generated in a way that works for your specific use-case. This includes options for generating the code as a function, and for including the imports from your code when adding custom python code.&#x20;

| Parameter                   | Type                                                                   | Description                                                                                    |
| --------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `as_function`               | `bool`                                                                 | If `True`,  Mito generates a function. If `False`, Mito generates a script.                    |
| `function_name`             | `str`                                                                  | The name of the function Mito generates.                                                       |
| `call_function`             | `bool`                                                                 | If `True` the Mito generated code's last line will call the generated function.                |
| `function_params`           | `Union[Dict[ParamName, ParamValue], ParamSubtype, List[ParamSubtype]]` | A mapping from function parameter name to the original value used in the script.               |
| `import_custom_python_code` | `bool`                                                                 | If `True`, the Mito generated function will import custom importers and spreadsheet functions. |

For example, if you want to generate a function named "my\_function" that receives one input called `file_path`, you could use the following code options:

```python
{
    'as_function': True, 
    'call_function': True, 
    'function_name': 'my_function', 
    'function_params': {'file_path': "original_data.csv"},
    'import_custom_python_code': False, 
}
```


# Scheduling your Automation

Create fully automated processes by scheduling your Python script to run on GitHub

## Motivation

After you've used Mito to write Python code, you may want to schedule this code to execute on a repeated basis. Mito makes it incredibly easy to **schedule a Python automation**, automatically handling:

1. **Automatic version control/documentation:** Mito will place your automation and initial data files under version control, making sure that you never loose your work. Moreover, auto-generated documentation means your team can easily understand your automations.
2. **Avoid breaking dependency updates:** Mito will automatically detect what dependencies you're using, and freeze them for your automation. This makes sure future package changes don't break your code without your knowledge!
3. **Avoid complex scheduling interfaces:** Visually tell Mito the cadence to run your automation and let Mito handle generating cron job syntax, timezones, ensuring runners are available, and making sure all you need to do is download the result.&#x20;

## Where does my automation run?

Currently, Mito supports Github Actions as it's primary automation location. Mito will automatically open automation PRs against your selected repository.&#x20;

## How to schedule an automation:

#### Step 1: Create an Automations repository and configure it in Mito

1. Create a new Github repo. You can find instructions [here](https://docs.github.com/en/get-started/quickstart/create-a-repo).
2. Set the new Github Repo as the automation repository for Mito, using environmental variables.&#x20;

```python
import os
os.environ['MITO_CONFIG_GITHUB_AUTOMATION_REPO'] = 'mito-ds/mito-automations-test'
```

#### Step 2: Create a personal access token, and add it to your environment

1. Create a Github Token, following the [instructions here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). It will look something like `"ghp_thisisarandomstringoflettersandnumbers"`
2. Set the Github Token as an environmental variable wherever you are running Mito.

```python
import os
os.environ["GITHUB_TOKEN"] = "ghp_thisisarandomstringoflettersandnumbers"
```

#### Step 3: Use the Schedule Automation interface in the `Code` tab

1. Select `Code > Schedule Automation`
2. Give the automation a descriptive `Automation Name` and `Automation Description`. The Automation Name will become the GitHub PR title and the Automation Description will be the PR description.
3. Configure the `Automation Schedule`.
4. Click `Schedule on Github`. Mito will create a new PR with the required input files, Python code, and GitHub action workflow. In a few moments the PR will be ready for review.&#x20;

<figure><img src="/files/KFNKsjoTV5dnAZMFLpus" alt=""><figcaption><p>Use Mito to schedule automations on GitHub</p></figcaption></figure>

#### Step 4: Review and merge this PR

1. Review the code of this PR, making any necessary changes or updates
2. Merge this PR into the main branch to schedule the automation.

#### Step 5: Get the results of future automation runs

1. Go to the Github repo configured in Step 1.&#x20;
2. Go to the `Actions` tab and select the action for this automation.
3. Click on the most recent run for this automation.
4. Scroll down, and download the `results` artifact. This will contain the results of the automation. If there is no `results` artifact, this is likely because you did not export any files in your generated code.&#x20;


# Keyboard Shortcuts

Speed up your Mito workflow with keyboard shortcuts!

<table><thead><tr><th>Action</th><th width="280">Keyboard Shortcut (Mac)</th><th>Keyboard Shortcut (Windows)</th></tr></thead><tbody><tr><td>Copy</td><td>⌘+C</td><td>Ctrl+C</td></tr><tr><td>Paste</td><td>⌘+V</td><td>Ctrl+V</td></tr><tr><td>Find</td><td>⌘+F</td><td>Ctrl+F</td></tr><tr><td>Find and Replace</td><td>Ctrl+Shift+F</td><td>Ctrl+Shift+H</td></tr><tr><td>Undo</td><td>⌘+Z</td><td>Ctrl+Z</td></tr><tr><td>Redo</td><td>⌘+Y</td><td>Ctrl+Y</td></tr><tr><td>Select Columns</td><td>Ctrl+Space</td><td>Ctrl+Space</td></tr><tr><td>Select Rows</td><td>Shift+Space</td><td>Shift+Space</td></tr><tr><td>Select All</td><td>⌘+A</td><td>Ctrl+A</td></tr><tr><td>Open Previous Sheet</td><td>Option + LeftArrow</td><td>Alt + LeftArrow</td></tr><tr><td>Open Next Sheet</td><td>Option + RightArrow</td><td>Alt + RightArrow</td></tr><tr><td>Create a Graph</td><td>Ctrl+G</td><td>Alt + F1</td></tr><tr><td>Open File Import Taskpane</td><td>⌘+O</td><td>Ctrl+O</td></tr><tr><td>Add a Filter</td><td>Option+DownArrow</td><td>Alt +DownArrow</td></tr><tr><td>Merge</td><td>⌘+M</td><td>Ctrl+M</td></tr><tr><td>Pivot</td><td>Ctrl+Shift+L</td><td>Alt+F11</td></tr><tr><td>Set Number Format</td><td><ul><li>Ctrl+Shift+~ : Plain Text</li><li>Ctrl+Shift+1 : Number (Two Decimal Places)</li><li>Ctrl+Shift+2 : DateTime</li><li>Ctrl+Shift+3 : DateTime</li><li>Ctrl+Shift+4 : Currency</li><li>Ctrl+Shift+5 : Percentage</li><li>Ctrl+Shift+6 : Scientific Notation</li></ul></td><td><ul><li>Ctrl+Shift+~ : Plain Text</li><li>Ctrl+Shift+1 : Number (Two Decimal Places)</li><li>Ctrl+Shift+2 : DateTime</li><li>Ctrl+Shift+3 : DateTime</li><li>Ctrl+Shift+4 : Currency</li><li>Ctrl+Shift+5 : Percentage</li><li>Ctrl+Shift+6 : Scientific Notation</li></ul></td></tr></tbody></table>

{% hint style="info" %}
Note: Due to browser contraints, some shortcuts don't work in Safari.&#x20;
{% endhint %}


# Upgrading Mito

We move quick. Upgrade to get the latest and greatest.

{% hint style="warning" %}
Want help? Join our [Discord](https://discord.gg/XdJSZyejJU) or [Slack](https://join.slack.com/t/trymito/shared_invite/zt-1h6t163v7-xLPudO7pjQNKccXz7h7GSg) for immediate support.
{% endhint %}

First, open the terminal and virtual enviornment where Mito is installed.

```
pip install --upgrade mitosheet mito-ai
```

After running the above commands, **restart your JupyterLab kernel and refresh your browser** to load the new version of Mito. This is required for the new Mito functionality to render.


# Enterprise Logging

Connect Mito to your internal logging servers so you can track Python retention at your firm.

{% hint style="info" %}
Collecting Mito Enterprise Logs requires a [Mito Enterprise License](https://www.trymito.io/plans).&#x20;
{% endhint %}

## Why is Mito Enterprise Logging Useful?

Python adoption is often a black box at large enterprises. You might know who has access to Python or even how often they log in to a Python environment like JupyterHub, but you probably don't know for which users their Python code is delivering business value.&#x20;

Mito Enterprise Logging is designed to help you gain visibility into Python retention at your firm. The logs are designed to help you calculate metrics like:

* Monthly Active Users of Mito
* The top 100 most active Mito power users at your firm
* The teams that have not yet adopted Python and require additional support&#x20;
* The most commonly used Mito features at your firm
* The top 10 most common errors that users were blocked by

Metrics like these open the black box of Python adoption at your firm and make it easy to evaluate and communicate the success of Python automations.

## Collecting Mito Enterprise Logs

{% hint style="info" %}
Collecting Mito Enterprise Logs requires a [Mito Enterprise License](https://www.trymito.io/plans).&#x20;
{% endhint %}

### Setting up your log server

Mito is agnostic to the logging infrastructure that you use. Common log monitoring platforms include [Datadog](https://www.datadoghq.com/dg/logs/log-monitoring/), [Mixpanel](https://mixpanel.com/analysis/), and [Amplitude](https://amplitude.com/amplitude-analytics).

To get the most out of the logs that Mito generates, it may be useful to supplement the logs Mito generates with additional information about each user. For example: `username`, `operating system`, `browser`, `environment`, etc. &#x20;

### Connecting Mito to your log server

To collect logs, you must set the following environment variables in your user's Python environment:&#x20;

```python
MITO_CONFIG_VERSION='2'
MITO_CONFIG_LOG_SERVER_URL='https://url/of/log/server'
MITO_CONFIG_LOG_SERVER_BATCH_INTERVAL='<number of seconds between log uploads>'
```

Once configured, Mito will upload logs to the server:

1. In a batched manner. This reduces the burden on your log server.&#x20;
2. The logs will upload at fixed time intervals, specified by MITO\_CONFIG\_LOG\_SERVER\_BATCH\_INTERVAL. If no batch interval is provided, logs will be uploaded every 10 seconds by default.
3. From a separate thread than the main Mito processing thread. This ensures that log collection has a minimal effect on your users' experience.
4. If log upload fails:
   1. No logs will be lost. Logs will be saved and tried again on the next upload attempt.
   2. An exponential backoff strategy is used, so upload will be retried with double the batch interval. This exponential backoff strategy avoids overburdening the server.

Together, the above mean that logs may sometimes be dropped, especially if the Python process Mito is running in is terminated unexpectedly.&#x20;

## Logs Generated by Mito Enterprise

### Mito Usage Events

<table><thead><tr><th width="263">Log Event</th><th>Description</th></tr></thead><tbody><tr><td>mitosheet_rendered</td><td>A new or existing Mito spreadsheet was created</td></tr></tbody></table>

### Mito Analysis Events

#### Data Import and Export Events

<table><thead><tr><th width="262">Log Event </th><th>Description</th></tr></thead><tbody><tr><td>excel_import_edit</td><td>At least one sheet from an Excel workbook was imported</td></tr><tr><td>excel_range_import_edit</td><td>A range from an Excel worksheet was imported using either dynamic or static range detection </td></tr><tr><td>simple_import_edit</td><td>A CSV file was imported</td></tr><tr><td>dataframe_import_edit</td><td>A dataframe that was defined in the Jupyter notebook was imported using the Import Dataframe Taskpane</td></tr><tr><td>export_to_file_edit</td><td>Data in Mito was exported to a CSV or Excel file</td></tr></tbody></table>

#### Data Transformation Events

<table><thead><tr><th width="260">Log Event</th><th>Description</th></tr></thead><tbody><tr><td>pivot_edit</td><td>A pivot table was created or updated</td></tr><tr><td>filter_column_edit</td><td>A column filter was applied or updated</td></tr><tr><td>sort_edit</td><td>The dataframe was sorted by a column</td></tr><tr><td>change_column_dtype_edit</td><td>A column's data type was changed</td></tr><tr><td>merge_edit</td><td>Two dataframes were merged together or an existing merge was updated</td></tr><tr><td>concat_edit</td><td>Dataframes were vertically concatonated on top of eachother to creatre a new dataframe</td></tr><tr><td>delete_column_edit</td><td>A column(s) were deleted</td></tr><tr><td>rename_column_edit</td><td>A column was renamed</td></tr><tr><td>add_column_edit</td><td>A column was added to the dataframe</td></tr><tr><td>set_column_formula_edit</td><td>A formula was created or updated</td></tr><tr><td>reorder_column_edit</td><td>A column's order in the dataframe was changed</td></tr><tr><td>fill_na_edit</td><td>NaN values were filled using the FillNaN Taskpane</td></tr><tr><td>delete_row_edit</td><td>A row(s) were deleted</td></tr><tr><td>drop_duplicates_edit</td><td>Duplicate values were removed from the dataframe using the Drop Duplicates Taskpane</td></tr><tr><td>split_text_to_columns_edit</td><td>A column was split on a delimiter into multiple columns using the Split Text to Columns Taskpane</td></tr><tr><td>promote_row_to_header_edit</td><td>A row was promoted to the header row</td></tr><tr><td>melt_edit</td><td>A dataframe was melted (unpivoted)</td></tr><tr><td>reset_index_edit</td><td>The dataframe's indexes were reset to the standard 0, 1, ... N</td></tr><tr><td>transpose_edit</td><td>A dataframe was transposed</td></tr><tr><td>dataframe_delete_edit</td><td>A dataframe was deleted</td></tr><tr><td>dataframe_duplicate_edit</td><td>A dataframes was duplicated</td></tr><tr><td>dataframe_rename_edit</td><td>A dataframe was renamed</td></tr></tbody></table>

#### Formatting Events

<table><thead><tr><th width="329">Log Event</th><th>Description</th></tr></thead><tbody><tr><td>change_column_format_edit</td><td>A column had its format changed. Ie: From plain text to accounting format</td></tr><tr><td>set_dataframe_format_edit</td><td>A conditional formatting or dataframe color scheme was updated.</td></tr></tbody></table>

#### Graphing Events

<table><thead><tr><th width="330">Log Event</th><th>Description</th></tr></thead><tbody><tr><td>graph_edit</td><td>A graph was created or an existing graph had it's configuration updated. For example, a bar chart was changed to a line chart.</td></tr><tr><td>graph_delete_edit</td><td>A graph was deleted</td></tr><tr><td>graph_rename_edit</td><td>A graph was renamed </td></tr></tbody></table>

### Errors

<table><thead><tr><th width="333">Log Event</th><th>Description</th></tr></thead><tbody><tr><td>error</td><td>All errors in Mito generate an <code>error</code> log event that contains useful information like the error traceback needed to identify and correct a bug.<br><br>Use the log param <code>params_failed_log_event</code>  to identify which event caused the error.<br><br>For easy triaging, errors are tagged with an <code>error_severity_code.</code> </td></tr><tr><td>frontend_render_failed</td><td>The Mito Spreadsheet has completely crashed. This is the most severe error. </td></tr></tbody></table>

## Error Severity Codes

| Error Category               | Error Severity Code |
| ---------------------------- | ------------------- |
| Likely just a warning        | 0                   |
| Likely user error            | 10                  |
| Likely inconsequential error | 11                  |
| Likely Mito Bug              | 20                  |
| Unable to import Data        | 21                  |
| Unable to replay analysis    | 22                  |
| Mito Crashed                 | 50                  |
| Misc. (unexpected errors)    | -1                  |

## Example Logs

To help you understand the logs that Mito generates, below is a video of a short Mito session accompanied with the logs generated by that session. In this session the user:

1. Renders a Mito spreadsheet
2. Adds a column to the end of the dataframe
3. Renames the new column to `New Column`
4. Writes a spreadsheet formula, `=LEFT(Last Name0, 2)` to get the first two letters from the Last Name column
5. Generates an error by attempting to create a duplicate column header

{% embed url="<https://youtu.be/vjz6hs7P1G0>" %}

```json
[
    {
        "event": "mitosheet_rendered",
        "params_user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15", 
        "version_python": "3.9.6", 
        "version_pandas": "2.1.2", 
        "version_mito": "0.3.131", 
        "timestamp_gmt": "2024-01-25T23:07:59Z"
    }, 
    {
        "event": "add_column_edit",
        "params_sheet_index": 0, 
        "params_column_header": "childworldfall", 
        "params_column_header_index": 5, 
        "params_public_interface_version": 3, 
        "version_python": "3.9.6", 
        "version_pandas": "2.1.2", 
        "version_mito": "0.3.131", 
        "timestamp_gmt": "2024-01-25T23:08:03Z" 
    }, 
    {
        "event": "rename_column_edit",
        "params_sheet_index": 0, 
        "params_column_id": "childworldfall", 
        "params_new_column_header": "personpersonhat", 
        "params_public_interface_version": 3, 
        "version_python": "3.9.6", 
        "version_pandas": "2.1.2", 
        "version_mito": "0.3.131", 
        "timestamp_gmt": "2024-01-25T23:08:07Z", 
    }, 
    {
        "event": "set_column_formula_edit",
        "params_sheet_index": 0, 
        "params_column_id": "childworldfall", 
        "params_formula_label": "workfallpoint", 
        "params_new_formula": "=LEFT(companypartcaseI[workfallpoint], 2)", 
        "params_index_labels_formula_is_applied_to": {"type": "timepartcase"}, 
        "params_cell_editor_location": "cell", 
        "params_public_interface_version": 3, 
        "version_python": "3.9.6", 
        "version_pandas": "2.1.2", 
        "version_mito": "0.3.131", 
        "timestamp_gmt": "2024-01-25T23:08:14Z"
    }, 
    {
        "event": "error"
        "error_severity_code": "10",
        "params_failed_log_event": "rename_column_edit_failed",
        "params_sheet_index": 0, 
        "params_column_id": "womancasepoint", 
        "params_new_column_header": "timedogcase", 
        "params_public_interface_version": 3, 
        "error_traceback": [
            "Traceback (most recent call last):", "  File 'mito_backend.py', line 253, in receive_message", 
            "    self.handle_edit_event(event)", 
            "    File 'mito_backend.py', line 178, in handle_edit_event", 
            "    self.steps_manager.handle_edit_event(event)", 
            "    File 'steps_manager.py', line 523, in handle_edit_event", 
            "    self.execute_and_update_steps(new_steps)", 
            "    File 'steps_manager.py', line 745, in execute_and_update_steps", 
            "    final_steps = execute_step_list_from_index(", "  File 'steps_manager.py', line 101, in execute_step_list_from_index", 
            "    new_step.set_prev_state_and_execute(last_valid_step.final_defined_state, non_skipped_steps)", 
            "    File 'step.py', line 154, in set_prev_state_and_execute", 
            "    post_state_and_execution_data = self.step_performer.execute(new_prev_state, params)", 
            "    File 'rename_column.py', line 42, in execute", 
            "    raise make_column_exists_error(new_column_header)", 
            "    mitosheet.errors.MitoError: (column_exists_error, Column Already Exists, Sorry, a column already exists with the name application sign date. Try picking a different name!)"
        ], 
        "error_traceback_last_line": "mitosheet.errors.MitoError: (column_exists_error, Column Already Exists, Sorry, a column already exists with the name application sign date. Try picking a different name!\)", 
        "version_python": "3.9.6", 
        "version_pandas": "2.1.2", 
        "version_mito": "0.3.131", 
        "timestamp_gmt": "2024-01-25T23:08:20Z", 
    }
]
```

## Debugging your logging configuration

If Mito is unable to upload logs, it will generate useful errors.&#x20;

To see the logs in JupyterLab, click on `View` > `Show Log Console` , and inside of the log console, change the Log Level from `Warning` to `Debug`. &#x20;

For example, with the following invalid enterprise logging configuration, you should see the following error messages:

```python
import os 
os.environ['MITO_CONFIG_VERSION'] = '2'
os.environ['MITO_CONFIG_LOG_SERVER_URL'] = 'https://invalid-url'
```

<figure><img src="/files/vVs8tf1G6tJFYnnCLOB7" alt=""><figcaption></figcaption></figure>


# Getting Started with Mito for Streamlit

Add a fully featured spreadsheet to your Streamlit app with just 2 lines of code.

## Overview of Mito for Streamlit

[Streamlit](https://www.streamlit.io/) is an open-source Python library that makes it easy to create and share beautiful, custom web apps for machine learning and data science. In just a few minutes you can build and deploy powerful data apps.

Mito for Streamlit allows Streamlit application developers to add a spreadsheet directly into their Streamlit application. In turn, their users can use Mito to:

1. Import, clean, and transform datasets into a format required by the rest of the Streamlit app.
2. Do flexible data exploration and analysis.
3. Create Python scripts using Mito's code-gen capabilities.

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Install Mito for Streamlit</strong></td><td>Get started by installing the <code>mitosheet</code> package for Streamlit.</td><td></td><td><a href="/pages/maA1rxkIIxGhgzSiVNQU">/pages/maA1rxkIIxGhgzSiVNQU</a></td></tr><tr><td><strong>API Reference</strong></td><td>Learn about how to Mito's Streamlit APIs, including examples and features.</td><td></td><td><a href="/pages/YAUVypkgwq6tAbo8bd74">/pages/YAUVypkgwq6tAbo8bd74</a></td></tr><tr><td><strong>App gallery</strong></td><td>Try out awesome Streamlit applications that include the Mito spreadsheet.</td><td></td><td><a href="/pages/8yNpOA1Qa483ArzCfxY8">/pages/8yNpOA1Qa483ArzCfxY8</a></td></tr></tbody></table>


# Streamlit Overview

Turns data scripts into shareable web apps in minutes. All in pure Python. No front‑end experience required.

## Streamlit: The Basics

[Streamlit](https://www.streamlit.io/) is an open-source Python library that makes it easy to create and share beautiful, custom web apps for machine learning and data science. In just a few minutes you can build and deploy powerful data apps.&#x20;

In practice, a Streamlit application is just a `.py` file where you add a few Streamlit commands and then you run it with `streamlit run`:

```
streamlit run your_script.py [-- script args]
```

As soon as you run the script as shown above, a local Streamlit server will spin up and your app will open in a new tab in your default web browser. This app is your canvas, where you'll draw charts, text, widgets, tables, and more. This `.py` file is all you need to build a fully-featured web-app!

What gets drawn in the app is up to you. For example [`st.text`](https://docs.streamlit.io/library/api-reference/text/st.text) writes raw text to your Streamlit app, and [`st.line_chart`](https://docs.streamlit.io/library/api-reference/charts/st.line_chart) draws a line chart. Refer to Streamlit's [API documentation](https://docs.streamlit.io/library/api-reference) to see all commands that are available to you.

## Core Concepts in Streamlit

New to writing Streamlit applications and looking to understand more? Check out the Streamlit docs to learn more [core concepts](https://docs.streamlit.io/library/get-started/main-concepts).&#x20;


# Create a Mito for Streamlit App

A Quickstart guide to creating your first Streamlit app with the Mito Spreadsheet.

{% hint style="info" %}
Make sure you've installed [Mito for Streamlit](/getting-started/installing-mito/installing-mito-for-streamlit) before continuing.
{% endhint %}

The easiest way to create your first Streamlit application with Mito is to try things yourself. Streamlit has an awesome developer story, so for each edit you make to your code, you can just refresh the page and see your new changes.

In this guide, we're going to use Mito for Streamlit to create an interactive app that allows users to explore Tesla stock data. We'll do some basic data cleaning, and then perform an analysis that computes the traded volume in the most recent month.&#x20;

{% hint style="info" %}
To see the finished script, [scroll down](#putting-it-all-together).
{% endhint %}

## Create your first app

1. First, create a new Python script. Let's call it `stock_data.py`
2. Open `stock_data.py` in your favorite IDE or text editor, then add these lines:

   ```python
   import streamlit as st
   from mitosheet.streamlit.v1 import spreadsheet
   ```
3. Let's make the page wide, and set a title:

   ```python
   st.set_page_config(layout="wide")
   st.title('Tesla Stock Volume Analysis')
   ```
4. Now, run your Streamlit app from the command line:

   ```bash
   streamlit run stock_data.py
   ```
5. The Streamlit app should open in a new tab in your web-browser. Check out that awesome title!

### Add a Mitosheet

1. Now, let's use the Mito spreadsheet to display&#x20;

   ```python
   CSV_URL = 'https://raw.githubusercontent.com/plotly/datasets/master/tesla-stock-price.csv'
   new_dfs, code = spreadsheet(CSV_URL)
   ```
2. You'll see a few buttons in the upper-right corner of your app asking if you'd like to rerun the app. Choose **Always rerun**, and you'll see your changes automatically each time you save the `stock_data.py` file.
3. When your app refreshes, you will see the Mito spreadsheet with Tesla stock data. Scroll around like you would in any other spreadsheet!
4. The return value of the `spreadsheet` is each of the tabs of the spreadsheet, as well as the code that corresponds to the edits you make in the spreadsheet. Let's display both:

   ```python
   st.write(new_dfs)
   st.code(code)
   ```

### Use the Mitosheet to Clean the Dataset

1. Take a closer look at this dataset. It looks like the first row has an invalid date. Let's remove it from our analysis by **right clicking on the row label 0** and then clicking **Delete Rows.**
2. Turn the `Date` column into a datetime. Click the **Filter** icon next to the `Date` header, and in the taskpane that opens, use the **Dtype** dropdown to select **datetime.**
3. Pause here and check out the dataframes displayed below the Mitosheet. Note that each&#x20;
4. Turn the `Volume` column into a float. Click the **Filter** icon next to the `Volume` header, and in the taskpane that opens, use the **Dtype** dropdown to select **float.**

### Use the Mitosheet to Create a Pivot Table

We're now ready to use more of Mito's advanced functionality. Let's create a pivot table that allows us to understand how the traded volume has changed over time.&#x20;

1. Click the **Pivot** button in the Mito toolbar.&#x20;
2. Add `Date` to the **Rows** section. Group date by **year-month**, so we can understand volume changes on a monthly lee.&#x20;
3. Add `Volume` to the **Values** section. Select an aggregation type of **sum**.
   1. If you cannot select **sum** for `Volume`, you may have forgotten to change `Volume` to a **float.** See step 4 in the section above.
4. This pivot table now displayes the total of traded volume per month. If you scroll below, you will see that this pivot table is returned from the Mito spreadsheet, and the code to generate this pivot table is returned as well.

See the rest of our documentation to see what other functionality is available in Mito, or continue to our [App Gallery](/mito-for-streamlit/streamlit-app-gallery) to get ideas for how to use Mito in your Streamlit applications.

## Putting it all together

That's it, you made your first app with Mito for Streamlit. Here's our finished script:

```python
import streamlit as st
from mitosheet.streamlit.v1 import spreadsheet

st.set_page_config(layout="wide")
st.title('Tesla Stock Volume Analysis')

CSV_URL = 'https://raw.githubusercontent.com/plotly/datasets/master/tesla-stock-price.csv'
new_dfs, code = spreadsheet(CSV_URL)

st.write(new_dfs)
st.code(code)
```

### Share your app

After you’ve built an app using Mito for Streamlit, it's time to share it! To show it off to the world you can use **Streamlit Community Cloud** to deploy, manage, and share your app for free.

It works in 3 simple steps:

1. Put your app in a public GitHub repo (and make sure it has a requirements.txt!)
2. Sign into [share.streamlit.io](https://share.streamlit.io/)
3. Click 'Deploy an app' and then paste in your GitHub URL

That's it! You now have a publicly deployed app that you can share with the world. Click to learn more about [how to use Streamlit Community Cloud](https://docs.streamlit.io/streamlit-community-cloud).


# API Reference

## The Spreadsheet Component

To display the Mito spreadsheet in a Streamlit application, use the following code:

```python
from mitosheet.streamlit.v1 import spreadsheet

# ... rest of your streamlit app

spreadsheet()
```

### Component API

{% code fullWidth="false" %}

```python
from mitosheet.streamlit.v1 import spreadsheet

spreadsheet(
    *args: , 
    import_folder: Optional[str]=None,
    df_names: Optional[List[str]]=None,
    sheet_functions: Optional[List[Callable]]=None, 
    importers: Optional[List[Callable]]=None, 
    code_options: Optional[CodeOptions]=None,
    column_definitions: Optional[List[ColumnDefinitions]]=None,
    return_type: Options[str]='default',
    default_editing_mode: Optional[Literal['cell', 'column']]=None,
    height: Optional[str]=None,
    key=None
) -> Tuple[Dict[str, pd.DataFrame], str]
```

{% endcode %}

<table data-full-width="true"><thead><tr><th width="239">Argument Name</th><th width="264.3333333333333">Type</th><th>Explanation</th></tr></thead><tbody><tr><td><code>*args</code></td><td><pre><code>Union[pd.DataFrame, str]
</code></pre></td><td>Pass any number of Pandas dataframes or paths to CSV files that will be displayed by in the Mito spreadsheet.</td></tr><tr><td><code>import_folder</code></td><td><pre><code>Optional[str]
</code></pre></td><td>A file path to a folder where users can import data from. Any subfolders will be available for navigation and importing within the Mito file browser.</td></tr><tr><td><code>df_names</code></td><td><pre><code>Optional[List[str]]
</code></pre></td><td>if you pass Pandas dataframes through the <code>args</code>, then optionally include the names of these dataframes in this list. This makes Mito generated code more correct.</td></tr><tr><td><code>sheet_functions</code></td><td><pre><code>Optional[List[Callable]]
</code></pre></td><td>Pass functions that are available as spreadsheet functions in the Mito spreadsheet. <a href="/pages/6qV553Nkd9PC9oVpxVPw">See more here. </a><em>(Mito Enterprise)</em></td></tr><tr><td><code>importers</code></td><td><pre><code>Optional[List[Callable]]
</code></pre></td><td>Pass custom data importers that get an auto-generated UI. <a href="/pages/uCaIxnzLqyYDumLOcr4x">See more here. </a><em>(Mito Enterprise)</em></td></tr><tr><td><code>editors</code></td><td><pre><code>Optional[List[Callable]]
</code></pre></td><td>Pass Python functions that edit a dataframe to get an auto-generated Ui. <a href="https://docs.trymito.io/how-to/custom-editors-autogenerate-ui-from-any-function">See more here.</a> <em>(Mito Enterprise)</em></td></tr><tr><td><code>code_options</code></td><td><code>Optional[CodeOptions]</code></td><td>Pass a <code>CodeOptions</code> object to specify how the code should be generated. <a href="/pages/1FFVvCoXz21kkmI1JfOi">See more here.</a> <em>(Mito Enterprise)</em></td></tr><tr><td><code>column_definitions</code></td><td><code>Optional[List[ColumnDefinitions]]=None</code></td><td>An optional list of <code>ColumnDefinitions</code> to specify conditional formats for a set of columns. See below for usage. <a href="/pages/qJQjjYtD5258YP2kHGTf">See more here</a>. <em>(Mito Enterprise)</em></td></tr><tr><td><code>key</code></td><td><pre><code>Optional[str]
</code></pre></td><td>An optional key that uniquely identifies this component. Necessary if you have multiple Mito <code>spreadsheet</code> displaying the same data.</td></tr><tr><td><code>return_type</code></td><td><code>Optional[str]</code></td><td>An optional string to identify what information you want from the <code>spreadsheet</code> function. See below for the options.</td></tr><tr><td><code>default_editing_mode</code></td><td><code>Optional[Literal['cell', 'column']]</code></td><td>Sets default formula editing behavior. Formulas will either default to editing the entire column, or the specific cell being edited. If not set, defaults to editing the entire column. <em>(Mito Enterprise)</em></td></tr><tr><td><code>height</code></td><td><code>Optional[str]</code></td><td>An optional string to specify the height in pixels that you want to use for the mitosheet. ie: "900px"</td></tr></tbody></table>

### Return Types

By default, the `spreadsheet` component returns:

```python
new_dfs, code = spreadsheet()
```

* `new_dfs`: a Python dictionary from dataframe name to dataframe object. There will be one entry for each tab in the Mito spreadsheet.
* `code`: a string that corresponds to the edits made by the user of the course of the Mito analysis.&#x20;

#### MitoAnalysis Return Type

To **easily rerun your analysis on new data,** return the [MitoAnalysis](/mito-for-streamlit/api-reference/runnableanalysis-class) class through the `return_type` parameter:

```python
analysis = spreadsheet(return_type='analysis')
```

#### Other return types

* `selection`: the current selected cells in the mitosheet
* `default_list`: similar to the default return type, but the dataframes are a list instead of a dictionary
* `dfs_dict` similar to the default return type, but only returns the dict without the code
* `code`: similar to the default return type, but only return the code
* `dfs_list`: returns a list of the dataframes generated by the analysis

## Examples

Below are examples of common uses of the Mito spreadsheet component in a streamlit application.

#### Empty Mito Spreadsheet

```python
from mitosheet.streamlit.v1 import spreadsheet

# Render an empty spreadsheet that allows users to import from the ./data folder
new_dfs, _ = spreadsheet(import_folder='./data')
```

#### Display a Dataframe for Editing

```python
import pandas as pd
from mitosheet.streamlit.v1 import spreadsheet

# Pass a single dataframe for editing
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
new_dfs, _ = spreadsheet(df, df_names=['df'])
new_df = list(new_dfs.values())[0]

# Note that multiple dataframes can be passed as well
# and each will appear as a tab in the Mito spreadsheet
new_dfs, _ = spreadsheet(df1, df2, df_names=['df1', 'df2'])

```

#### Display a CSV file for Editing

```python
from mitosheet.streamlit.v1 import spreadsheet

# Mito will automatically read this file into a dataframe
# and display it as a sheet tab
dfs, _ = spreadsheet('path-to-file.csv')
```

#### Displaying Mito generated code

```python
from mitosheet.streamlit.v1 import spreadsheet

# The second return value is Mito generated code
new_dfs, code = spreadsheet('path-to-file.csv')

# Display the code
st.code(code)
```


# Understanding import\_folder

## Why import\_folder exists

By default, it is not secure to give Streamlit app users access to the entire file system of the server that is running the Streamlit application.&#x20;

As such, app authors have the ability to configure exactly which files users have access to by passing a folder that users have access to, through the `import_folder` parameter.&#x20;

Note that users will have access to all folders and files inside of the `import_folder` recursively.


# RunnableAnalysis class

An easier way to replay your analysis on new data

The `RunnableAnalysis` class is returned when you specify `return_type='analysis'`:

```python
analysis = spreadsheet(return_type='analysis')
```

### Why Use the RunnableAnalysis class?&#x20;

Mito is build for tool for automation. When you make edits in the Mitosheet, it generates code that can be used to replay those edits across new datasets. To make that automation easier to do in your dashboard app, you can use the `RunnableAnalysis` class.&#x20;

First, to help rerun the analysis with new data, the **`RunnableAnalysis` class allows you to access the parameters**: the things you can change when re-running the analysis. Currently, the parameter options are either import and export locations.

Furthermore, when you're ready to re-run your analysis, the **`RunnableAnalysis.run()` function allows you to overwrite those parameters** with new data. For example, you can apply the same set of edits onto two different CSV files.&#x20;

{% hint style="info" %}
To see a fully executable example, [scroll to the bottom](#example-usage).
{% endhint %}

## API

### `get_param_metadata(param_type: Literal['import', 'export'])`

You might want to use `get_param_metadata` to **access all of the parameters that you could override in your analysis.** However, you can also filter for imports or exports if you only want to override one of those types.

This can be used for displaying input on a dashboard that can be used when rerunning the analysis.&#x20;

The return type of this function is a list of `ParamMetadata` objects. They'll look like this:

```python
class ParamMetadata(TypedDict):
    type: ParamType
    subtype: ParamSubtype
    required: bool
    name: str
    original_value: Optional[str]
```

#### required

Some fields are defined as required. This means they are **required arguments for the run function.** Because they were passed as a positional dataframe argument to the `spreadsheet` function, they aren't stored in the `ParamMetadata`.

#### name

This is the name of the variable for this parameter in the code. This can be used for display, but it's main use is **to pass that parameter to the run function as a keyword argument.**&#x20;

#### original\_value

This is the value that was originally used for this parameter when creating this analysis. **The `run` function will default to using this** if you don't pass this parameter to the function.&#x20;

#### Type/Subtype

The **ParamType** and **ParamSubtype** types are used to describe the usage of the parameter. So the  "type" of a parameter will either be 'import' or 'export', and the 'subtype' will describe whether the file is a csv or excel or was passed in other ways. The types are defined as:

```python
ParamType = Literal[
    'import',
    'export'
]

ParamSubtype = Literal[
    'import_dataframe',
    'file_name_export_excel',
    'file_name_export_csv',
    'file_name_import_excel',
    'file_name_import_csv',
    'all' # This represents all of the above
]
```

#### Example Usage

You could use it to display file uploaders for each import in the analysis:

```python
import streamlit as st
from mitosheet.streamlit.v1 import spreadsheet

# Set the streamlit page to wide so you can see the whole spreadsheet
st.set_page_config(layout="wide")

# Create the spreadsheet with return type 'analysis'
analysis = spreadsheet(import_folder='datasets', return_type='analysis')

# Get all of the imports parameters for that analysis
import_params = analysis.get_param_metadata('import')

# Use the parameter metadata to display the params
for param in import_params:
    st.file_uploader(param['name'])
```

### run(\*args, \*\*kwargs)

This is the function that you'd want to call to **rerun your analysis with new data**. This is designed to **allow for overriding the original values** of each parameter. However, for imports that were passed as a positional argument to the `spreadsheet` function, a value will be required to be passed to this function.&#x20;

The `name` value in the `ParamMetadata` should be used as the keyword for that param. So, for example:

```python
import streamlit as st
from mitosheet.streamlit.v1 import spreadsheet

# Set the streamlit page to wide so you can see the whole spreadsheet
st.set_page_config(layout="wide")

# Create the spreadsheet with return type 'analysis'
analysis = spreadsheet(import_folder='datasets', return_type='analysis')

# Get all of the import parameters for that analysis
import_params = analysis.get_param_metadata('import')

print(import_params[0]['name'])
# Output: file_name_import_csv_0

analysis.run(file_name_import_csv_0='/path/to/new/data.csv')
```

### to\_json and from\_json

For **easier storage of analyses**, you can use `to_json` and `from_json` to store the analysis object. For example:

```python
import streamlit as st
from mitosheet.streamlit.v1 import spreadsheet

# Set the streamlit page to wide so you can see the whole spreadsheet
st.set_page_config(layout="wide")

# Create the spreadsheet with return type 'analysis'
analysis = spreadsheet(return_type='analysis')

analysis_json = analysis.to_json()

# Store analysis_json somewhere. Note that it should be stored securely, as it
# may contain code that edits private data
#############################

# Then, load an analysis from a file:
analysis_file_contents = <load analysis json here>

new_analysis_from_file = RunnableAnalysis.from_json(analysis_file_contents)
```

## Example Usage

This is an example of using the `RunnableAnalysis` class from start to finish, including gathering new values for each parameter and creating a button to re-run the analysis on that new data.&#x20;

{% hint style="info" %}
If you want to run this code locally, **make sure to have a folder called 'datasets'** with the data you want to use (in the directory you're starting streamlit from).&#x20;

If you use the Mitosheet to import data from the newly created `datasets` directory you've created, these imports will **appear in the dashboard**! Configuring them will rerun the analysis on new data.
{% endhint %}

```python
import streamlit as st
import pandas as pd 
from mitosheet.streamlit.v1 import spreadsheet

# Set the streamlit page to wide so you can see the whole spreadsheet
st.set_page_config(layout="wide")

# Create an empty spreadsheet
analysis = spreadsheet(
    import_folder='datasets',
    return_type='analysis'
)

# Create an object to store the new values for the parameters
updated_metadata = {}

# Loop through the parameters in the analysis to display imports
for idx, param in enumerate(analysis.get_param_metadata()):
    new_param = None

    # For imports that are exports, display a text input
    if param['subtype'] in ['file_name_export_excel', 'file_name_export_csv']:
        new_param = st.text_input(param['name'], value=param['initial_value'], key=idx)
        
    # For imports that are file imports, display a file uploader
    elif param['subtype'] in ['file_name_import_excel', 'file_name_import_csv']:
        new_param = st.file_uploader(param['name'], key=idx)
    
    if new_param is not None:
        updated_metadata[param['name']] = new_param

# Show a button to trigger re-running the analysis with the updated_metadata
run = st.button('Run')
if run:
    result = analysis.run(**updated_metadata)
    st.write(result)
```


# Column Definitions

{% hint style="info" %}
Setting the `column_definitions` parameter to preconfigure the formatting of your data requires a [Mito Enterprise License](https://www.trymito.io/plans).&#x20;
{% endhint %}

### Why use the column\_definitions parameter?

The `column_definitions` parameter allows you to preconfigure the format of columns displayed in the Mito Spreadsheet. They're particularly useful when you need to apply conditional formatting to columns so your app users can instantly see informative data immedietly after loading your app. &#x20;

### Column Definitions Usage

The `column_conditions` parameter allows users to define conditional formatting rules for specific columns in specific dataframes displayed spreadsheet.

The `column_conditions` is a list of formatting configurations applied to each sheet. &#x20;

* **columns**:  Specifies the columns names to apply the conditional formatting rule to.
* **conditional\_formats**: Specifies the conditional formatting rules for the specified columns.
* **filters**: Each filter is a pair of `condition`  and `value`. For example, if the `condition` is 'greater' and the value is 5, the applied font\_color and background\_color will be applied to all cells in the specific column with a value greater than 5. [See a full list available conditions here](#filter-conditions-reference-list).&#x20;
* **font\_color**: The Hex string representation the font should be displayed in if the cell meets the required condition. A valid conditional format must have at least a font\_color and/or background\_color.
* **backgrond\_color:** The Hex string representation the cell background should be colored in if the cell meets the required condition. A valid conditional format must have at least a font\_color and/or background\_color.

#### Example Usage

The below `column_definitions` displays applies conditional formatting to columns "A" and "B" in the first dataframe inside the spreadsheet.&#x20;

```python
spreadsheet(
    df1, 
    column_definitions=[
        [
            {
                'columns': ['A', 'B'],
                'conditional_formats': [{
                    'filters': [{'condition': 'greater', 'value': 5}], 
                    'font_color': '#c30010', 
                    'background_color': '#ffcbd1' 
                }] 
            }
        ]
    ]
)
```

## Filter Conditions Reference List&#x20;

Below is the complete list of `conditions` available to be used in a conditional format filter. Take note that most filter conditions are only valid if applied to a column with the correct data type, except for the filter conditions labelled with `Any Data Type` at the bottom of the table.&#x20;

<table><thead><tr><th width="230">Column Data Type</th><th width="522">Filter Conditions</th></tr></thead><tbody><tr><td>Number</td><td><code>number_exactly</code></td></tr><tr><td></td><td><code>number_not_exactly</code></td></tr><tr><td></td><td><code>greater</code></td></tr><tr><td></td><td><code>greater_than_or_equal</code></td></tr><tr><td></td><td><code>less</code></td></tr><tr><td></td><td><code>less_than_or_equal</code></td></tr><tr><td></td><td><code>number_lowest</code></td></tr><tr><td></td><td><code>number_highest</code></td></tr><tr><td>String</td><td><code>contains</code></td></tr><tr><td></td><td><code>string_does_not_contain</code></td></tr><tr><td></td><td><code>string_exactly</code></td></tr><tr><td></td><td><code>string_not_exactly</code></td></tr><tr><td></td><td><code>string_starts_with</code></td></tr><tr><td></td><td><code>string_ends_with</code></td></tr><tr><td></td><td><code>string_contains_case_insensitive</code></td></tr><tr><td>Dates</td><td><code>datetime_exactly</code></td></tr><tr><td></td><td><code>datetime_not_exactly</code></td></tr><tr><td></td><td><code>datetime_greater</code></td></tr><tr><td></td><td><code>datetime_greater_than_or_equal</code></td></tr><tr><td></td><td><code>datetime_less</code></td></tr><tr><td></td><td><code>datetime_less_than_or_equal</code></td></tr><tr><td>Boolean</td><td><code>boolean_is_true</code></td></tr><tr><td></td><td><code>boolean_is_false</code></td></tr><tr><td>Any Data Type</td><td><code>empty</code></td></tr><tr><td></td><td><code>not_empty</code></td></tr><tr><td></td><td><code>most_frequent</code></td></tr><tr><td></td><td><code>least_frequent</code></td></tr></tbody></table>

## More Examples

#### Applying conditional formatting to a single dataframe

```python
spreadsheet(
    df1, 
    column_definitions=[
        [
            {
                'columns': ['A', 'B'],
                'conditional_formats': [{
                    'filters': [{'condition': 'greater', 'value': 5}], 
                    'font_color': '#c30010', 
                    'background_color': '#ffcbd1' 
                }] 
            }
        ]
    ]
)
```

#### Applying multiple conditional formatting rules to a single dataframe

```
spreadsheet(    
    df1, 
    column_definitions=[
        [
            {
                'columns': ['A'],
                'conditional_formats': [{
                    'filters': [{'condition': 'greater', 'value': 5}], 
                    'font_color': '#c30010', 
                    'background_color': '#ffcbd1' 
                }] 
            },
            {
                'columns': ['B'],
                'conditional_formats': [{
                    'filters': [{'condition': 'contains', 'value': 'invalid'}], 
                    'font_color': '#c30010', 
                    'background_color': '#ffcbd1' 
                }] 
            }
        ]
    ]
) 
```

#### Applying conditional formatting to multiple dataframes

```python
spreadsheet(
    df1, 
    df2
    column_definitions=[
        [
            {
                'columns': ['A', 'B'],
                'conditional_formats': [{
                    'filters': [{'condition': 'greater', 'value': 5}], 
                    'font_color': '#c30010', 
                    'background_color': '#ffcbd1' 
                }] 
            },
        ],
        [
            {
                'columns': ['C', 'D'],
                'conditional_formats': [{
                    'filters': [{'condition': 'less', 'value': 0}], 
                    'font_color': '#c30010', 
                    'background_color': '#ffcbd1' 
                }] 
            },
        ],
    ]
)
```

##




---

[Next Page](/llms-full.txt/1)

