ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Pandas进阶实战:数据类型转换与文件读写全攻略

Pandas进阶实战:数据类型转换与文件读写全攻略 1. 先搞清楚这一篇到底在讲什么先说个结论pandas学到“基础三”这个阶段重点已经不是“pandas是什么”或者“DataFrame怎么创建”而是怎么把一个又脏又乱的原始表格变成能干净计算、能导出、能画图的状态。前两篇基础讲的是看数据、选数据这篇讲的是改数据、存数据、画数据前后差别很大。这里的“脏”不只是缺失值和重复行还包括列的类型不对、日期格式混乱、字符串里夹着数字这些看起来特别微观的问题。恰恰是这些问题卡住了绝大多数刚学完基础二的人。这篇内容适合三类人正在在线实训平台刷“pandas初体验”“pandas数据结构创建”“pandas读写文本文件”这类关卡刚做完前两关但对第三关无从下手的同学已经能写简单pandas代码但一遇到类型转换或文件读写的报错就要查半天的人以及环境装了三天都装不上、只想赶紧看到代码跑起来的学习者。下面所有关键点我都会顺手解释一句“为什么这么做”而不是扔一堆参数让你硬背。1.1 基础一、基础二没掌握的话基础三会非常吃力不是我吓唬人。基础三默认你已经具备三个能力能创建DataFrame、能通过列名选中一列或多列、能使用布尔索引做条件筛选。如果你连df[df[score] 80]这种写法都要现查建议把前两篇先练熟不然这一篇里“先筛选再转换”“筛选完重置索引”的连环操作会让你看得很累甚至产生“我怎么全不会”的错觉。更关键的是前两篇的大多数操作是“只读”的比如筛选、布尔判断、查看缺失值这些操作不会改变原表。基础三完全不同大量操作是“写入”的最典型的就是df[col] df[col].astype(float)。这一行会真实地改变这一列的类型不留神就把原始数据覆盖了。这种“有没有赋值回去”的区别是基础三阶段最需要形成肌肉记忆的第一件事。1.2 装pandas这件事仍然卡着一大批人别笑安装简单但安装失败的理由千奇百怪。最常见的是在PyCharm的Terminal里执行pip install pandas半天后报错Could not find a version that satisfies the requirement pandas (from versions: none)。99%的情况是pip默认访问的官方源在国内网络环境下载不了换成清华源一行命令就能解决pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple如果还提示no matching distribution found那就要检查两件事pip版本是不是太旧以及你的Python版本和pandas版本是否匹配。先执行python -m pip install --upgrade pip再装一次基本能解决大半问题。还有一种场景也高频出现有人在ArcGIS Pro这种自带Python环境的软件里想用pandas却import失败。这种集成软件往往自带一套独立的Python解释器系统Python里装的包它看不到需要你在ArcGIS Pro自己的Python包管理器里装或者手动指定解释器路径。这个问题和PyCharm里“右侧解释器选错”本质一样。至于手机Python装pandas我的态度很明确能装就装装不上别死磕。pandas带C扩展手机环境普遍缺少编译工具折腾成本极高。真想练习就开一个在线Python环境或者回到电脑上这才符合实际开发节奏。1.3 到基础三你要在脑子里建立一条数据流水线把视角拉高一点。基础三阶段你再处理一个文件心里应该有一条流水线读取文件接着打印df.info()看列名和类型然后做类型转换和清洗再按业务逻辑筛选、排序、去重最后画图或者导出文件。这条流水线前一步的产物是后一步的输入缺失任何中间环节后面都会返工。为什么强调这件事因为很多人在学基础三时会陷入“收集命令”的误区今天记一个drop_duplicates明天抄一个to_datetime感觉自己学了好多但真拿到一份乱糟糟的Excel时完全不知道从哪下手。真正有用的不是命令清单而是顺序感——先看类型再决定转不转、怎么转转完之后才谈得上分析和导出。这一篇的章节顺序就是按这条真实加工链路排的。2. 数据类型转换绕不开的三板斧在pandas基础三阶段类型转换是出现频率最高的操作。场景往往是这样你用read_csv读进来一个“销售额”列dtypes一看是object直接sum()得到一串数字拼在一起的文本或者你拿到一个“2024年5月1日”形式的日期列它实际上是字符串排序时按字典序排得乱七八糟。这些问题的本质都一样pandas把数据按“看起来的样子”存了而我们要按“实际应该是什么”来用。日常80%的类型转换需求其实落在三个函数上astype、pd.to_numeric、pd.to_datetime外加一个字符串专用通道str。把它们逐个讲透比背二十个冷门参数有用。2.1 astype强制转换但要求数据足够干净astype是看起来最“硬核”的转换工具直接把一列转成指定类型df[age] df[age].astype(int) df[score] df[score].astype(float) df[city] df[city].astype(category)转数值型是它的常规用法category类型倒被很多人忽视。当你的数据里某个文本列只有几种取值比如城市名只有十几个转成category后底层按整数存储内存占用能降不少。如果你在处理几十万行级别的数据这个优化是立竿见影的。astype最需要记住的坑有两个。第一个它返回的是一个副本不会直接修改原DataFrame。必须写赋值df[col] df[col].astype(float)直接写df[col].astype(float)不管结果列不会有任何变化。这是新手最容易忽视的一条。第二个坑更致命astype遇到脏数据直接抛异常。比如这一列里混进一个“不详”整列转换直接中断后面的代码全不执行。所以astype只适合你已经确认数据足够干净的场景。如果你没把握更稳妥的方案是下一小节要说的pd.to_numeric。2.2 pd.to_numeric清洗脏数字的默认武器和astype的“一刀切”不同pd.to_numeric更像一个“宽容派”。它专门用来处理“看起来是数字实际上不是纯数字”的列。比如单元格里写着“1,200.00”“800元”“N/A”这些内容用astype一个都过不去但to_numeric能配合errors参数把其中能转的转掉转不了的置成NaN。errors参数有三个取值raise是默认值遇到非法内容直接抛错coerce会把转不过去的变成NaNignore则留着原样返回整列。日常使用我几乎只碰coercedf[amount] pd.to_numeric(df[amount], errorscoerce)转完以后紧跟着做一件关键的事把NaN筛出来看。因为这些NaN位置就是脏数据的藏身之处print(df[df[amount].isna()])这个“先转换再排查NaN”的思路比一开始就在源文本里各种replace来清洗高出不知道多少倍。它不用你预判脏数据长什么样只需要转完看一眼就知道哪些行需要人工处理是删是改一目了然。我处理报表时遇到金额列混着“-”“不详”“N/A”这套流程是默认进场动作没有之一。2.3 pd.to_datetime日期时间列的正确打开方式日期转换是基础三里最容易被轻视的一环。原因很好理解一个“2024/5/1”看着就是日期你觉得pandas肯定能读懂。大部分情况下它确实能读懂但有一种情况会出大问题那就是“01/05/2024”这种格式。pandas自动推断时很可能把日当成月、月当成日也就是按美式习惯解析结果你的2024年5月1日就变成了2024年1月5日。这种错误相当隐蔽因为代码不报错、结果也能跑直到画图时趋势线完全错乱你才会回头怀疑是日期顺序反了。所以我的建议是遇到非标准格式用format参数明说df[date] pd.to_datetime(df[date], format%d/%m/%Y)%d/%m/%Y表示“日月年”。常用格式无非%Y-%m-%d、%d/%m/%Y、%Y/%m/%d %H:%M:%S这些记不牢就查表重要的是养成“转换后打印head()看一眼”的习惯别相信自动解析也别相信肉眼。日期转换的价值不止于“格式好看”。一旦列变成datetime64类型你就能用.dt访问器提取各种衍生字段df[year] df[date].dt.year df[weekday] df[date].dt.dayofweek df[month] df[date].dt.month拿月份字段做分组汇总是后续做月度趋势分析最常见的操作。时间列不转这些全免谈。2.4 str通道批量字符串清洗的日常操作字符串处理和类型转换看起来不搭边但本质是一回事把“不适合计算”的列变成“适合计算”的列。这里的主角是.str访问器它让整个Series像一串字符串对象一样批量操作。最常用的几个操作包括df[name].str.strip()去掉首尾空格df[city].str.contains(北京)返回布尔Series配合条件筛选df[phone].str.startswith(189)做手机号段筛选以及str.replace配合正则表达式做批量清理df[phone] df[phone].str.replace(r\D, , regexTrue)这一行把电话列里所有非数字字符删光只剩11位号码。类似场景很多比如从地址里抽邮编、从备注里抠金额都是先replace清理再to_numeric转换。字符串通道同样返回新对象记得接住返回值。我遇到过一个很典型的坑某份客户名单从Excel导入后包括列名在内的很多单元格都带着全角空格或不可见字符导致df[城市] 北京怎么筛都是False。最后用df.columns df.columns.str.strip()清掉列名空格再对城市列做strip问题立刻消失。这种问题你不会在日常练习中遇到但面对真实数据时几乎无法避免。3. 数据结构创建与重塑索引才是底层逻辑热词里“pandas数据结构创建”出现频率很高但基础三阶段再提创建重点已经不是“怎么建一个DataFrame”而是“索引是怎么影响你后续所有运算的”。这一节把创建、排序、去重和重置索引放在一起讲因为它们共用同一套底层逻辑索引决定了pandas怎么对齐数据和运算结果。3.1 创建Series和DataFrame时最容易忽略的索引顺序pandas有一个底层特性叫“数据对齐”大白话说就是两个Series做加减乘除时它们不按位置对齐而是按索引标签对齐。这在处理乱序数据时很强大但对新人来说极其容易懵。看这个例子s1 pd.Series([10, 20, 30], index[a, b, c]) s2 pd.Series([1, 2, 3], index[c, b, a]) print(s1 s2)结果不是按位置计算得到[12, 22, 33]而是按标签配对a和a加、b和b加、c和c加最终结果索引是a, b, c值分别是11, 22, 33。明白这点以后你再看合并两个DataFrame之后顺序乱掉、筛选后索引断裂导致运算出现一堆NaN就不会抓狂了。DataFrame创建时也有一个容易忽视的点如果你用“列表里放字典”的方式创建列的顺序严格按第一个字典的键顺序但如果你直接用numpy数组创建pandas根本不知道每列该叫什么名字只能手动指定columns。在线平台上很多“数据结构创建”类题目考的往往不是创建本身而是创建后你能不能正确索引和运算。3.2 排序、去重之后为什么多数情况都要reset_indexsort_values排序很简单记得升序降序用ascending控制多列排序时传一个列表比如df.sort_values([date, amount])它会先按date排再按amount排。drop_duplicates去重时需要关注subset参数它决定按哪些列判断重复df.drop_duplicates(subset[date, user_id], keepfirst)这行的意思是“同一天同一个用户只保留第一条记录”。如果你不写subset它会看整行是否完全重复很多时候未必是你想要的。真正容易出事的环节是索引。筛选、排序、去重之后DataFrame的索引往往变成0、3、5、7这种不连续的样子。如果你不处理直接拿它去和其他数据运算pandas会按这个残缺的索引去匹配匹配不上的位置全部是NaN。解决办法就一行df df.reset_index(dropTrue)dropTrue特别重要不写的话旧索引会被保留成一行叫index的新列很多时候你根本不需要它。我在实训里见过不少同学明明数据就几行导出的文件里却多出一列“index”就是忘记加dropTrue。3.3 apply与applymap自定义逻辑的入口pandas内置方法再多总有覆盖不到的自定义逻辑。这时候apply是万能备胎。它可以沿指定轴将一个函数应用到每一行或每一列。比如把华氏温度列转成摄氏温度def to_celsius(f): return (f - 32) * 5 / 9 df[celsius] df[fahrenheit].apply(to_celsius)简单逻辑也能写lambdadf[celsius] df[fahrenheit].apply(lambda x: (x-32)*5/9)。如果逻辑更复杂传一个带if、for的自定义函数完全没问题。但要记住一个社区共识apply的性能远不如向量化运算。能用df[col] * 2实现的需求绝对不要写成df[col].apply(lambda x: x*2)。apply的存在是为了兜底不是用来替代正常运算的。applymap则作用在整个DataFrame上对所有元素应用同一个函数比如把数值统一格式化成百分比字符串。基础三阶段知道有它就行日常使用频率不算高。4. 文件读写read_csv到to_excel成败都在细节里文件读写是数据“进硬盘、出硬盘”的环节也是热词里“pandas读写文本文件”反复被搜的原因。很多人以为read_csv就是把文件读进来实际上决定成败的全是参数细节。这一节把csv和Excel两大类读写讲透。4.1 read_csv编码、分隔符、日期解析三大高频参数读csv能不能跑通最先影响成败的不是列名而是编码。国内环境从Excel导出的csv很多是GBK编码直接pd.read_csv(file.csv)大概率抛UnicodeDecodeError加上encodinggbk就通了。如果文件是从系统导出的往往是utf-8不确定时可以先拿记事本打开看一眼中文不乱码就说明当前编码判断没错。第二个高频参数是sep。都知道“csv是逗号分隔”但实际生产环境的csv可能用分号、制表符甚至竖线做分隔符。不指定seppandas只会按逗号切整列数据会被揉成一团那是真头大。第三个是parse_dates读取的同时直接把时间列解析成datetime类型省得事后用to_datetime再转一次。顺带还可以用usecols只读特定列对大文件来说能显著省内存。把这些合起来一个典型的读取语句长这样df pd.read_csv( sales.csv, encodinggbk, sep,, parse_dates[日期], usecols[日期, 金额] )一行读取直接跳过了一半的类型转换问题。写csv也有两个固定习惯to_csv时加indexFalse否则索引会被写进文件第一列导出给同事用Excel打开时加encodingutf-8-sig否则中文在Excel里会乱码。这两个参数组合是我给业务方导出文件前的固定动作。4.2 读写Excelsheet、索引和ExcelWriterExcel读写比csv多一层“sheet”的概念。读的时候很容易忽略sheet_name参数不指定就默认读第一个sheet。文件里如果恰好有多个sheet且你要的不是第一个数据全错而且不会报错提醒你。写Excel时to_excel默认会把DataFrame的索引写成一列所以同样要indexFalse。想把多个DataFrame写进同一个Excel的不同sheet用ExcelWriter是最干净的方式with pd.ExcelWriter(report.xlsx) as writer: df_summary.to_excel(writer, sheet_name汇总, indexFalse) df_detail.to_excel(writer, sheet_name明细, indexFalse)这个写法会自动创建文件并把两个sheet写进去比先写一个再openpyxl拼来拼去省事太多。有一点提醒如果要在已有文件上追加sheet有的pandas版本需要给ExcelWriter传modea默认的modew会覆盖原文件。旧版pandas甚至不支持modea遇到这种需求第一反应是升级pandas而不是硬折腾。4.3 多文件合并concat比循环追加靠谱当你要合并十几份同结构csv比如每个月一个销售文件最省心的方案不是用循环一次次往一个空DataFrame里append而是先收集全部DataFrame再一次concatimport glob files glob.glob(data/2024_*.csv) frames [pd.read_csv(f) for f in files] df_all pd.concat(frames, ignore_indexTrue)concat默认纵向拼接也就是把行堆叠起来。ignore_indexTrue表示拼接后重新生成0到n-1的连续索引这个参数极其重要不写的话合并结果会带着一堆重复的旧索引给后续操作埋雷。如果要做横向拼接传axis1这时要特别小心两边行的顺序是否一致最稳妥的做法是都按同一列排序后再拼。现在处理多份同结构数据我基本都是这个套路又快又不容易错。5. pandas与matplotlib的配合练习pandas和matplotlib是老搭档。一个负责把数据整理得服服帖帖一个负责把结果画出来。基础三阶段你不需要掌握很复杂的绘图甚至不需要专门系统地学matplotlib用好DataFrame自带的plot()方法就能覆盖大部分日常图表。5.1 用plot()快速出折线图和柱状图DataFrame.plot()默认画折线图。你把一个带索引的Series或DataFrame直接调用再配一行plt.show()图就出来了。举一个例子按月汇总销售额后得到一个月度和金额的DataFrame直接df.plot()就是一张趋势折线图。有一个极常见的坑pandas本身不显示图片它只是构建了matplotlib的底层对象必须调用plt.show()才能弹出窗口或者用plt.savefig(figure.png)保存成文件。我第一次跑图时代码没报错但窗口什么都不弹查了半天才发现是忘了plt.show()。柱状图也很简单给plot加一个kindbar参数就行比如按“客户类型”分组后的销量对比一眼就能看出哪个组最高。在在线练习里这类题多半要求你把处理好的分组结果画出来核心其实在前面那步“分组聚合”画图只是收尾。5.2 hist与boxplot数据分布一眼看透描述数据的分布看表格里的均值、方差远不如看直方图直观。df[price].hist()能把价格字段的分布画成直方图异常值会在右侧拖出长尾或者在某几个区间突然堆积肉眼一秒就能发现。这个能力在做数据质量检查时非常好用。箱线图boxplot则适合比较多组数据的分布比如不同城市价格分别长什么样。它用四分位数把数据的分布区间画出来超出箱体范围的异常值会单独排在一边清洗数据时拿着这个图去定位异常记录效率很高。基础三阶段我建议先把hist用熟boxplot知道怎么调出来就行。这两张图对应着“单列分布”和“分组分布”两种最常见的观察需求足够应付绝大多数报告场景。5.3 画图前必须确认的三个前提画图本身很少出错出错大多是在前面的数据处理环节。我总结了三个反复踩的点。第一列类型没转好。时间列还是字符串就画x轴横轴全是乱序文本数值列没转成float图上的线可能变成只有0和1两个取值。这件事再次印证了第2章的重要性类型转换没做好画出来的图都是错的。第二索引混乱。筛选、去重后忘了reset_index图表的x轴会莫名其妙出现断点因为索引不连续。解决方案还是那句处理完数据记得reset_index(dropTrue)。第三中文显示问题。matplotlib默认字体没有中文字符坐标轴标题、图例凡是中文全变成方块。临时解决方案是设置中文字体比如plt.rcParams[font.sans-serif] [SimHei]或者干脆把图表标题、坐标轴标签写成英文。每次画图前我的习惯是先df.info()看一眼各列类型确认都正常再动手。这习惯帮我避免了很多低级返工。6. 常见问题排查与个人避坑速查最后把基础三阶段最高频的问题整理成速查形式。这些不是从文档里抄来的是我实际踩过的坑和验证过的解法。6.1 安装报错的排查路径Could not find a version that satisfies the requirement pandas (from versions: none)这个报错几乎成了国内新手装pandas的第一道坎。我的排查顺序是先查pip版本pip --version如果很旧就先python -m pip install --upgrade pip。换镜像源原命令后面加-i https://pypi.tuna.tsinghua.edu.cn/simple。清华源对国内网络非常友好成功率极高。看Python版本和位数pandas针对不同Python版本发布对应安装包如果Python太老新版pandas可能没有对应的预编译版本。如果仍在报错把pip和setuptools都更新一次再重试。还有一种PyCharm特有的迷惑场景界面里明明显示装好了运行却提示No module named pandas。这多半是解释器选择错了项目右下角或设置里选了A解释器但实际安装包的却是B解释器。赶紧检查当前运行的Python路径比重新装包有用。6.2 运行期高频报错清单把我在基础三阶段见过最多的报错整理成一张表方便对照。报错或现象原因建议处理UnicodeDecodeErrorcsv编码不是utf-8改用encodinggbkNo module named pandas解释器/环境不对检查PyCharm解释器路径ValueError: could not convert string to floatastype遇到脏数据改用to_numeric(..., errorscoerce)DateFormatter found invalid dates时间列还是字符串先pd.to_datetime转换画图时中文全是方块matplotlib字体无中文设置中文字体或改用英文标签导出的csv第一列是数字索引被写进文件to_csv(..., indexFalse)两个Series相加结果全是NaN索引对不上确认对齐方式必要时重置索引Excel导出后多出一列index忘了dropTrue或indexFalse在相应方法里显式关闭索引只要看到表里的前两列基本就能对上后一列的处理方式。排错的关键不是重复“安装卸载”而是先定位问题属于“环境问题”还是“数据类型问题”。6.3 几条长期受用的日常习惯第一凡是对列做类型转换结果必须重新赋值回去。pandas大部分操作返回新对象不是原地修改。写的代码越多越容易在这一点上翻车。第二读完文件先df.info()再看数据没有例外。info()能同时暴露列名、非空数量、各列类型相当于给接下来的处理做一次体检。跳过这一步直接分析大概率会在中途被类型问题打断。第三一个步骤单独一行别把十个操作链式写成一个超长表达式。链式写法看起来很酷排错时却很痛苦。拆开写每行做一件事处理出错时一眼就能定位到哪一行。第四凡是导出给同事或外部看的文件统一加indexFalse需要中文不乱码就再加encodingutf-8-sig。这两件事成了肌肉记忆后几乎没有人再因为你的导出文件翻过车。我个人用了pandas几年之后回头看基础三这个阶段真正宝贵的不是多记住了几个函数而是终于建立起了“数据需要预处理”的意识。一旦你习惯了“拿到任何表格都先看类型、再想转不转、转完再加工”的节奏后面学分组聚合、学多表关联、学可视化都只是在这条流水线上加新环节而已。如果你此刻正卡在某个类型转换或者读文件报错上按着上面的思路一步步排查多半能走出来。
返回列表