Kaggle教程与Pandas文档中apply修改DataFrame行的疑问
背景与示例代码
我正在通过Kaggle教程学习Pandas,看到如下示例(reviews为DataFrame):
review_points_mean = reviews.points.mean() reviews.points.map(lambda p: p - review_points_mean) def remean_points(row): row.points = row.points - review_points_mean return row reviews.apply(remean_points, axis='columns')
我注意到remean_points函数会修改传入的row参数并返回它,但Pandas官方文档中关于DataFrame.apply的说明指出:修改传入对象的函数可能产生意外行为或错误,不受支持。文档示例是移除行元素的操作,而该函数仅修改行元素值,因此有以下疑问:
- 尽管
remean_points修改了row参数,它是否被Pandas官方支持? - 该函数是否未被Pandas官方允许,但因仅修改行元素值而在当前版本中可用?
- 是否存在我理解有误的情况?
同时我想了解:该示例目前可运行,这种写法在未来Pandas版本中是否仍可用,以及是否是修改值时使用apply的推荐方式(另一种方式是先复制row再修改)。
解答
核心结论
直接修改apply传入的行对象(row)的写法,是Pandas官方不推荐、也不保证长期支持的用法,哪怕当前能正常运行。
针对疑问的具体解答
是否被官方支持?
不支持。Pandas官方文档对DataFrame.apply的明确说明中,修改传入的对象(无论修改的是元素值还是行结构)都属于未定义行为,官方不会保证这种用法的正确性和跨版本兼容性。是否因仅修改值当前可用?
当前能运行只是依赖Pandas内部实现细节的“侥幸”情况。apply传入的row可能是原DataFrame的视图而非独立副本,修改它可能会意外修改原DataFrame(本例中未出现是因为最终返回了修改后的行,实际行为完全由内部逻辑决定)。一旦Pandas优化内部实现,这种写法就可能失效。是否理解有误?
你的理解没有错误。官方的禁止范围不仅限于修改行结构(比如移除元素),修改元素值同样属于不被支持的范畴——只要是对传入的row对象本身进行修改操作,都属于未定义行为。
关于未来可用性与推荐写法
- 未来兼容性:这种写法在未来Pandas版本中大概率会出现问题。比如官方可能会强制传入副本,到时修改
row的操作只会影响临时副本,无法体现在返回结果中,甚至可能抛出错误。 - 推荐写法:
- 若必须使用
apply,应先复制行对象再修改,避免触碰原传入对象:
def remean_points(row): new_row = row.copy() new_row.points = new_row.points - review_points_mean return new_row reviews.apply(remean_points, axis='columns')- 更优的方案是完全避免
apply,使用Pandas原生的向量化运算(效率远高于循环式的apply):
这才是符合Pandas设计理念的规范写法,既高效又不存在兼容性风险。reviews.points - reviews.points.mean() - 若必须使用
内容的提问来源于stack exchange,提问作者A SJ

