Data analysis often starts with an unfamiliar spreadsheet or CSV file. Before you can write a single transformation, you need to know what’s in it and what’s wrong with it. Positron is a free IDE for data science projects that puts that inspection step in the same workspace as your code, so you can examine the data first and then watch your results take shape as you run your code.
In this tutorial, you’ll use Positron’s data tools to answer one question about a set of sales orders: How does median order value differ between retail and wholesale orders across product categories? You’ll inspect the raw data, clean it in a script, repeat the analysis in a notebook, and try Positron’s AI assistant. Then you’ll decide whether the tool fits the way you and your team work with data.
By the end of this tutorial, you’ll understand that:
- Data Explorer helps you find quality issues in your data before running cleanup steps in Python.
- Data cleaning belongs in saved code, whether that’s a script or a notebook, so that your fixes stay reproducible and your analysis starts from clean data.
- Scripts and notebooks let you produce and visualize intermediate results as your analysis develops.
- Posit Assistant is an AI agent that can suggest explanations, analyses, and visualizations for the data you’re working with.
Positron is built on Visual Studio Code’s open-source foundation and supports both Python and R workflows. You’ll focus on Python throughout, using a small dataset to explore Positron’s data tools.
Get Your Code: Click here to get the ready-to-run notebooks and sales dataset you’ll use to inspect, clean, analyze, and visualize data in Positron IDE.
Take the Quiz: Test your knowledge with our interactive “Positron IDE: A Hands-on Python Tutorial” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Positron IDE: A Hands-on Python TutorialCheck your understanding of Positron IDE for Python data analysis, from exploring raw data to cleaning it in scripts and notebooks.
Get Started With Positron IDE
To follow along with this tutorial, you need basic familiarity with pandas DataFrames, Matplotlib, and uv. Make sure to install uv on your system if you don’t already have it.
Note: The examples use pandas 3.0.5 and Matplotlib 3.11.2. The interface instructions target Positron 2026.09.1-2.
Next, install Positron. Check the storage requirements first because the installer can require over 1 GB of space on some platforms. On Windows, you’ll also need the latest Visual C++ Redistributable installed. Then download the installer for your operating system, run it, and follow the on-screen instructions.
Once you’ve installed Positron, open the IDE. A fresh installation will look something like the following:

Because Positron is built on VS Code’s open-source codebase, you can import your existing VS Code settings. For this tutorial, you’ll skip that step by clicking Later in the pop-up box in the lower-left corner.
In the accompanying materials, you’ll find data/sales_data.csv, a dataset of 5,130 fictional orders for olive oil, bath products, and gift baskets. This is the sample data you’ll use in this tutorial, so make sure to download the materials before reading on.
In Positron, select Open Folder from the File menu or from the Primary Side Bar and open the folder containing the materials. The project has the following layout:
positron-ide/
│
├── data/
│ └── sales_data.csv
│
├── notebooks/
│ └── explore_sales.ipynb
│
├── src/
│ ├── analyze_sales.py
│ └── prepare_sales.py
│
├── pyproject.toml
└── uv.lock
In any data analysis workflow, data cleaning is probably the most important step. The prepare_sales.py script checks and cleans the source data for you.
The analyze_sales.py script analyzes the cleaned data, and the explore_sales.ipynb notebook reproduces the work of both scripts in one place. The project configuration file, pyproject.toml, lists your starting dependencies.
To manage the project, you’ll use uv, which generates the uv.lock file to record the resolved versions of your dependencies. You don’t have to edit this file by hand because uv keeps it up to date for you.
Now, you can create a Python virtual environment without leaving the editor. Open the Command Palette with Ctrl+Shift+P on Windows or Linux, or Cmd+Shift+P on macOS, and run Python: Create Environment:

Positron asks which environment provider you want. Select uv. Then it asks which Python version to use. Select 3.14.
Positron creates a .venv folder in your project, discovers it, and selects it for your Python session. It also bundles the IPython kernel, so you can use the Console without installing anything else.
Next, install the project dependencies. Select View → Terminal from the app’s main menu. The Terminal opens in the Panel at the bottom, starting a new session with the Python environment activated. If you don’t see the environment name in parentheses, then activate the environment yourself. On Linux and macOS, run source .venv/bin/activate. On Windows, run .venv\Scripts\Activate.ps1 in PowerShell.
Note: If Positron doesn’t pick up the environment automatically, run Interpreter: Discover All Interpreters from the Command Palette to refresh the list, and then select the project’s .venv.
With the Terminal open, run the following command:
$ uv sync --locked
This command reads uv.lock and installs the recorded versions of pandas, Matplotlib, and nbformat into .venv.
Explore Raw Data Files
When you get a new dataset, explore it visually before you run any analysis. This first step helps you get familiar with the data: the fields and their meanings, the number of rows, the presence of outliers and missing values, and so on.
For this kind of exploration, Positron has a Data Explorer that launches automatically when you select a raw data file in the File Explorer. The supported formats include CSV, TSV, Parquet, and Excel (.xlsx), plus compressed versions of CSV, TSV, and Parquet files.
To try it out, select data/sales_data.csv in the File Explorer, which opens the file in the Data Explorer. To free up screen space, you can hide the left, right, and bottom panels using the layout icons in the top-right corner of the window. You’ll end up with a view like the following:

The Data Explorer has three primary components:
- Data grid: Spreadsheet-like display of the individual columns, rows, and cells
- Filter bar: Temporary filters for specific columns
- Summary panel: Descriptive statistics for each column in the dataset
In the lower-left corner of the Data Explorer, you’ll find the row (5,130) and column (16) counts. Each column header shows the field name and data type. Browse the headers and scroll across the grid. The order_type, product_category, quantity, unit_price, and sale_price columns will be central to your analysis.
Use the column controls on the right to sort sale_price in descending order:

The same menu contains a few other options, including Add Filter. You can also apply filters on the Filter bar, which sits directly above the Summary panel. Sorting and filtering change only the view, so the CSV on disk stays exactly as you downloaded it.
The Summary panel lists each column name alongside a chart. If you expand a column, then you’ll see additional statistics that depend on the column’s type. Categorical columns report missing, empty, and unique values, while numeric columns report missing values along with the minimum, median, mean, maximum, and standard deviation.
Note: The Summary panel recalculates its statistics when you apply a filter. During the recalculation, you’ll see loading indicators next to the column names and in the lower-left corner of the window, and the expanded statistics will show placeholder dots until the values appear.
A visual inspection helps you spot data quality issues. For example, you may notice the following problems in the sample dataset:
- Misspelled column name:
produce_nameinstead ofproduct_name - Inconsistent capitalization:
product_categorymixesBath productswithOlive OilandGift Basket
In the next section, you’ll fix these and other issues, then visualize and analyze the clean data.
Clean, Visualize, and Analyze the Data
You already have a rough idea of what your data contains. Now, you’ll clean, visualize, and analyze it. You’ll work through the whole process in scripts first, then reproduce it in a notebook.
The analysis is the whole point of your work, so remember the question you need to answer: How does median order value (sale_price) differ between retail and wholesale orders across product categories? You’ll answer it with a pair of Python scripts, one to clean the data and one to analyze it.
Using Python Scripts
First, you’ll load and clean the data. Close the Data Explorer, show the File Explorer, and select src/prepare_sales.py. Notice that the first line contains the # %% comment:
prepare_sales.py
# %%
from pathlib import Path
import pandas as pd
PROJECT_ROOT = Path.cwd()
sales = pd.read_csv(PROJECT_ROOT / "data/sales_data.csv")
print(sales.shape)
print(sales.head())
Positron interprets this comment as the start of a cell. Cells are chunks of code that you can run on their own, but they share one Python session, so a cell that uses sales works only after you’ve run the cell that creates it. When you start or restart a session, run the cells in order:

This first cell imports Path from pathlib and pandas as pd. Then it stores the current working directory in PROJECT_ROOT. Positron’s Console starts at the folder you opened, so that’s your project root, where data/ lives. Finally, it reads data/sales_data.csv into a DataFrame named sales and prints its shape and first five rows.
Click Run Cell above the first # %% comment. The Console pane at the bottom will show the code as a REPL session and display the shape of the DataFrame, (5130, 16), and its first five rows.
You now have a pandas DataFrame called sales in the active Python session. Open sales in the Variables pane to inspect the in-memory object:

Although you can inspect the data visually in the Data Explorer and the Variables pane, you should run some checks programmatically to flag missing values, duplicates, and inconsistent types. Run the second cell in prepare_sales.py:
prepare_sales.py
# ...
# %%
print("Missing cells:", sales.isna().sum().sum())
print("Duplicate rows:", sales.duplicated().sum())
print("Repeated order numbers:", sales["order_number"].duplicated().sum())
print(sales.dtypes)
The first three checks each report zero. This means that your data has no missing cells, duplicate rows, or repeated order numbers.
The data type check reveals another issue beyond those you spotted in the Data Explorer: pandas reads order_date as strings rather than as dates.
In the cell below, you’ll fix that issue along with the misspelled column name and inconsistent categories:
prepare_sales.py
# ...
# %%
clean_sales = sales.rename(
columns={"produce_name": "product_name"},
)
clean_sales["order_date"] = pd.to_datetime(
clean_sales["order_date"], format="%d/%m/%Y"
)
clean_sales["product_category"] = (
clean_sales["product_category"].str.strip().str.title()
)
To clean the data without losing the original DataFrame, you typically create a copy with the issues fixed. The code renames the produce_name column to product_name. It also parses the order_date strings with the "%d/%m/%Y" format to get pandas datetime objects, then normalizes the product categories by removing leading and trailing spaces and applying title case.
Finally, save the clean data so that your analysis can start from it:
prepare_sales.py
# ...
# %%
clean_sales.to_csv(PROJECT_ROOT / "data/sales_clean.csv", index=False)
Now go ahead and check your work. Select data/sales_clean.csv in the File Explorer to open it in the Data Explorer. The grid should now show a product_name header in place of produce_name, and the product categories should use consistent title case. Inspect the dates, and you’ll find that they all follow a format like 2019-02-09 instead of 09/02/2019.
You’re ready to answer your question. Open src/analyze_sales.py and run its first cell:
analyze_sales.py
# %%
from pathlib import Path
import matplotlib.pyplot as plt
import pandas as pd
PROJECT_ROOT = Path.cwd()
sales = pd.read_csv(
PROJECT_ROOT / "data/sales_clean.csv",
parse_dates=["order_date"],
)
This cell imports pandas and Matplotlib. Then it loads sales_clean.csv, parsing order_date back into dates with parse_dates. This is required because CSV files store everything in plain text.
Before you start the analysis, run the second cell and look at the overall numbers:
analyze_sales.py
# ...
# %%
print(sales[["quantity", "unit_price", "sale_price"]].describe().round(2))
print(sales["order_type"].value_counts())
This code produces the following output:
quantity unit_price sale_price
count 5130.00 5130.00 5130.00
mean 3.22 83.82 333.08
std 2.51 84.84 592.44
min 1.00 5.99 5.99
25% 2.00 14.50 34.00
50% 3.00 45.00 104.00
75% 4.00 123.00 342.00
max 14.00 234.00 3276.00
order_type
Retail 4375
Wholesale 755
Name: count, dtype: int64
The mean sale price is 333.08, while the median, shown in the 50% row, is 104.00. A few large orders pull the mean well above the middle of the data, so the median describes a typical order more faithfully. You also have 4,375 retail orders compared with 755 wholesale orders, so the two groups differ in size.
After this quick analysis, you know that your answer should use the median and report each group’s order count next to that median. The median is the middle value after sorting a group’s order values, or the average of the two middle values when a group has an even number of orders. Run the following cell to build that summary:
analyze_sales.py
# ...
# %%
order_summary = sales.groupby(
["product_category", "order_type"],
as_index=False,
).agg(
orders=("order_number", "size"),
median_order_value=("sale_price", "median"),
)
print(order_summary.round(2).to_string(index=False))
Grouping by two columns produces six rows, one retail group and one wholesale group per product category. The as_index=False argument keeps the grouping keys as ordinary columns, which you need for inspection and plotting, and the named aggregations give the result columns readable names:
product_category order_type orders median_order_value
Bath Products Retail 1308 22.35
Bath Products Wholesale 86 67.53
Gift Basket Retail 751 140.00
Gift Basket Wholesale 41 351.00
Olive Oil Retail 2316 135.00
Olive Oil Wholesale 628 1404.00
There’s your answer. A typical wholesale order is worth more than a typical retail order in every category, but the gap is much wider in some categories than in others:
- Bath products: 22.35 retail compared with 67.53 wholesale
- Gift baskets: 140 retail compared with 351 wholesale
- Olive oil: 135 retail compared with 1,404 wholesale
Olive oil is the outlier. A typical wholesale order in that category is worth about as much as ten retail ones.
The table above has the numbers, but a chart would make the differences easier to grasp. Reshape the summary so that each order type becomes a chart series:
analyze_sales.py
# ...
# %%
chart_data = order_summary.pivot(
index="product_category",
columns="order_type",
values="median_order_value",
)
ax = chart_data.plot.bar(rot=0, figsize=(8, 4))
ax.set(xlabel="Product category", ylabel="Median order value")
ax.set_title("Retail and Wholesale Order Values")
plt.tight_layout()
plt.show()
In this example, the .pivot() call rearranges the values you already aggregated. Each pair of bars compares retail and wholesale orders within one category, so you can see the size of every gap at a glance.
Positron’s Plots pane displays the Matplotlib result:

Change the chart’s title and run the cell again to create another version. Then use the plot-history controls to move between them. You can also save a plot to a file, copy it to your clipboard, and more. Next, you’ll reproduce this same analysis in a notebook.
Using a Notebook
A script keeps your calculations in a plain Python file. A notebook places those same calculations beside explanations and visible results, so it’s worth repeating this analysis there to see the difference firsthand. Open notebooks/explore_sales.ipynb in the File Explorer. Positron uses its Notebook Editor by default:

The notebook should already be using the project’s Python kernel. If not, then go to the Kernel Selector in the notebook’s action bar and choose the appropriate kernel.
You’ll notice that the notebook sets PROJECT_ROOT to Path.cwd().parent, while the scripts use Path.cwd(). That’s because a notebook’s kernel starts in the notebook’s own folder, not the folder you opened.
A notebook is a stack of cells. Code cells hold Python code and can run on their own, but they share the notebook’s kernel, so a cell that uses a variable works only after you’ve run the cell that creates it. When you start or restart the kernel, run the cells from the top. Markdown cells hold descriptions, explanations, and conclusions.
Use the buttons at the top of the editor, or the ones that appear between cells, to add a cell of either type where you need it. To run the selected cell, click its Run Cell button or press Shift+Enter. This keyboard shortcut also moves to the next cell, adding a new one if you’re at the end of the notebook.
Here’s what you get after running the first code cell:

This notebook covers the same ground as the two scripts. The first code cell loads the data and displays some information about its shape and content. Notice how the Markdown cells explain the code.
The next code cells check data quality, clean the data, and then describe and compare it. Run these cells. You’ll see the same output you got with the scripts.
The Visualize the Comparison cell renders the Matplotlib chart inline, as cell output under the code that built it:

In practice, notebooks are a great tool for data processing, cleaning, visualization, and presentation. Scripts are better suited to repetitive tasks that can run in the background.
Try Posit Assistant to Explain Your Notebook
Posit Assistant is Positron’s built-in AI helper. It can read and analyze the data and code in your session, explain what a piece of code does, write new code, and suggest relevant analyses and visualizations for your data.
You can access the assistant by opening the Posit Assistant pane from the Primary Side Bar:

Before you can chat with the assistant, you need to connect an LLM provider. You can supply the credentials for a provider you already have an account with. Open the Command Palette and run Authentication: Configure Language Model Providers. Then pick a provider and authenticate:

Check the setup guide for more details on each provider’s requirements. Most require an API key or a browser sign-in, while enterprise providers like Microsoft Foundry also need an endpoint and a model ID.
Once you connect an LLM provider, you can use the assistant to help process your data. For example, with your notebook open, select the Assistant button in the notebook’s action bar, and you’ll see a panel like the following:

In the Notebook Assistant panel, you’ll find several quick actions that the assistant can run on your notebook. Go ahead and select the Explain This Notebook option to start a new chat with a dedicated prompt. Below, you can see the result of running this quick action with Google’s Gemini 3 Flash Preview model:

From here, you can try the other quick actions or ask follow-up questions in the chat to dig further into your analysis.
Limitations to Know About
Positron packs a lot into one workspace, but you should know about a couple of limitations before you incorporate it into your workflow:
-
The VS Code Marketplace is off-limits: Positron installs extensions from the Open VSX catalog because Microsoft doesn’t license the Marketplace outside its own builds. Open VSX carries most popular extensions but not all of them, and some copies lag behind the originals. Check your must-have extensions before you migrate, and install any missing ones manually from
.vsixfiles. -
SSH support requires a Linux host: Positron’s Remote SSH support runs the interface locally with a remote backend on a Linux server. It doesn’t work with native Windows or macOS hosts, although WSL on Windows counts as Linux. The client and server also have to run the exact same Positron version.
If either limitation gets in your way, then you can check out other IDEs and editors tailored for data science, such as Spyder or JupyterLab. A broader Python IDE comparison can help you weigh the alternatives, depending on your needs.
Conclusion
Positron IDE gives you specialized tools for working with data. You can use them to inspect data visually, clean it programmatically, run your analysis, and present the results in notebooks and charts.
In this tutorial, you’ve learned how to:
- Inspect raw files with Positron’s Data Explorer and in-memory
DataFrameobjects in the Variables pane - Clean and save your data with pandas and Python
- Analyze and visualize data with Python scripts and notebooks
- Use Posit Assistant to get an AI explanation of your notebook
Try Positron in your workflow with your own dataset to see whether it suits your needs. Pay attention to whether its built-in tools for data processing and visualization save you time and help you get more accurate results.
You’ve worked in Python throughout this tutorial, but Positron can also run R code in the same workspace and project, and each language keeps its own runtime and packages. That makes Positron a reasonable choice for teams that use both languages.
Get Your Code: Click here to get the ready-to-run notebooks and sales dataset you’ll use to inspect, clean, analyze, and visualize data in Positron IDE.
Frequently Asked Questions
Now that you have some experience with Positron IDE for Python data analysis, you can use the questions and answers below to check your understanding and recap what you’ve learned.
These FAQs address the most important concepts you’ve covered in this tutorial. Click the Show/Hide toggle beside each question to reveal the answer.
Positron IDE is a free development environment for data science with Python and R. It combines data inspection, scripts, notebooks, plots, and package management in one workspace so you can explore data and check your analysis as you work.
The Data Explorer handles CSV, TSV, Parquet, and Excel (.xlsx) files, including compressed CSV, TSV, and Parquet files. Selecting one of them in the File Explorer opens it directly in the Data Explorer’s spreadsheet-style grid, so you can take a first look at an unfamiliar dataset without writing any code.
Filtering and sorting in the Data Explorer change the displayed view without modifying the original CSV or DataFrame. To make a transformation reproducible, write the equivalent filtering or sorting code in a script or notebook and save the prepared data to a separate file when needed.
The # %% comment marks the start of a cell, which is a chunk of code that you can run on its own. Positron shows a Run Cell control above each one, and the output appears in the Console pane.
Positron’s data inspection, Python execution, notebooks, and plotting features work without an AI provider account. Posit Assistant, which this tutorial covers, requires you to connect an LLM provider, so that provider’s charges and data policies apply to your usage.
Take the Quiz: Test your knowledge with our interactive “Positron IDE: A Hands-on Python Tutorial” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Positron IDE: A Hands-on Python TutorialCheck your understanding of Positron IDE for Python data analysis, from exploring raw data to cleaning it in scripts and notebooks.