Pandas Library in Python (2026): The Complete Pandas 3.0 Tutorial
If you learned Pandas from a tutorial written before January 2026, some of what it taught you no longer runs — .applymap(), .append(), and chained assignment tricks were quietly removed or made stricter in Pandas 3.0. This tutorial teaches the current, correct syntax throughout, with a dedicated migration section if you're coming from older code.
Quick Answer: What Is Pandas and What Changed in 3.0?
Pandas is Python's core library for data manipulation and analysis, built around the one-dimensional Series and two-dimensional DataFrame. Pandas 3.0, released January 21, 2026, is the biggest breaking change to the library in years: Copy-on-Write is now default (chained assignment now raises a hard error instead of a warning), text columns default to a new PyArrow-backed string dtype instead of the old generic object type, and several long-deprecated methods — .applymap(), Series.ravel(), DataFrame.append() — have been permanently removed. If your existing code or a tutorial you're following predates January 2026, expect some of it to no longer run as written.
What's Actually New in Pandas 3.0
Before writing a single line of code, it's worth understanding exactly what changed and why — because these aren't cosmetic updates, they're behavior changes that will silently alter what your existing scripts do.
- Copy-on-Write (CoW) is now the default. Pandas has struggled for over a decade with an ambiguous question: does an operation on a DataFrame return a view of the original data, or an independent copy? Copy-on-Write resolves this — every derived DataFrame or Series now behaves as a separate object, with an actual copy only created in memory the moment something tries to modify it.
- Chained assignment now raises an error, not a warning. The old
SettingWithCopyWarningthat many people learned to simply ignore is gone. In its place, attempting chained assignment (likedf[df['A'] > 0]['B'] = 1) now raises a hardChainedAssignmentError. - A dedicated PyArrow-backed string dtype replaces the old object dtype. Text columns are now inferred as
string[pyarrow]by default when PyArrow is installed, rather than the old genericobjectdtype. This is faster, uses less memory, and enables zero-copy data sharing with tools like Polars and DuckDB — but it also means dtype checks written for the old behavior may no longer match. - Default datetime resolution changed from nanoseconds to microseconds, fixing the long-standing out-of-bounds date error for dates outside the 1678–2262 range.
- The
copy=keyword argument on many methods now does nothing. It's deprecated and has no effect under Copy-on-Write, since the whole point of CoW is that you no longer need to specify this manually. DataFrame.applymap(),Series.ravel(), andDataFrame.append()have been permanently removed — not just deprecated. Use.map(), standard NumPy array conversion, andpd.concat()respectively instead.groupby(observed=)now defaults toTrueinstead ofFalse, changing how grouping on categorical columns behaves by default.
A huge share of Pandas content online — tutorials, course videos, forum answers — still teaches pre-3.0 behavior, because it was written before January 2026. If code you find elsewhere uses .applymap(), relies on chained assignment, or checks for dtype == 'object' on string columns, it may no longer work as shown. This tutorial teaches current, Pandas 3.0–correct syntax throughout.
Installing Pandas 3.0
Getting set up correctly matters more than usual this time, given the Python version floor and the PyArrow dependency.
# Requires Python 3.11 or later python --version # Install pandas with the pyarrow backend # (pyarrow powers the new default string dtype) pip install pandas pyarrow
import pandas as pd print(pd.__version__) # Should print 3.0.0 or later
Series and DataFrame: The Two Core Structures
Everything in Pandas builds on two structures. Understanding the distinction early saves confusion later.
- A Series is a one-dimensional labeled array — conceptually, a single column of data with an index attached.
- A DataFrame is a two-dimensional labeled table — multiple Series sharing the same index, conceptually a spreadsheet or SQL table with named columns and rows.
import pandas as pd # A Series — one column, with an index prices = pd.Series([2.50, 3.75, 1.20], name="price") print(prices) # A DataFrame — multiple columns sharing an index df = pd.DataFrame({ "product": ["coffee", "tea", "water"], "price": [2.50, 3.75, 1.20], "in_stock": [True, True, False] }) print(df) # Selecting one column returns a Series print(type(df["price"])) # <class 'pandas.core.series.Series'> # Selecting multiple columns returns a DataFrame print(type(df[["price", "in_stock"]])) # DataFrame # In Pandas 3.0, string columns default to the new PyArrow-backed dtype print(df.dtypes) # product string[pyarrow] <-- new default, was 'object' before 3.0 # price float64 # in_stock bool
For a broader, structured path through Pandas alongside the rest of the Python data science stack, our data science tutorials and resources hub covers where Pandas fits in the full learning roadmap from Python basics through machine learning.
Loading and Exploring Data
Real data analysis starts with getting data in, then understanding its shape before touching it.
import pandas as pd # Load from CSV, Excel, or JSON df = pd.read_csv("sales_data.csv") # df = pd.read_excel("sales_data.xlsx") # df = pd.read_json("sales_data.json") # Always check the shape and structure before doing anything else print(df.head()) # first 5 rows print(df.info()) # column names, dtypes, non-null counts print(df.describe()) # summary statistics for numeric columns print(df.shape) # (rows, columns)
df.info() is the single fastest way to catch problems early — unexpected data types, columns with far fewer non-null values than expected, or memory usage that's higher than it should be. In Pandas 3.0, watch particularly for whether string columns show up as string[pyarrow] (the new default) or fall back to object, which happens automatically if PyArrow isn't installed.
Cleaning Data the Copy-on-Write-Safe Way
This is the section where old tutorials break most visibly. Under Copy-on-Write, a very common older pattern for conditionally modifying data no longer works — and understanding exactly why, and the correct replacement, matters more than any other single thing in this tutorial.
# This pattern was common (if warned-about) before Pandas 3.0. # Under Copy-on-Write, it now raises a ChainedAssignmentError. df[df["price"] > 3]["category"] = "premium" # ChainedAssignmentError: You are setting values through # chained assignment. This will never work.
# Always use .loc[] for conditional assignment. # This was always the recommended approach — it's now required. df.loc[df["price"] > 3, "category"] = "premium" # This is unambiguous under Copy-on-Write: you are modifying # the original df directly, in one step, not through a chain # of two separate indexing operations.
The underlying rule that makes this click: any time you're modifying data based on a condition, do it in a single .loc[] call rather than two separate square-bracket operations chained together. The old chained version was always ambiguous about whether it was modifying a view or a copy — Pandas simply used to warn about it instead of stopping you.
# Handling missing values df = df.dropna(subset=["price"]) # drop rows missing price df["category"] = df["category"].fillna("unknown") # fill with a value # Renaming columns df = df.rename(columns={"prod": "product"}) # Applying a function to a column — use .map(), not .applymap() # .applymap() was permanently removed in Pandas 3.0 df["price_rounded"] = df["price"].map(round) # Combining multiple dataframes — use pd.concat(), not .append() # .append() was permanently removed in Pandas 3.0 combined = pd.concat([df1, df2], ignore_index=True)
Groupby: Split-Apply-Combine
groupby() is Pandas' answer to "summarize this data by category," and it follows a consistent three-step pattern: split the DataFrame into groups based on a column, apply a function to each group independently, then combine the results back into a single output.
import pandas as pd df = pd.DataFrame({ "product": ["A", "B", "A", "B", "A"], "region": ["North", "South", "North", "South", "West"], "sales": [100, 150, 200, 120, 180] }) # Group by one column, aggregate one metric avg_sales = df.groupby("product")["sales"].mean() print(avg_sales) # product # A 160.0 # B 135.0 # Group by multiple columns grouped = df.groupby(["product", "region"])["sales"].sum() # Apply multiple aggregations at once summary = df.groupby("product")["sales"].agg(["mean", "sum", "count"]) print(summary)
If you're grouping on a categorical column, note that groupby(observed=) now defaults to True in Pandas 3.0, instead of False as before. This changes whether unused category levels appear in your grouped results by default — set it explicitly if your code depends on the old behavior.
Merging, Joining, and Concatenating DataFrames
Real datasets rarely live in one table. Pandas gives you three distinct tools for combining them, and picking the right one matters:
merge()— combines data based on shared column values, like a SQL JOIN. Use this when you have a common key (like a customer ID) across two tables..join()— combines data based on the index, a convenient shorthand for a specific common merge pattern.pd.concat()— stacks DataFrames together, either by rows or by columns, without matching on keys. This is also the current replacement for the removed.append()method.
import pandas as pd orders = pd.DataFrame({"customer_id": [1, 2, 3], "amount": [50, 75, 30]}) customers = pd.DataFrame({"customer_id": [1, 2, 4], "name": ["Alice", "Bob", "Cara"]}) # merge() — like a SQL JOIN on a shared column merged = orders.merge(customers, on="customer_id", how="left") # concat() — stack rows from multiple dataframes together # This is the Pandas 3.0 replacement for the removed .append() q1_sales = pd.DataFrame({"month": ["Jan", "Feb"], "sales": [100, 120]}) q2_sales = pd.DataFrame({"month": ["Apr", "May"], "sales": [140, 130]}) full_year = pd.concat([q1_sales, q2_sales], ignore_index=True)
Understanding when to use each of these three tools is a common early stumbling block. If you're building toward machine learning workflows where clean, correctly-merged data feeds directly into model training, our open-source machine learning tools guide covers the Scikit-learn and modeling stack that Pandas output typically feeds into next.
Migrating from Pandas 2.x to 3.0
If you have existing Pandas code written before January 2026, here is exactly what to check, in one table.
| Change | Pandas 2.x behavior | Pandas 3.0 behavior | Fix |
|---|---|---|---|
| Chained assignment | SettingWithCopyWarning |
ChainedAssignmentError |
Use .loc[] |
| String dtype | object |
string[pyarrow] |
Update dtype checks |
copy= keyword |
Creates a copy | No effect (deprecated) | Remove the argument |
groupby(observed=) |
Default False |
Default True |
Set explicitly if needed |
.applymap() |
Available | Removed | Use .map() |
.append() |
Available | Removed | Use pd.concat() |
| Datetime resolution | Nanoseconds | Microseconds (default) | Review date range logic |
The recommended migration path, per the Pandas team's own guidance, is not to jump straight to 3.0:
Upgrade to Pandas 2.3 first
Stay on the last 2.x release and run your existing code as-is. This surfaces deprecation warnings without breaking anything yet.
Enable Copy-on-Write mode manually to test compatibility
Set pd.options.mode.copy_on_write = True while still on 2.3, then run your code and fix whatever breaks — this simulates 3.0's default behavior before you've actually upgraded.
Resolve every deprecation warning
Treat warnings as required fixes, not optional cleanup — anything still warning in 2.3 is very likely to be a hard error or removed feature in 3.0.
Upgrade to Pandas 3.0
With PyArrow installed and Python 3.11+ confirmed, upgrade. Re-run your full test suite, if you have one, and pay particular attention to any code that checks dtype == 'object' on string columns.
Pandas vs Polars: Should You Learn Both?
Polars is worth a brief, honest mention, since it's increasingly part of the same conversation — and it's directly relevant to Pandas 3.0's own design, since the new PyArrow-backed string dtype specifically enables zero-copy data sharing with Polars.
- Pandas remains the more widely used and required library for Python data analysis, with the deepest ecosystem integration across visualization, machine learning, and reporting tools. Most job postings and most existing codebases assume Pandas.
- Polars is genuinely faster for very large datasets, built from the ground up on the same Apache Arrow foundation that now also powers Pandas 3.0's string dtype — which is part of why the two increasingly interoperate well.
- The practical recommendation: learn Pandas first and thoroughly — it remains the correct starting point for nearly everyone — then add Polars later specifically for workloads where raw performance on large data genuinely matters.
Frequently Asked Questions
What is the Pandas library in Python used for?
Pandas is Python's core library for data manipulation and analysis, built around the one-dimensional Series and two-dimensional DataFrame. It's used to load data from CSV, Excel, SQL, and JSON sources, clean and reshape messy data, filter and group rows, merge multiple datasets together, compute statistics, and prepare data for visualization or machine learning. It's foundational to nearly every Python-based data science, data analysis, and machine learning workflow.
What is new in Pandas 3.0?
Pandas 3.0, released January 21, 2026, is the most significant breaking release since the library's 1.x era. Core changes: Copy-on-Write (CoW) is now default, meaning chained assignment now raises a ChainedAssignmentError instead of the old SettingWithCopyWarning; a new dedicated string dtype backed by PyArrow (string[pyarrow]) replaces the old object dtype for text columns; default datetime resolution changed from nanoseconds to microseconds; the copy= keyword argument on many methods now has no effect; and DataFrame.applymap(), Series.ravel(), and DataFrame.append() have been permanently removed.
Is Pandas 2.x code compatible with Pandas 3.0?
Mostly, but not entirely — 3.0 is a breaking release. Code relying on chained assignment (like df[df['A'] > 0]['B'] = 1) now raises an error instead of a warning. Code using .applymap(), Series.ravel(), or .append() will fail outright since these were permanently removed. Code checking dtype == 'object' on string columns may behave unexpectedly, since strings are now backed by a dedicated string dtype by default. The Pandas team recommends upgrading to 2.3 first, resolving all deprecation warnings, then moving to 3.0.
What is Copy-on-Write in Pandas and why does it matter?
Copy-on-Write (CoW) is a memory management approach, now default in Pandas 3.0, that resolves the long-standing ambiguity over whether an operation on a DataFrame returns a view or an independent copy. Under CoW, any derived DataFrame or Series behaves as a completely separate object, and a copy is only created in memory when something tries to modify it. Practically, this eliminates the confusing SettingWithCopyWarning, replacing it with a clear ChainedAssignmentError when chained assignment is attempted, and has been reported to meaningfully improve performance in production workloads.
How do I install and check my Pandas version?
Install with pip install pandas, or pip install pandas pyarrow to also get the PyArrow backend powering the new default string dtype in Pandas 3.0. To check your installed version, run import pandas as pd followed by print(pd.__version__). Pandas 3.0 requires Python 3.11 or later, so confirm your Python version with python --version if you encounter installation errors.
What is the difference between a Pandas Series and a DataFrame?
A Series is a one-dimensional labeled array, conceptually a single column of data with an index attached. A DataFrame is a two-dimensional labeled table made up of multiple Series sharing the same index, conceptually a spreadsheet or SQL table. Selecting one column from a DataFrame (df['column_name']) returns a Series; selecting multiple columns (df[['col1', 'col2']]) returns a DataFrame. Nearly all real-world Pandas work happens at the DataFrame level.
Should I learn Pandas or Polars in 2026?
Pandas remains the more widely used and required library for Python data analysis in 2026, with the deepest ecosystem integration. Polars is a newer, genuinely faster alternative built on the same Apache Arrow foundation that now also powers Pandas 3.0's default string dtype, worth learning as a second tool for very large datasets where raw performance matters most. For most learners and most job postings, Pandas remains the correct starting point, with Polars as a valuable addition once Pandas fundamentals are solid.
Conclusion: Learn It Right the First Time
Pandas 3.0 is a genuinely good release — Copy-on-Write removes a decade-old source of confusing bugs, the new string dtype is faster and lighter, and the removed methods were all things the Pandas team had been warning about for years. But "genuinely good" doesn't mean "compatible with everything you learned before," and that gap is exactly where most confusion happens right now. If a tutorial, course, or Stack Overflow answer you're following predates January 2026, treat its syntax with the same skepticism you'd apply to a five-year-old JavaScript tutorial — the concepts likely still hold, but the exact code may not run.
The practical habit worth building: whenever you hit an error that doesn't match what a tutorial promised, check whether it's a Pandas 3.0 behavior change before assuming you made a mistake. Chained assignment errors, dtype mismatches, and missing methods are the three most common symptoms, and all three are covered directly in this guide.
For the next steps in a Pandas-centered data science path — visualization, machine learning, and eventually production deployment — our data science tutorials and resources hub lays out the full roadmap, and our open-source machine learning tools guide covers exactly where cleaned Pandas DataFrames go next in a real modeling pipeline.
Explore More Python & Data Science Tutorials
Visit the Review Publically Data Science hub for the complete learning roadmap, from Python fundamentals through machine learning and deployment.
▶ Explore the Data Science Hub- Pandas Official Documentation — What's New in 3.0.0 (January 21, 2026)
- Pandas Official Documentation — Group By: Split-Apply-Combine
- DEV Community — Pandas 3.0 Is Here: Copy-on-Write, PyArrow, and What You Need to Know
- SharpSkill — Pandas 3.0 in 2026: New APIs, Breaking Changes and Interview Questions
- PyRastra — Pandas 3.0 Migration Guide: What Changed and How to Upgrade Safely
- Real Python — Combining Data in Pandas With merge(), .join(), and concat()
- Review Publically — Data Science Tutorials & Resources Hub
- Review Publically — Open-Source ML Tools 2025
Khalid Hussain
Founder of Review Publically. MSc holder and Google Advanced Data Analytics certified. Teaches Python data analysis with a focus on current, correct, production-ready syntax rather than outdated conventions.
Related Articles