使用 pd.concat 堆叠 DataFrames
使用 pd.concat 垂直或水平堆叠 DataFrames,按索引或列对齐,并处理重复索引。
使用 pd.concat 堆叠 DataFrames 是 CoddyKit 上的免费 Pandas & NumPy Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Pandas & NumPy Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Pandas & NumPy Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Concatenate DataFrames?
In real projects, data rarely arrives in a single file. You might have monthly sales files, regional survey exports, or database query results split across multiple queries. Concatenation stacks these separate DataFrames into one combined table. Pandas provides pd.concat() for this purpose, handling both vertical (row-wise) and horizontal (column-wise) stacking.
Basic Vertical Concatenation
The most common use of pd.concat() is stacking DataFrames vertically (adding more rows). Pass a list of DataFrames and the function appends them one below the other. Both DataFrames must have compatible columns for a clean result. Pandas aligns on column names automatically, filling missing columns with NaN.
import pandas as pd
jan = pd.DataFrame({'product': ['A', 'B'], 'sales': [100, 200]})
feb = pd.DataFrame({'product': ['A', 'C'], 'sales': [150, 120]})
combined = pd.concat([jan, feb])
print(combined)
# product sales
# 0 A 100
# 1 B 200
# 0 A 150
# 1 C 120Resetting the Index After Concat
Notice that pd.concat() preserves the original indices from each DataFrame, which can result in duplicate index values (as seen above with two rows at index 0 and index 1). Pass ignore_index=True to create a fresh sequential integer index in the combined result, which is almost always what you want.
combined = pd.concat([jan, feb], ignore_index=True)
print(combined)
# product sales
# 0 A 100
# 1 B 200
# 2 A 150
# 3 C 120
print(combined.index)
# RangeIndex(start=0, stop=4, step=1)Tracking Source with keys
When concatenating data from multiple sources, you may want to know which original DataFrame each row came from. Pass the keys parameter with a list of labels. Pandas creates a MultiIndex where the outer level identifies the source. You can then use .loc['label'] to access rows from a specific source.
combined = pd.concat([jan, feb], keys=['January', 'February'])
print(combined)
# product sales
# January 0 A 100
# 1 B 200
# February 0 A 150
# 1 C 120
# Access only February rows
print(combined.loc['February'])Horizontal Concatenation with axis=1
Pass axis=1 to concatenate DataFrames side by side (adding more columns). Pandas aligns on the row index, so both DataFrames should have the same index for a clean result. If indices differ, non-matching rows will be filled with NaN. This is useful for combining features computed from the same dataset in separate steps.
names = pd.DataFrame({'name': ['Alice', 'Bob', 'Carol']}, index=[1, 2, 3])
scores = pd.DataFrame({'score': [95, 88, 72]}, index=[1, 2, 3])
combined = pd.concat([names, scores], axis=1)
print(combined)
# name score
# 1 Alice 95
# 2 Bob 88
# 3 Carol 72Handling Mismatched Columns
If the DataFrames being concatenated have different columns, Pandas keeps all columns and fills missing values with NaN. This is the default join='outer' behaviour. If you want to keep only the columns that appear in all DataFrames, pass join='inner', which drops any column not present in every source.
df1 = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
df2 = pd.DataFrame({'b': [5, 6], 'c': [7, 8]})
# Outer join (default): keeps all columns
print(pd.concat([df1, df2], ignore_index=True))
# a b c
# 0 1.0 3 NaN
# 1 2.0 4 NaN
# 2 NaN 5 7.0
# 3 NaN 6 8.0
# Inner join: keeps only shared columns
print(pd.concat([df1, df2], join='inner', ignore_index=True))
# b
# 0 3
# 1 4
# 2 5
# 3 6Concatenating Many Files in a Loop
A typical pattern when loading multiple files is to collect all DataFrames in a list and call pd.concat() once at the end. Avoid concatenating inside a loop (e.g., df = pd.concat([df, new_chunk])) because this creates a new DataFrame copy on every iteration, leading to quadratic time complexity for large collections.
import glob
# Efficient: collect first, concat once
files = glob.glob('data/sales_*.csv')
frames = [pd.read_csv(f) for f in files]
combined = pd.concat(frames, ignore_index=True)
# Inefficient (avoid):
# result = pd.DataFrame()
# for f in files:
# result = pd.concat([result, pd.read_csv(f)]) # slow!Concatenating Series
pd.concat() works with Series as well as DataFrames. Concatenating a list of Series vertically gives a longer Series. Concatenating with axis=1 produces a DataFrame where each Series becomes a column. The Series are aligned on their index, so the index labels must match for a clean horizontal concat.
s1 = pd.Series([1, 2, 3], name='x')
s2 = pd.Series([4, 5, 6], name='y')
# Vertical: one long Series
print(pd.concat([s1, s2]))
# 0 1
# 1 2
# ...
# Horizontal: a DataFrame with two columns
print(pd.concat([s1, s2], axis=1))
# x y
# 0 1 4
# 1 2 5
# 2 3 6Verifying the Concatenated Result
After concatenating, always verify the result has the expected shape and no unexpected NaN values. A quick sanity check pattern: compare the combined row count to the sum of individual counts, and call isna().sum() to spot any unintended missing values introduced by column misalignment. These checks prevent silent data quality issues from propagating into your analysis.
combined = pd.concat([jan, feb], ignore_index=True)
# Sanity checks
assert len(combined) == len(jan) + len(feb), 'Row count mismatch'
print('Missing values per column:')
print(combined.isna().sum())
print('Shape:', combined.shape)concat vs append (deprecated)
Older Pandas code may use df.append(other), which was a convenience wrapper around pd.concat(). This method was deprecated in Pandas 1.4 and removed in Pandas 2.0. Always use pd.concat([df, other], ignore_index=True) in modern code. The behaviour is identical but pd.concat is more explicit and supports concatenating more than two DataFrames at once.
# Old (removed in Pandas 2.0):
# combined = jan.append(feb, ignore_index=True)
# Modern equivalent:
combined = pd.concat([jan, feb], ignore_index=True)
print(combined)Practical Example: Yearly Sales Report
Here is a realistic pattern: load monthly DataFrames, add a source label, concatenate, and compute a full-year summary. The keys parameter makes it easy to trace each row back to its month, and ignore_index=True combined with a month column gives a clean, flat DataFrame for group-by analysis.
months = ['jan', 'feb', 'mar']
frames = []
for m in months:
df = pd.DataFrame({'product': ['A', 'B'], 'sales': [100, 200]})
df['month'] = m
frames.append(df)
yearly = pd.concat(frames, ignore_index=True)
print(yearly.groupby('month')['sales'].sum())Quick Check
Test your understanding of pd.concat for stacking DataFrames from this lesson.
Lesson Recap
In this lesson you learned: how to stack DataFrames vertically with pd.concat() and ignore_index=True, how to track sources using the keys parameter, and how join='inner' vs 'outer' controls column handling when schemas differ. Next up we explore pd.merge() for SQL-style inner and outer joins on shared key columns.
常见问题解答
「使用 pd.concat 堆叠 DataFrames」课时是免费的吗?
是的 — 「使用 pd.concat 堆叠 DataFrames」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Pandas & NumPy Academy 课程的其余内容,请升级到 CoddyKit PRO。 Pandas & NumPy Academy 课程共包含 4 节课。
「使用 pd.concat 堆叠 DataFrames」这节课中我会学到什么?
使用 pd.concat 垂直或水平堆叠 DataFrames,按索引或列对齐,并处理重复索引。 你通过在浏览器中直接运行的动手代码来练习 Pandas & NumPy Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Pandas & NumPy Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Pandas & NumPy Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「使用 pd.concat 堆叠 DataFrames」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Pandas & NumPy Academy 课中编写并运行代码吗?
能。每节 Pandas & NumPy Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 pd.concat 堆叠 DataFrames
- pd.merge:内连接与外连接
- 左连接与右连接
- 按索引连接