📊 阅读时长:18分钟 | 关键词:Pandas、concat拼接、merge合并、insert、reindex、drop

引言

前两篇文章我们学了 Series 和 DataFrame 的创建与访问,以及数据清洗的核心方法。但在实际数据分析中,数据往往分散在多个表格里——你需要把它们拼在一起、按某个字段关联、或者删除不需要的行列。这篇文章就来解决这些"进阶操作"。

一、DataFrame 常用属性速览

在进入具体操作之前,先熟悉一下 DataFrame 的常用属性。打印一下,心里有数:

import pandas as pd
import numpy as np

d = [['Tom', 17], ['Bob', 18], ['Linda', 26]]
df = pd.DataFrame(data=d, index=['p1', 'p2', 'p3'], columns=['name', 'age'])

print(df.T)           # 转置:行列互换
print(df.dtypes)      # 每一列的数据类型
print(df.shape)       # 形状:(3, 2)
print(df.size)        # 元素总数:6
print(df.index)       # 行索引
print(df.columns)     # 列索引
print(df.axes)        # 以列表形式返回 [行索引, 列索引]
print(df.values)      # 以 ndarray 形式返回数据
属性 描述
T 转置(行列互换)
dtypes 返回每一列的数据类型
shape 返回 DataFrame 的形状(行数, 列数)
size 返回元素总数量
index 返回行索引
columns 返回列索引
axes 以列表形式返回 [行索引, 列索引]
values 以 ndarray 数组形式返回数据

二、insert() 插入新列

insert(loc, column, value) 可以在指定位置插入一列,而不是追加到最后。

d = {'name': ['Tom', 'Bob', 'Linda'], 'age': [17, 18, 26]}
df = pd.DataFrame(data=d, index=['p1', 'p2', 'p3'])

# 在索引为 2 的位置插入列 'weight'(即第 3 列)
df.insert(2, 'weight', [65, 75, 60])
print(df)

输出:

    name  age  weight
p1   Tom   17      65
p2   Bob   18      75
p3 Linda   26      60

参数说明

  • loc:整数,指定插入列的位置(列索引)
  • column:新列的名称
  • value:插入的数据,可以是标量、Series 或 array-like

💡 提示:insert() 是原地操作,直接修改原 DataFrame,没有返回值。

三、reindex() 重新索引

reindex() 不改变原数据,而是按你指定的标签"重新取值"。如果指定的标签不存在,默认填 NaN。

data = np.arange(12).reshape(3, 4)
df = pd.DataFrame(data, index=['n1', 'n2', 'n3'], columns=['a', 'b', 'c', 'd'])
print(df)
    a  b   c   d
n1  0  1   2   3
n2  4  5   6   7
n3  8  9  10  11
# 重新索引行标签
df2 = df.reindex(index=['n2'])        # 只取 n2 行
print(df2)

df2 = df.reindex(index=['n2', 'n1', 'n4'], fill_value=3.14)  # n4 不存在,填充 3.14
print(df2)

# 重新索引列标签
df2 = df.reindex(columns=['c'])        # 只取 c 列
print(df2)

参数说明

参数 说明
labels 要获取的标签列表,与 axis 配合使用
axis 0 为行,1 为列
index 直接指定行标签
columns 直接指定列标签
fill_value 缺失位置的填充值,默认为 NaN

💡 reindex() 返回新的 DataFrame,不修改原数据。

四、pd.concat() 拼接

当你有两个表格需要"上上下下"或"左左右右"拼起来时,就用 pd.concat()

df1 = pd.DataFrame([[1, 2], [3, 4]], index=['p1', 'p2'], columns=list('AB'))
df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AC'))

print("df1:\n", df1)
print("df2:\n", df2)
df1:
     A  B
p1  1  2
p2  3  4

df2:
    A  C
0  5  6
1  7  8
# 默认 axis=0:上下拼接,列做并集,缺失值填 NaN
print(pd.concat([df1, df2]))

# join='inner':只保留共有的列
print(pd.concat([df1, df2], join='inner'))

# axis=1:左右拼接,行索引对齐
print(pd.concat([df1, df2], axis=1))

参数详解

参数 说明
objs 要拼接的 DataFrame 序列(列表)
axis 0 = 纵向拼接(默认),1 = 横向拼接
join 'outer' 保留所有列(默认),'inner' 只保留共有列
ignore_index True 时忽略原索引,重新生成 0, 1, 2…

一张图搞懂 concat

axis=0(纵向)              axis=1(横向)
+---+---+                  +---+---+---+---+
| A | B |                  | A | B | A | C |
+---+---+     join='outer' +---+---+---+---+
| 1 | 2 |                  | 1 | 2 | 5 | 6 |
| 3 | 4 |  +----------->   | 3 | 4 | 7 | 8 |
+---+---+                  +---+---+---+---+
| A | C |
+---+---+
| 5 | 6 |
| 7 | 8 |
+---+---+
     结果:列做并集,缺失填 NaN

五、pd.merge() 合并(重点!)

concat 是"物理拼接",merge 是"逻辑关联"——它像 SQL 的 JOIN,按某个共同的键(列)将两张表关联起来。

d1 = {'name': ['Tom', 'Bob', 'Jack'], 'age': [18, 17, 19], 'weight': [65, 66, 67]}
df1 = pd.DataFrame(data=d1)

d2 = {'name': ['Tom', 'Jack'], 'height': [168, 187], 'weight': [65, 68]}
df2 = pd.DataFrame(data=d2)

print("df1:\n", df1)
print("df2:\n", df2)
df1:
   name  age  weight
0   Tom   18      65
1   Bob   17      66
2  Jack   19      67

df2:
   name  height  weight
0   Tom     168      65
1  Jack     187      68
# 内连接(inner):只保留两表都有的 name
print(pd.merge(df1, df2, how='inner', on='name'))

# 左连接(left):以左表为准,右表没有的填 NaN
print(pd.merge(df1, df2, how='left', on='name'))

# 右连接(right):以右表为准,左表没有的填 NaN
print(pd.merge(df1, df2, how='right', on='name'))

# 外连接(outer):两表所有行都保留
print(pd.merge(df1, df2, how='outer', on='name'))

四种连接方式对比(一张表记住)

连接方式 说明 结果
inner 取两表键的交集 只保留 key 同时存在的数据
left 左表为基准 右表匹配不上的填 NaN
right 右表为基准 左表匹配不上的填 NaN
outer 取两表键的并集 匹配不上的都填 NaN

inner 的结果(两表都有的 name = Tom, Jack):

   name  age  weight_x  height  weight_y
0   Tom   18        65     168        65
1  Jack   19        67     187        68

⚠️ 注意:两表都有 weight 列,merge 会自动加上后缀 _x_y 区分。

left 的结果(Bob 在右表不存在,对应数据填 NaN):

   name  age  weight_x  height  weight_y
0   Tom   18        65   168.0      65.0
1   Bob   17        66     NaN       NaN
2  Jack   19        67   187.0      68.0

参数详解

参数 说明
left / right 左右两个 DataFrame
how 'inner' / 'left' / 'right' / 'outer'
on 连接键(列名),该键必须在两表中都存在

六、drop() 删除行或列

df = pd.DataFrame([[1, 2], [3, 4], [5, 6]], 
                  index=['n1', 'n2', 'n3'], columns=['a', 'b'])
print(df)
    a  b
n1  1  2
n2  3  4
n3  5  6
# 删除行索引为 'n2' 的数据行
print(df.drop(index='n2'))

# 删除列索引为 'b' 的数据列
print(df.drop(columns='b'))

# 批量删除多行
print(df.drop(index=['n2', 'n1']))

# 批量删除多列
print(df.drop(columns=['a', 'b']))

# inplace=True 直接修改原数据
df.drop(index='n1', inplace=True)
print(df)

参数详解

参数 说明
labels 要删除的标签,与 axis 配合
axis 0 = 删除行,1 = 删除列
index 直接指定要删除的行标签
columns 直接指定要删除的列标签
inplace True 直接修改原数据,返回 None

小结

序号 知识点 一句话总结
1 DataFrame 属性 shape/dtypes/index/columns 快速了解数据轮廓
2 insert() 在指定位置插入新列
3 reindex() 按标签重新取值,不存在的填 NaN
4 pd.concat() 上下或左右"物理拼接",join 控制保留策略
5 pd.merge() 按共同键"逻辑关联",how 控制 inner/left/right/outer
6 drop() 按标签删除行或列,inplace=True 原地修改

下一篇文章,我们将学习 Pandas 的统计与聚合——describe()groupby()apply() 等,这些才是数据分析真正的"生产力工具"。


本文是「Python从入门到数据分析」系列的第 15 篇。关注我,不错过后续更新。

更多推荐