Pandas is an open-source Python library built on top of NumPy, used for data manipulation and analysis. It provides fast, flexible, and expressive data structures designed to work with both relational and labelled data. The word "Pandas" is derived from the term "Panel Data", an econometrics term for multidimensional structured datasets. For a Class 12 Informatic Practices student, Pandas is the most important library because most of the syllabus deals with reading, cleaning, analysing, and visualising data using it.
The library introduces two key data structures: the Series, which is a one-dimensional labelled array that can hold any data type, and the DataFrame, which is a two-dimensional labelled data structure with columns of potentially different types. Think of a Series as a single column of a spreadsheet and a DataFrame as the entire spreadsheet. Most real-world datasets, such as student marksheets, sales records, or temperature readings, map naturally onto the DataFrame, which is why it is the workhorse of data analysis in Python.
This chapter lays the foundation for all subsequent chapters. We will first learn to import Pandas, then create Series and DataFrames from a variety of sources, inspect their attributes, and finally access individual elements and slices. Mastery of these basics is essential because Chapter 2 builds operations such as filtering, merging, grouping, and aggregation directly on these structures.
Pandas is not part of the standard Python library, so it must be installed first using the command pip install pandas. Once installed, the library is imported with an alias so that commands remain short:
import pandas as pd
import numpy as np
The alias pd is the community standard and is used in almost every pandas program. We also import numpy because pandas internally stores data using NumPy arrays. To confirm installation, the version can be printed:
print(pd.__version__)
Every program in this chapter assumes these two import lines have already been executed.
A Series is a one-dimensional array-like object that holds a sequence of values and an associated array of data labels, called its index. The index need not be numeric; it can be strings, dates, or any hashable object. If no index is supplied, pandas automatically assigns a default integer index from 0 to n-1.
import pandas as pd
marks = pd.Series([88, 92, 75, 68])
print(marks)
Output:
0 88
1 92
2 75
3 68
dtype: int64
The left column shows the auto-generated index and the right column shows the values.
import pandas as pd
student = pd.Series([88, 92, 75], index=["Ravi", "Simran", "Amit"])
print(student)
Output:
Ravi 88
Simran 92
Amit 75
dtype: int64
When a custom index is supplied, elements can be accessed either by position or by label. student[0] returns 88, and student["Ravi"] also returns 88.
A Series can also be created directly from a Python dictionary. The dictionary keys become the index and the values become the data:
import pandas as pd
d = {"Maths": 90, "Science": 85, "English": 78}
s = pd.Series(d)
print(s)
Output:
Maths 90
Science 85
English 78
dtype: int64
import pandas as pd
import numpy as np
arr = np.array([10, 20, 30, 40])
s = pd.Series(arr, index=["a", "b", "c", "d"])
print(s)
If a scalar value is used, the Series repeats that value for each index label:
import pandas as pd
s = pd.Series(7, index=[1, 2, 3])
print(s)
Output:
1 7
2 7
3 7
dtype: int64
Series objects expose several attributes that reveal their metadata:
import pandas as pd
s = pd.Series([10, 20, 30, 40], index=["a", "b", "c", "d"])
print(s.values)
print(s.index)
print(s.dtype)
print(s.shape)
print(s.size)
print(s.hasnans)
s.values returns the underlying NumPy array.s.index returns the index object.s.dtype gives the data type of the values.s.shape returns a tuple (4,) showing the number of rows.s.size returns the total number of elements.s.hasnans returns True if any value is missing.Useful methods include s.head(n) and s.tail(n) to view the first and last n elements, s.describe() to get statistical summary like count, mean, std, min and max, and s.sort_values() to sort the series in ascending order:
import pandas as pd
s = pd.Series([88, 92, 75, 68], index=["Ravi", "Simran", "Amit", "Neha"])
print(s.head(2))
print(s.sort_values())
print(s.describe())
A Series behaves like a NumPy array, so arithmetic and comparison operators are applied element-wise without any explicit loop. This property is called vectorisation.
import pandas as pd
s = pd.Series([10, 20, 30])
print(s + 5)
print(s * 2)
print(s > 15)
Output:
0 15
1 25
2 35
dtype: int64
0 20
1 40
2 60
dtype: int64
0 False
1 True
2 True
dtype: bool
Arithmetic between two Series is aligned on their index labels. If a label is missing in either series, the result for that position is NaN (Not a Number). Series also support built-in statistical methods such as s.sum(), s.mean(), s.min(), s.max(), s.median(), and s.std().
A DataFrame is a two-dimensional, size-mutable, and potentially heterogeneous tabular data structure with labelled axes: rows are labelled by an index and columns are labelled by column names. It can be thought of as a dictionary of Series objects sharing the same index, or as a spreadsheet stored in memory.
import pandas as pd
data = {
"Name": ["Ravi", "Simran", "Amit"],
"Maths": [90, 85, 78],
"Science": [88, 92, 80]
}
df = pd.DataFrame(data)
print(df)
Output:
Name Maths Science
0 Ravi 90 88
1 Simran 85 92
2 Amit 78 80
The keys of the dictionary become the column names and each list supplies the values for that column. Rows are indexed 0, 1, 2 by default.
Here each dictionary represents one row, and the keys become the column names:
import pandas as pd
rows = [
{"Name": "Ravi", "Maths": 90},
{"Name": "Simran", "Maths": 85}
]
df = pd.DataFrame(rows)
print(df)
import pandas as pd
s1 = pd.Series([90, 85, 78], index=["Ravi", "Simran", "Amit"])
s2 = pd.Series([88, 92, 80], index=["Ravi", "Simran", "Amit"])
df = pd.DataFrame({"Maths": s1, "Science": s2})
print(df)
import pandas as pd
data = [["Ravi", 90], ["Simran", 85], ["Amit", 78]]
df = pd.DataFrame(data, columns=["Name", "Maths"])
print(df)
An empty DataFrame can be created and columns added later:
import pandas as pd
df = pd.DataFrame()
df["Name"] = ["Ravi", "Simran"]
print(df)
Common attributes of a DataFrame are shown below:
import pandas as pd
df = pd.DataFrame(
{"Name": ["Ravi", "Simran", "Amit"], "Maths": [90, 85, 78]},
index=[101, 102, 103]
)
print(df.shape)
print(df.size)
print(df.index)
print(df.columns)
print(df.values)
print(df.dtypes)
print(df.axes)
df.shape returns (3, 2) meaning 3 rows and 2 columns.df.size returns the total number of elements, which is 6.df.index shows the row labels.df.columns shows the column labels.df.values returns the data as a NumPy array.df.dtypes gives the data type of each column.df.axes returns a list [Index([101,102,103]), Index(['Name','Maths'])].Basic viewing methods are df.head(n), df.tail(n), and df.info(). df.head() displays the first 5 rows by default, df.tail() the last 5, and df.info() prints a concise summary of the DataFrame including column names, non-null counts, and dtypes.
Data in a DataFrame can be accessed either column-wise or row-wise.
A single column is a Series and can be selected in two equivalent ways:
print(df["Name"])
print(df.Name)
Multiple columns are selected by passing a list of column names, which returns a DataFrame:
print(df[["Name", "Maths"]])
A new column can be added by simple assignment:
df["Physics"] = [75, 82, 90]
A column can be deleted using the del statement:
del df["Physics"]
Rows can be selected using loc (label based), iloc (position based), or simple slicing. df.loc[101] returns the row whose index label is 101, while df.iloc[0] returns the first row:
print(df.loc[101])
print(df.iloc[0])
print(df[1:3])
The slice df[1:3] returns rows from position 1 up to but not including position 3. Labelled access using loc includes the end label, whereas integer slicing excludes the end position.
| Source | Code | Default Index |
|---|---|---|
| List | pd.Series([88, 92]) |
0, 1, 2 ... |
| Dictionary | pd.Series({"a": 1, "b": 2}) |
Dictionary keys |
| NumPy array | pd.Series(np.array([1, 2])) |
0, 1, 2 ... |
| Scalar | pd.Series(7, index=[1, 2]) |
Given index |
| Attribute | Series | DataFrame |
|---|---|---|
values |
NumPy array of data | 2-D NumPy array |
index |
Row labels | Row labels |
columns |
Not available | Column labels |
shape |
(n,) tuple |
(r, c) tuple |
dtype / dtypes |
Data type | Data type per column |
size |
Number of elements | Total number of elements |
import pandas instead of import pandas as pd, causing the code to fail with NameError.loc and iloc: loc works with index labels and includes the end label, while iloc works with integer positions and excludes the end.df.Name to work when the column name contains a space or starts with a digit; only df["column name"] works then.df[1:3] selects rows with labels 1 and 2; integer slicing always uses positions, not labels.s.dtype on a DataFrame; a DataFrame has multiple columns, so the correct attribute is df.dtypes.df[["A", "B"]] returns a DataFrame while df["A"] returns a Series.dtype line at the bottom.head() and tail() take the number of rows as an optional argument and default to 5.describe(), sort_values(), and index-based selection.df.shape gives a tuple, and order is always rows first, columns second.Pandas provides the two fundamental data structures, Series and DataFrame, which form the backbone of data analysis in Python. A Series is a one-dimensional labelled array created from lists, dictionaries, NumPy arrays, or scalars, while a DataFrame is a two-dimensional table created from dictionaries of lists, lists of dictionaries, Series, or lists of lists. Both structures expose rich attributes such as index, values, shape, and dtype and support vectorised operations that work without explicit loops. Understanding how to create, inspect, and access these structures prepares the student for advanced operations like filtering, grouping, merging, and statistical aggregation, which form the subject matter of Python Pandas - II and the data handling chapters that follow.