数据分析避不开 Pandas,而 DataFrame 的增、删、改、查更是每天都在用的基本功。这篇文章用一份 1960--2019 全球 GDP 数据 从头走一遍四大操作,每一个都带可运行代码 + 运行结果 + 踩坑提示,建议收藏后跟着敲一遍。
0. 准备数据
import pandas as pd
# 注意:原文件是 GBK 编码,必须指定 encoding='gbk'
df = pd.read_csv('data/1960-2019全球GDP数据.csv', encoding='gbk')
print(df.columns) # Index(['year', 'country', 'GDP'])
df.head()
数据一共三列:year(年份)、country(国家)、GDP(数值)。后面所有操作都基于它,演示时经常用 df[:5].copy() 拷贝前 5 行出来做试验,避免污染原始数据。
小习惯:练习增删改一定要先
.copy(),否则很容易在不知不觉中改掉原表。
一、增:新增列
给 DataFrame 加列有两大思路:直接赋值 和 assign()。
思路 1:直接赋值 df['新列'] = ...
df2 = df[:5].copy()
# 写法1:固定值(整列都是同一个数)
df2['c1'] = 23
# 写法2:传入列表(长度必须和行数一致)
df2['c2'] = ['cxk', 'lyf', 'wyf', 'wyb', '水冷哥']
# 写法3:用已有列做运算,生成新列
df2['c3'] = df2['year'] * 2
# 写法4:通过函数返回值生成新列
def my_func1():
return 25000
df2['c4'] = my_func1()
df2
运行结果 :新增了 c1/c2/c3/c4 四列,行数不变。
⚠️ 踩坑:写法 2 的列表长度必须和 DataFrame 行数完全相等 ,否则直接报
ValueError。写法 3 是最高频的用法,本质是 "拿一列(Series)做运算得到新列"。
思路 2:assign () 链式新增
df3 = df[:5].copy()
# 新增1列
df3 = df3.assign(c1=23)
# 新增多列(一次性搞定)
df3 = df3.assign(
c1=23,
c2=['cxk', 'lyf', 'wyf', 'wyb', '水冷哥'],
c3=df3['year'] * 2,
cf=my_func1()
)
df3
assign() 的优势是可以链式调用、一次加多列 ,且它本身不会修改原表,必须用返回值接住。
对比:
df['c1']=23直接改原表;assign()返回新表。两者都常用,喜欢链式编程选assign。
二、删:删除行 / 列 / 去重
2.1 删行
df4 = df[:10].copy()
df4 = df4.drop(0) # 删 index=0 那一行
df4 = df4.drop([0, 2, 4]) # 删多个指定 index
df4 = df4.drop(index=0) # 用 index 参数,更明确
df4 = df4.drop(index=[0, 2, 4])
df4
drop 默认按 行标签(index) 删,返回新表,不改原表。
2.2 删列
# 方式A:axis=1(0是行,1是列)
df4 = df4.drop('GDP', axis=1)
# 方式B:columns 参数(推荐,一眼看懂)
df4 = df4.drop(columns=['country'])
df4
⚠️ 踩坑:删列必须指定轴 ,用
columns=[...]最清晰;写drop('GDP')会默认按行找,找不到就报KeyError。
2.3 去重
去重用 drop_duplicates():
df_dup = df[['country']].copy()
# 按 country 去重,保留第一条
uniq = df_dup.drop_duplicates()
# 只按 country 去重,并保留最后一次出现的记录
uniq_last = df_dup.drop_duplicates(subset='country', keep='last')
# 查看去重后的国家数量
print(len(uniq))
三、改:替换数据
改的核心工具就是 replace(),它有两种作用域:全局 DataFrame 替换、单列 Series 替换。
3.1 单列直接改
df5 = df[:5].copy()
df5['c1'] = 23 # 整列覆盖为固定值
df5['GDP'] = [1, 23, 666666, -48, 6] # 整列覆盖为列表
# 单值替换:把 '美国' 换成 'usa'
df5['country'] = df5['country'].replace('美国', 'usa')
# 字典多值替换
df5['country'] = df5['country'].replace({
'英国': 'GB',
'法国': 'FR'
})
df5
3.2 全局 DataFrame 替换(多列多值)
# 写法1:inplace 修改原表
df5.replace({'country': {'日本': '岛国'}}, inplace=True)
# 写法2:一次性替换多个国家(推荐)
df6 = df[:5].copy()
df6 = df6.replace({
'country': {
'美国': 'usa',
'日本': '岛国',
'中国': 'cn',
'英国': 'GB',
'法国': 'FR'
}
})
df6
两种写法怎么选:
表格
| 写法 | 作用域 | 适用场景 |
|---|---|---|
df['col'].replace({旧:新}) |
单列 Series | 只改一列,逻辑简单,优先推荐 |
df.replace({'列': {旧:新}}) |
整个 DataFrame | 多列不同替换规则 |
⚠️ 重点踩坑:不要在单列上写
inplace=True!
df['country'].replace('美国', 'usa', inplace=True) # ❌ 警告!
df['country']返回的是中间副本,对它inplace根本改不到原表。Pandas 3.0 之后这种写法会直接失效 。 ✅ 正确姿势:赋值回去df['country'] = df['country'].replace('美国', 'usa')。
四、查:取数据 + 条件筛选
4.1 head / tail
df.head() # 默认前5条
df.tail(3) # 后3条
4.2 按列名取
df['year'] # 返回 Series(一维)
df.year # 点语法,同上(列名简单、不重名时可用)
df[['year']] # 返回 DataFrame(二维)
⚠️ 踩坑:
df['year']和df[['year']]差一个括号,返回类型完全不同 ------ 前者一维 Series,后者二维 DataFrame。点语法df.year遇到列名含空格 / 中文、或和size/count等内置方法重名时会出错,正式代码建议用df['year']。
4.3 按行取(切片 /loc/iloc)
print(df[:5]) # 前5行(位置切片)
print(df[1:5:2]) # 位置1、3 两行(步长2)
print(df[10::5]) # 从位置10到末尾,步长5
print(df.loc[0:2, :]) # 按【行标签】取 0~2 行(含端点)
print(df.iloc[0:2, :]) # 按【数字位置】取 0、1 两行(不含端点)
⚠️ 核心易错点:
df[]里传字符串 / 字符串列表 = 取列 ;传切片a:b= 取行。df[]的切片按行位置,不是行标签。df.loc[0:2]按标签取且含端点 ;df.iloc[0:2]按位置取且不含端点。2.x 下行标签恰好是 0、1、2... 时容易混,改了 index 后立马露馅。
4.4 query () 条件筛选(重点)
# 需求:中国、美国、日本 三国 2015~2019 年的数据
result = df.query(
"country in ['中国','美国','日本'] and (year >= 2015 and year <= 2019)"
)
result
query 多条件用法速查:
表格
| 需求 | 写法 |
|---|---|
| 并且(and) | "age > 18 and score > 80" |
| 并且(&) | "age > 18 & score > 80" |
| 或者 | "age == 18 or score > 88" |
| in 多值匹配 | "country in ['中国','美国']" |
| 引用外部变量 | "year >= @min_year" |
| 列名含空格 | "user age > 20"(反引号包裹) |
提示:query 里字符串常量要加引号 (
'中国'),数字不用;外部变量必须加@。query 返回新表,不会改原表,记得用变量接住。
五、全文速记(收藏版)
| 操作 | 一句话写法 |
|---|---|
| 增列 | df['c']=... 或 df=df.assign(c=...) |
| 删行 | df=df.drop(index=[0,2]) |
| 删列 | df=df.drop(columns=['col']) |
| 去重 | df=df.drop_duplicates(subset='col') |
| 改单列 | df['c']=df['c'].replace({旧:新}) |
| 改多列 | df=df.replace({'列':{旧:新}}) |
| 取前 N 行 | df.head(N) |
| 按列名取 | df['col'] / df[['col']] |
| 按位置取 | df.iloc[行, 列] |
| 按标签取 | df.loc[行, 列] |
| 条件筛选 | df.query("条件 and/or 条件") |
六、完整可运行源码
把下面这段存成 pandas_crud.py 直接跑,全部结论都能复现(记得把 CSV 路径换成你自己的):
import pandas as pd
# 0. 读数据
df = pd.read_csv('data/1960-2019全球GDP数据.csv', encoding='gbk')
# 1. 增
df2 = df[:5].copy()
df2['c1'] = 23
df2['c2'] = ['a', 'b', 'c', 'd', 'e']
df2['c3'] = df2['year'] * 2
df2 = df2.assign(c4=25000, c5=df2['year'] * 10)
# 2. 删
df4 = df[:10].copy()
df4 = df4.drop(index=[0, 2, 4])
df4 = df4.drop(columns=['GDP'])
uniq = df[['country']].drop_duplicates()
# 3. 改
df6 = df[:5].copy()
df6['country'] = df6['country'].replace({'中国': 'CN', '英国': 'GB'})
# 4. 查
result = df.query("country in ['中国','美国','日本'] and (year >= 2015 and year <= 2019)")
print(result)
如果对你有帮助,欢迎一键三连(点赞 + 收藏 + 关注)。 下期可以继续聊聊 groupby 聚合、merge 合并,或者把这份数据做成可视化。评论区告诉我你想看哪个方向,我来安排!