
【Pandas入门】3 天从 DataFrame 到窗口函数数据处理核心全掌握学 Pandas网上教程一大堆但看完还是不会写这篇文章用 3 天的学习路径从最基础的 DataFrame 创建到面试必考的窗口函数每一步都有实战代码和踩坑记录。一、先看问题假设你有一张员工表老板问你每个部门有多少人平均薪资多少→groupby agg找出每个部门薪资最高的员工→idxmax清洗手机号去掉横杠、提取邮箱域名→str 访问器计算每个员工的工龄年→dt 访问器每个部门内部按薪资排名→rank groupby找出薪资比前一名高 20% 的员工→shift这些问题光靠 Python 列表字典解决不了。你需要 DataFrame、apply/map、数据清洗、窗口函数——这就是 Pandas 数据处理的核心体系。二、第 1 天DataFrame 基础操作创建 / 查看 / 选择 / 类 SQL2.1 Series 和 DataFrame 创建importpandasaspd# ---------------------# Series 一维数据# ---------------------# 从列表创建s1pd.Series([1,2,3,4])# 从列表 索引创建s2pd.Series([1,2,3],index[a,b,c])# 从字典创建s3pd.Series({a:1,b:2})# ---------------------# DataFrame 二维数据# ---------------------# 从字典创建最常用df1pd.DataFrame({name:[张三,李四,王五,赵六],age:[25,30,28,35],salary:[15000,18000,16000,22000],department:[技术,技术,市场,市场]})# 从列表创建df2pd.DataFrame([[1,2,3],[2,3,4]],columns[a,b,c])# 从文件读取df3pd.read_csv(data.csv)df4pd.read_excel(data.xlsx)df5pd.read_sql(sql,connection)# 需要安装 sqlalchemy 和 psycopg22.2 数据查看快速了解数据# 查看前 5 行df.head()# 查看后 5 行df.tail()# 查看形状行数列数df.shape# 查看详细信息类型、非空值df.info()# 查看统计信息均值、最大最小等df.describe()# 查看列类型df.dtypes2.3 数据选择loc vs iloc重点列选择# 选择单列df[name]# 选择多列df[[name,age]]loc按标签选择# 选择所有行的 name 和 age 列df.loc[:,[name,age]]# 选择第 0 行的 name 列df.loc[0,name]# 切片左闭右闭包含第 2 行df.loc[0:2,name]iloc按位置选择# 选择所有行的第 1、2 列df.iloc[:,[1,2]]# 选择第 0 行第 0 列df.iloc[0,0]# 切片左闭右开不包含第 2 行df.iloc[0:2,0]2.4 类 SQL 操作WHERE / ORDER BY / GROUP BYWHERE 条件筛选# 单个条件df[df[age]30]# 多个条件注意 | 优先级低必须加括号df[(df[age]30)(df[salary]10000)]# 范围筛选df[df[salary].isin([15000,18000])]df[df[salary].between(10000,20000)]ORDER BY 排序# 降序df.sort_values(salary,ascendingFalse)# 多列排序df.sort_values([department,salary])GROUP BY 分组聚合# 简单分组每个部门平均薪资df.groupby(department)[salary].mean()# 多聚合命名聚合推荐df.groupby(department).agg(avg_salary(salary,mean),max_salary(salary,max),count(name,count))三、第 2 天数据清洗 窗口函数3.1 缺失值处理查看缺失值df.isna()# 检查每个值是否为空df.isnull()# 同上df.isna().sum()# 统计每列缺失值数量删除缺失值df.dropna()# 删除包含空值的行df.dropna(howall)# 只删除全为空的行df.dropna(subset[name,age])# 只检查 name 和 age 列填充缺失值df.fillna(0)# 所有空值填 0df.fillna({age:25,salary:10000})# 按列指定填充值df[salary].fillna(df[salary].mean())# 用均值填充3.2 重复值处理查找重复值df.duplicated()# 标记重复行第一次出现为 Falsedf.duplicated(subset[name],keeplast)# 检查 name 列最后一次出现为 Falsedf.duplicated(keepFalse)# 所有重复都标记为 True删除重复值df.drop_duplicates()# 删除重复行df.drop_duplicates(subset[name])# 根据 name 列去重3.3 类型转换# 直接转换df[age]df[age].astype(int)# 转换为日期df[hire_date]pd.to_datetime(df[hire_date])# 转换为数字df[salary]pd.to_numeric(df[salary])3.4 窗口函数核心窗口函数 对一组相关行做计算但不像 groupby 那样把行合并。3.4.1 排名函数# rank相同值排名相同跳过后续排名对应 SQL RANKdf[rank]df[salary].rank(methodmin,ascendingFalse)# 22000→1, 18000→2, 18000→2, 15000→4# dense_rank相同值排名相同不跳过对应 SQL DENSE_RANKdf[dense_rank]df[salary].rank(methoddense,ascendingFalse)# 22000→1, 18000→2, 18000→2, 15000→3# row_number每个值唯一排名对应 SQL ROW_NUMBERdf[row_number]df[salary].rank(methodfirst,ascendingFalse)# 22000→1, 18000→2, 18000→3, 15000→4三种排名的区别面试必考函数22000180001800015000特点rank1224重复跳号dense_rank1223重复不跳号row_number1234不重复不跳号3.4.2 分组排名# 每个部门内部独立排名df[dept_rank]df.groupby(department)[salary].rank(methoddense,ascendingFalse)3.4.3 位移函数shift对应 SQL LAG / LEAD# lag前一行df[prev_salary]df.groupby(department)[salary].shift(1)# lead后一行df[next_salary]df.groupby(department)[salary].shift(-1)3.4.4 累计聚合df[cum_sum]df[salary].cumsum()# 累计和df[cum_max]df[salary].cummax()# 累计最大值df[cum_min]df[salary].cummin()# 累计最小值3.4.5 滚动窗口df[rolling_mean]df[salary].rolling(3).mean()# 最近 3 行均值3.4.6 分组找最大最小行idxmax / idxmin# 找到每组薪资最高的行idx_maxdf.groupby(department)[salary].idxmax()df_max_salarydf.loc[idx_max]四、第 3 天apply / map 字符串 / 日期处理4.1 apply vs map vs applymap核心方法适用对象作用返回值map()Series一对一映射Seriesapply()Series/DataFrame应用函数Seriesapplymap()DataFrame逐元素应用DataFramemap() 用法# 字典映射df[gender_cn]df[gender].map({M:男,F:女})# 函数映射df[age_group]df[age].map(lambdax:青年ifx30else中年)apply() 用法# 用于 Seriesdf[salary_k]df[salary].apply(lambdax:f{x/1000}k)# 用于 DataFrameaxis1 按行处理df[info]df.apply(lambdarow:f{row[name]}({row[age]}岁),axis1)# 自定义函数defcalculate_bonus(row):bonusrow[salary]*0.1ifrow[performance]A:bonus*1.2returnint(bonus)df[bonus]df.apply(calculate_bonus,axis1)applymap() 用法注意pandas 3.x 改为 map()# 旧版本df.applymap(lambdax:x*2)# 新版本兼容写法df.apply(lambdacol:col.map(lambdax:x*2))# 或者直接用 map()df.map(lambdax:x*2)4.2 字符串处理.str 访问器基础操作df[email].str.upper()# 全大写df[email].str.lower()# 全小写df[email].str.title()# 首字母大写df[name].str.len()# 字符串长度查找匹配df[email].str.contains()# 是否包含df[email].str.startswith(zhang)# 开头df[email].str.endswith(.com)# 结尾df[email].str.count(a)# 统计出现次数df[email].str.find()# 查找位置df[email].str.match(r^[a-z])# 正则匹配提取分割df[email].str.split().str[0]# 分割后取第一部分用户名df[email].str[:5]# 切片df[email].str.extract(r(.*)(.*))# 正则提取替换df[phone].str.replace(-,)# 替换df[phone].str.replace(r\D,,regexTrue)# 正则替换去掉所有非数字s.str.strip()# 去两端空格4.3 日期处理.dt 访问器提取日期部分df[hire_date].dt.year# 年df[hire_date].dt.month# 月df[hire_date].dt.day# 日df[hire_date].dt.day_of_week# 星期几0周一df[hire_date].dt.day_name()# 星期几名称df[hire_date].dt.quarter# 季度df[hire_date].dt.day_of_year# 一年中的第几天提取时间部分df[login_time].dt.hour# 小时df[login_time].dt.minute# 分钟df[login_time].dt.second# 秒日期计算todaypd.Timestamp(2024-01-01)# 日期差df[days_since_hire](today-df[hire_date]).dt.days# 日期加减df[hire_date]pd.Timedelta(days30)# 加 30 天df[hire_date]pd.offsets.DateOffset(months3)# 加 3 个月推荐日期格式化df[hire_date_cn]df[hire_date].dt.strftime(%Y年%m月%d日)五、踩坑记录大全坑 1pandas 版本差异applymap 不见了错误信息DataFrame object has no attribute applymap 原因pandas 3.x 版本移除了 applymap()改用 map() 解决方法 # 兼容写法 df.apply(lambda col: col.map(lambda x: x 1)) # 或直接用 df.map(lambda x: x 1)坑 2DateOffset 性能警告警告PerformanceWarning: Non-vectorized DateOffset being applied to Series or DatetimeIndex 原因直接用 pd.DateOffset() 效率低 解决方法 df[hire_date] pd.offsets.DateOffset(months3) # 注意是 offsets且 months 复数坑 3SQLAlchemy 还需要 psycopg2错误信息需要安装 psycopg2 才能连接 PostgreSQL 原因只安装了 sqlalchemy没安装数据库驱动 解决方法pip install psycopg2-binary坑 4apply 里日期计算误用 .dt错误在用 apply 处理单个日期值时误用 .dt 原因apply 传入的是单个值不是 Series不能用 .dt 解决方法 def calc_years(date_val): return (pd.Timestamp(2026-05-31) - date_val).days // 365 # 直接用 days df[years] df[hire_date].apply(calc_years)坑 5idxmax 返回索引不是值坑idxmax() 返回的是索引标签不是值 解决方法用 loc 取行 idx_max df.groupby(department)[salary].idxmax() df_max df.loc[idx_max]坑 6多条件优先级 | 优先级低坑 和 | 优先级比比较运算符低 解决方法每个条件都要加括号 df[(df[age] 30) (df[salary] 10000)]坑 7f-string 引号问题错误f-string 里用单引号外面也用单引号 解决方法交替使用 df.apply(lambda x: f{x[name]}({x[age]}), axis1)六、3 天学习路径总结天主题核心技能重点Day 14DataFrame 基础Series/DataFrame 创建 / loc/iloc / 类 SQLloc vs ilocDay 15数据清洗 窗口函数缺失值/重复值/类型转换 / rank/shift/idxmax窗口函数Day 16apply/map 字符串/日期apply/map 对比 / .str / .dtapply axis1七、Pandas 核心能力速查表数据查看方法说明head()查看前 5 行tail()查看后 5 行shape查看形状info()查看信息describe()查看统计数据清洗方法说明isna()检查空值dropna()删除空值fillna()填充空值duplicated()检查重复drop_duplicates()删除重复数据选择方法说明loc[]按标签选择iloc[]按位置选择isin()包含判断between()范围判断分组聚合方法说明groupby()分组agg()多聚合idxmax()最大值索引窗口函数方法说明rank()排名shift()位移cumsum()累计和rolling()滚动窗口字符串处理方法说明str.upper()大写str.contains()包含str.split()分割str.replace()替换日期处理方法说明dt.year年dt.month月dt.day日Timedelta日期间隔 下一步数据透视表pivot_table 正则表达式从会处理数据到会分析数据。