大模型面试题13:pandas的基本操作
view()仅适用于连续张量,非连续需先;返回视图,修改会影响原张量;bmm无广播,批量矩阵相乘需保证batch数一致;dot对高维张量会展平,优先用matmul替代。
·
二、Pandas 核心操作(全面深度版)
(一)数据创建(全场景覆盖)
import pandas as pd
import numpy as np
# 1. 从字典创建(最常用)
df = pd.DataFrame({
'id': [1,2,3,4],
'name': ['Alice','Bob','Charlie','David'],
'score': [85.5, 90.0, np.nan, 78.0],
'class': ['A','B','A','B'],
'date': pd.date_range('2025-01-01', periods=4)
}, index=['a','b','c','d']) # 自定义索引
# 2. 从numpy数组创建
arr = np.array([[1,2],[3,4]])
df_arr = pd.DataFrame(arr, columns=['col1','col2'], index=['row1','row2'])
# 3. 从文件创建(实战核心)
df_csv = pd.read_csv('data.csv', sep=',', header=0, na_values=['NA', '缺失']) # CSV
df_excel = pd.read_excel('data.xlsx', sheet_name='Sheet1', usecols=['id','score']) # Excel
df_json = pd.read_json('data.json') # JSON
# 4. 空DataFrame
df_empty = pd.DataFrame(columns=['col1','col2'])
(二)数据探索(全方位分析)
# 1. 基础信息
df.info() # 列类型、非空值、内存占用
df.describe(include='all') # 数值列统计+类别列频次(include='all')
df.shape # (行数, 列数)
df.columns # 列名列表
df.index # 索引列表
# 2. 缺失值分析
df.isnull().sum() # 每列缺失值数量
df.isnull().mean() # 每列缺失值比例
df.notnull().sum() # 每列非空值数量
# 3. 类别列分析
df['class'].value_counts() # 频次统计(降序)
df['class'].value_counts(normalize=True) # 占比
df['class'].unique() # 唯一值列表
df['class'].nunique() # 唯一值数量
# 4. 数值列分析
df['score'].mean() # 均值
df['score'].median() # 中位数
df['score'].std() # 标准差
df['score'].min()/df['score'].max() # 最小/最大值
df['score'].quantile([0.25, 0.5, 0.75]) # 分位数
df.corr(numeric_only=True) # 数值列相关性矩阵
(三)索引操作(高级用法)
# 1. 设置/重置索引
df_idx = df.set_index('id') # 以id列为索引
df_idx = df_idx.reset_index() # 重置为默认整数索引(id变回列)
df_idx = df.reset_index(drop=True) # 重置索引并删除原索引列
# 2. 多级索引(分层索引)
df_multi = df.set_index(['class', 'id']) # 先class后id
df_multi.loc['A'] # 取class=A的所有行
df_multi.loc[('A', 1)] # 取class=A且id=1的行
# 3. 索引重命名/排序
df.index.rename('row_label', inplace=True) # 索引重命名
df.sort_index(ascending=False) # 按索引降序排序
df.sort_index(level='class', ascending=True) # 多级索引按class排序
(四)数据筛选(极致全面)
# 1. 基础列筛选
df[['name','score']] # 选多列
df.drop(['class'], axis=1) # 删除列
# 2. 行筛选(布尔索引)
df[df['score'] >= 80] # 分数≥80
df[(df['class'] == 'A') & (df['score'] > 80)] # class=A且分数>80(&:且,|:或,~:非)
df[df['name'].isin(['Alice','Bob'])] # 名字在列表中
df[df['score'].between(75, 90)] # 分数在75-90之间
df[df['name'].str.contains('li')] # 名字包含'li'(文本筛选)
# 3. 高级筛选(query/filter)
df.query('class == "A" and score > 80') # 字符串表达式筛选(更简洁)
df.filter(items=['name','score']) # 按列名筛选
df.filter(regex='^s') # 按列名正则筛选(以s开头)
df.filter(like='co') # 按列名包含'co'筛选
# 4. loc/iloc高级用法
df.loc[df['score'].notnull(), ['name','score']] # 非空分数的姓名和分数
df.iloc[::2, [0,2]] # 行步长2,列0和2
df.loc['a':'c', 'name':'score'] # 标签切片(左闭右闭)
df.iloc[0:3, 1:3] # 位置切片(左闭右开)
(五)数据修改(全场景)
# 1. 列值修改
df['score'] = df['score'].fillna(df['score'].mean()) # 填充缺失值为均值
df['score_level'] = df['score'].apply(lambda x: 'Pass' if x >= 80 else 'Fail') # 新增等级列
df['name'] = df['name'].str.upper() # 名字转大写
# 2. 替换值
df['class'] = df['class'].replace({'A':'Class A', 'B':'Class B'}) # 替换类别
df.replace(np.nan, 0, inplace=True) # 所有缺失值替换为0
# 3. 列重命名
df.rename(columns={'score':'math_score', 'name':'full_name'}, inplace=True)
# 4. 类型转换
df['score'] = df['score'].astype('int64') # 浮点转整数
df['date'] = pd.to_datetime(df['date']) # 字符串转日期
df['class'] = df['class'].astype('category') # 转类别型(节省内存)
# 5. 批量修改(apply/applymap/map)
df[['score']] = df[['score']].apply(lambda x: x*1.1) # 分数加10%
df.applymap(lambda x: x.strip() if isinstance(x, str) else x) # 所有字符串去空格
df['score_level'] = df['score_level'].map({'Pass':1, 'Fail':0}) # 类别映射为数值
(六)缺失值处理(高级策略)
# 1. 填充策略
df['score'].fillna(df['score'].mean(), inplace=True) # 均值填充
df['score'].fillna(df.groupby('class')['score'].transform('mean'), inplace=True) # 分组均值填充
df['score'].ffill(inplace=True) # 向前填充(用上一行值)
df['score'].bfill(inplace=True) # 向后填充(用下一行值)
df['score'].interpolate(method='linear', inplace=True) # 线性插值填充
# 2. 删除策略
df.dropna(axis=0, how='all') # 删除全为缺失值的行
df.dropna(axis=0, how='any', subset=['score']) # 删除score列有缺失的行
df.dropna(thresh=3) # 保留至少3个非空值的行
# 3. 标记缺失值
df['score_missing'] = df['score'].isnull().astype(int) # 新增列标记是否缺失
(七)分组聚合(高级用法)
# 1. 基础分组聚合
df_group = df.groupby('class')['score'].agg(['sum','mean','max','min']).reset_index()
df_group.columns = ['class','total_score','avg_score','max_score','min_score'] # 重命名聚合列
# 2. 命名聚合(清晰可控)
df_group = df.groupby('class').agg(
总分=('score', 'sum'),
平均分=('score', 'mean'),
人数=('id', 'count')
).reset_index()
# 3. 分组过滤
df_filtered = df.groupby('class').filter(lambda x: x['score'].mean() >= 80) # 保留平均分≥80的班级
# 4. 分组转换(保留原行数)
df['class_avg_score'] = df.groupby('class')['score'].transform('mean') # 新增列:班级平均分
df['score_diff'] = df['score'] - df['class_avg_score'] # 分数与班级平均分的差值
# 5. 多级分组
df_multi_group = df.groupby(['class', pd.Grouper(key='date', freq='M')])['score'].mean() # 按班级+月份分组
(八)合并与拼接(全类型)
# 1. 合并(merge):按列关联(类似SQL JOIN)
df1 = pd.DataFrame({'id': [1,2,3], 'math': [85,90,78]})
df2 = pd.DataFrame({'id': [1,2,4], 'english': [92,88,75]})
# 内连接(仅保留匹配行)
df_inner = pd.merge(df1, df2, on='id', how='inner') # id=1,2
# 左连接(保留左表所有行)
df_left = pd.merge(df1, df2, on='id', how='left') # id=1,2,3(english列id=3为NaN)
# 右连接(保留右表所有行)
df_right = pd.merge(df1, df2, on='id', how='right') # id=1,2,4(math列id=4为NaN)
# 外连接(保留所有行)
df_outer = pd.merge(df1, df2, on='id', how='outer') # id=1,2,3,4
# 2. 拼接(concat):按行/列堆叠
df3 = pd.DataFrame({'id': [5,6], 'math': [88,92]})
df_row = pd.concat([df1, df3], axis=0, ignore_index=True) # 行拼接(重置索引)
df_col = pd.concat([df1, df2.set_index('id')], axis=1).reset_index() # 列拼接
# 3. 追加(append):行拼接简化版(pandas 2.0后推荐用concat)
df_append = df1.append(df3, ignore_index=True)
(九)排序与排名
# 1. 按值排序
df.sort_values(by=['class','score'], ascending=[True, False], inplace=True) # 按班级升序、分数降序
# 2. 按索引排序
df.sort_index(ascending=False, inplace=True)
# 3. 排名
df['score_rank'] = df['score'].rank(method='min', ascending=False) # 分数排名(min:相同分数取最小排名)
# method可选:min/max/avg/first(按出现顺序)
(十)透视表与交叉表
# 1. 透视表(pivot_table):行/列/值/聚合
df_pivot = pd.pivot_table(
df,
values='score',
index='class',
columns='score_level',
aggfunc='mean',
fill_value=0 # 缺失值填充为0
)
# 2. 交叉表(crosstab):计数统计
df_crosstab = pd.crosstab(
df['class'],
df['score_level'],
margins=True, # 总计行/列
normalize='index' # 按行归一化(占比)
)
(十一)窗口函数(实战核心)
# 1. 滚动窗口(rolling)
df['score_rolling_mean'] = df['score'].rolling(window=2).mean() # 2期滚动均值
df['score_rolling_max'] = df['score'].rolling(window=3, min_periods=1).max() # 3期滚动最大值(至少1个值)
# 2. 指数加权窗口(ewm)
df['score_ewm'] = df['score'].ewm(alpha=0.2).mean() # 指数加权均值(alpha=权重)
# 3. 扩展窗口(expanding)
df['score_expanding_sum'] = df['score'].expanding(min_periods=1).sum() # 累计和
(十二)文本与时间序列处理
1. 文本处理(str访问器)
df['name'] = df['name'].str.strip() # 去空格
df['name_length'] = df['name'].str.len() # 名字长度
df['name_split'] = df['name'].str.split(' ') # 拆分字符串
df['name_first_char'] = df['name'].str[0] # 取第一个字符
df['name_contains'] = df['name'].str.contains('A', case=False) # 包含A(忽略大小写)
df['name_replace'] = df['name'].str.replace('li', 'LI') # 替换子串
2. 时间序列(dt访问器)
# 日期解析
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')
# 日期属性提取
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['weekday'] = df['date'].dt.weekday # 星期几(0=周一)
df['is_month_end'] = df['date'].dt.is_month_end # 是否月末
# 重采样(resample)
df_resample = df.resample('M', on='date')['score'].mean() # 按月重采样求均值
# 时间偏移
df['date_plus_7d'] = df['date'] + pd.Timedelta(days=7) # 加7天
df['date_plus_1m'] = df['date'] + pd.DateOffset(months=1) # 加1个月
(十三)数据导出
# 导出为CSV
df.to_csv('output.csv', index=False, encoding='utf-8', na_rep='NA')
# 导出为Excel
df.to_excel('output.xlsx', sheet_name='Sheet1', index=False)
# 导出为JSON
df.to_json('output.json', orient='records')
# 导出为numpy数组
arr = df.to_numpy()
三、核心避坑总结
Torch 避坑
view()仅适用于连续张量,非连续需先contiguous();transpose/permute返回视图,修改会影响原张量;bmm无广播,批量矩阵相乘需保证batch数一致;dot对高维张量会展平,优先用matmul替代。
Pandas 避坑
inplace=True直接修改原数据,无返回值;- 布尔索引中
and/or需替换为&/|,且条件需加括号; merge时列名不同需用left_on/right_on;- 时间序列需先解析为
datetime类型再操作; - 类别型数据用
astype('category')可大幅节省内存。
以上内容覆盖了Pandas从基础到进阶的全场景操作,包含详细规则、示例、边界案例和避坑指南,可直接落地到实战场景中。
更多推荐



所有评论(0)