Pandas中不修改原Series的函数式高效赋值方法问询
函数式高效替换Series值(不修改原对象)
当然有,这里有几种函数式、高效且不修改原Series的方法,都是一步生成新对象,符合无副作用的编程风格:
方法一:使用Series.mask() / Series.where()
这两个是Pandas内置的矢量化方法,返回全新Series,不会改动原数据。mask()会替换满足条件的元素,where()则替换不满足条件的元素,按需选择即可。
import pandas as pd import numpy as np t = np.arange(100) s = pd.Series(t*t, t) # 定义要修改的索引和对应值 target_idx = [3, 4] new_values = [44, 55] # 用mask实现:匹配目标索引时替换为新值 s2 = s.mask(s.index.isin(target_idx), pd.Series(new_values, index=target_idx)) # 用where实现:保留非目标索引的元素,替换目标索引的元素 s3 = s.where(~s.index.isin(target_idx), pd.Series(new_values, index=target_idx))
这种方法是矢量化操作,效率和copy()后修改相当,但更贴合函数式编程的无副作用原则。
方法二:构造新Series合并(combine_first())
先创建仅包含待修改索引和值的小Series,再通过combine_first()合并,新值会自动覆盖原Series对应索引的内容:
new_series = pd.Series(new_values, index=target_idx) s4 = new_series.combine_first(s)
代码简洁直观,适合修改少量索引的场景,同样不会触碰原Series。
方法三:使用Series.replace()(按索引映射替换)
如果要替换的索引和值可以组成键值对,replace()也能实现,只需构造索引到新值的映射字典:
replace_map = dict(zip(target_idx, new_values)) s5 = s.replace(replace_map)
注意:如果原Series的值和replace_map的键重复,这些值也会被替换。如果要严格按索引替换,可明确指定替换逻辑:
s5 = s.replace(to_replace=replace_map, value=None, inplace=False)
对比原方法
上述方法均无需先调用copy()再修改,一步生成新对象,完全避免了对原Series的修改。效率上和复制后修改基本一致,因为都是Pandas内部优化的矢量化操作,远快于循环迭代。
内容的提问来源于stack exchange,提问作者Jason S
相关产品推荐
相关产品推荐

