Skip to main content
MahiDev — Learn. Build. Become AI-ready.

Lesson 11

Adding Columns and Rows

Grow a DataFrame: build a new column from a value or an expression, place one at a chosen position, and append rows with loc or concat.

Intermediate25 min
Adding Columns and Rows hero Module 24 Lesson 11Adding Columns and Rows hero Module 24 Lesson 11

Assigning to a name that does not exist yet creates a column. The value can be a single number, a list of the right length, or an expression over the columns you already have, which is where pandas saves you a loop.

A table gaining a computed per_hour columnA table gaining a computed per_hour column

A column from a value

Assign a single value and pandas repeats it down the column. Assign a list and it must have exactly one value per row, or you get a ValueError.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey"],
    "score": [88, 74, 91],
})
learners["term"] = "autumn"
learners["group"] = [1, 2, 1]
print(learners)

Output:

text
     name  score    term  group
0   Avery     88  autumn      1
1  Jordan     74  autumn      2
2   Casey     91  autumn      1

A column from the other columns

An expression over whole columns runs element by element, with no loop in sight. round keeps the result readable, and comparisons give a Boolean column you can filter on later.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
learners["per_hour"] = (learners["score"] / learners["hours"]).round(2)
learners["passed"] = learners["score"] >= 75
print(learners[["name", "hours", "score", "per_hour", "passed"]])

Output:

text
     name  hours  score  per_hour  passed
0   Avery     42     88      2.10    True
1  Jordan     31     74      2.39   False
2   Casey     55     91      1.65    True
3   Riley     24     65      2.71   False
4  Morgan     47     82      1.74    True
5   Quinn     38     79      2.08    True

Place a column where you want it

Assignment always adds at the right. insert takes a position, a name, and the values, so a label column can sit next to the name it describes.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
learners.insert(1, "level", ["mid", "new", "senior", "new", "mid", "mid"])
print(learners.head(3))
print(learners.columns.tolist())

Output:

text
     name   level   track       city  hours  score
0   Avery     mid  Python  Northgate     42     88
1  Jordan     new   NumPy   Eastport     31     74
2   Casey  senior  Python  Northgate     55     91
['name', 'level', 'track', 'city', 'hours', 'score']

assign leaves the original alone

assign returns a new DataFrame with the extra columns, which suits a chain of steps where you do not want to touch the source table.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
report = learners.assign(
    per_hour=(learners["score"] / learners["hours"]).round(2),
    busy=learners["hours"] > 40,
)
print(report[["name", "per_hour", "busy"]])
print(learners.columns.tolist())

Output:

text
     name  per_hour   busy
0   Avery      2.10   True
1  Jordan      2.39  False
2   Casey      1.65   True
3   Riley      2.71  False
4  Morgan      1.74   True
5   Quinn      2.08  False
['name', 'track', 'city', 'hours', 'score']

Add a row

.loc[new_label] = [...] writes one row, and len(df) is the next free position when the index counts from 0. For several rows, build a small DataFrame and concat it, which is far cheaper than appending one row at a time.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan"],
    "hours": [42, 31],
})
learners.loc[len(learners)] = ["Casey", 55]
print(learners)

extra = pd.DataFrame({"name": ["Riley", "Morgan"], "hours": [24, 47]})
learners = pd.concat([learners, extra], ignore_index=True)
print(learners)

Output:

text
     name  hours
0   Avery     42
1  Jordan     31
2   Casey     55
     name  hours
0   Avery     42
1  Jordan     31
2   Casey     55
3   Riley     24
4  Morgan     47

ignore_index=True renumbers the rows so the labels stay unique.

Key takeaways

  • Assigning to a new name creates a column at the right-hand end

  • A single value fills the column; a list must match the row count

  • insert places a column at a chosen position and assign returns a new table

  • Use .loc for one row and pd.concat for many

  • Next: Updating Values

  • Previous: Filtering Rows

Loading playground…

Check your understanding

Adding Columns and Rows Quiz

What does assigning to a name that does not exist do?

1 / 10