Adding and changing columns
Calculating from other columns
import pandas as pd
orders = pd.DataFrame({
"product": ["Keyboard", "Monitor", "Mouse", "Webcam"],
"quantity": [1, 2, 3, 1],
"price": [89.99, 279.00, 24.50, 59.00],
})
orders["total"] = orders["quantity"] * orders["price"]
orders["total_with_tax"] = (orders["total"] * 1.18).round(2)
print(orders)Assigning to a new column name creates it, calculated for every row at once.
assign: several columns, as a new DataFrame
import pandas as pd
orders = pd.DataFrame({
"product": ["Keyboard", "Monitor", "Mouse", "Webcam"],
"quantity": [1, 2, 3, 1],
"price": [89.99, 279.00, 24.50, 59.00],
})
summary = orders.assign(
total=lambda d: d["quantity"] * d["price"],
share=lambda d: (d["total"] / d["total"].sum() * 100).round(1),
)
print(summary)assign returns a new DataFrame and leaves the original alone, and later columns can use earlier ones, as share uses total. It suits long chains of steps.
Conditions: np.where
import numpy as np
import pandas as pd
orders = pd.DataFrame({"product": ["Keyboard", "Monitor", "Mouse"], "total": [89.99, 558.00, 73.50]})
orders["size"] = np.where(orders["total"] >= 100, "large", "small")
orders["shipping"] = np.where(orders["total"] >= 100, 0, 49)
print(orders)Lookups: map
import pandas as pd
people = pd.DataFrame({"name": ["Asha", "Leo", "Mei", "Raj"], "city": ["Mumbai", "London", "Osaka", "Paris"]})
codes = {"Mumbai": "BOM", "London": "LHR", "Osaka": "KIX"}
people["airport"] = people["city"].map(codes)
print(people)map with a dictionary replaces each value with its entry. Values with no entry, like Paris here, become missing.
Custom logic: apply
import pandas as pd
orders = pd.DataFrame({
"product": ["Keyboard", "Monitor", "Mouse"],
"total": [89.99, 558.00, 73.50],
"express": [True, False, True],
})
def delivery_fee(row):
fee = 0 if row["total"] >= 100 else 49
if row["express"]:
fee += 99
return fee
orders["fee"] = orders.apply(delivery_fee, axis=1)
print(orders)apply(function, axis=1) calls your function once per row. It can express any logic, but it runs Python for every row, so on big tables prefer the column-at-a-time tools above.
Grouping numbers into bins: pd.cut
import pandas as pd
students = pd.DataFrame({"name": ["Asha", "Leo", "Mei", "Raj", "Zoe"], "score": [92, 58, 74, 88, 75]})
students["grade"] = pd.cut(students["score"], bins=[0, 60, 75, 90, 100], labels=["F", "C", "B", "A"])
print(students)
print(students["grade"].value_counts().sort_index())pd.cut sorts numbers into ranges. By default each bin includes its upper edge, so 75 falls in (60, 75] and gets a C.
Renaming, dropping and converting
import pandas as pd
raw = pd.DataFrame({"Prod Name": ["Pen", "Bag"], "qty": ["3", "1"], "notes": ["", "gift"]})
clean = (raw
.rename(columns={"Prod Name": "product", "qty": "quantity"})
.drop(columns=["notes"])
.astype({"quantity": int}))
print(clean)
print(clean["quantity"].sum())rename takes a dictionary of old to new names, drop(columns=...) removes columns, and astype converts types. Chaining them, wrapped in brackets, reads as a sequence of cleaning steps.