最近發現周圍的很多小夥伴們都不太樂意使用pandas,轉而投向其他的數據操作庫,身為一個數據工作者,基本上是張口pandas,閉口pandas了,故而寫下此系列以讓更多的小夥伴們愛上pandas。
系列文章說明:
系列名(系列文章序號)——此次系列文章具體解決的需求
平台:
有時在修改pandas對象中不想改變原數據框會使用.copy()給原數據框做一份拷貝,但數據內容中包含可變對象時,使用卻不會按本意進行,官方也在函數中給出說明,這裡一起了解下pandas中的深淺複製。
/ .copy(deep=True)函數詳解文檔:
Signature:df.copy(deep:'bool_t'=True)->'FrameOrSeries'Docstring:Makeacopyofthisobject'sindicesanddata.When``deep=True``(default),anewobjectwillbecreatedwithacopyofthecallingobject'sdataandindices.Modificationstothedataorindicesofthecopywillnotbereflectedintheoriginalobject(seenotesbelow).When``deep=False``,anewobjectwillbecreatedwithoutcopyingthecallingobject'sdataorindex(onlyreferencestothedataandindexarecopied).Anychangestothedataoftheoriginalwillbereflectedintheshallowcopy(andviceversa).Parameters----------deep:bool,defaultTrueMakeadeepcopy,includingacopyofthedataandtheindices.With``deep=False``neithertheindicesnorthedataarecopied.Returns-------copy:SeriesorDataFrameObjecttypematchescaller.Notes-----When``deep=True``,dataiscopiedbutactualPythonobjectswillnotbecopiedrecursively,onlythereferencetotheobject.Thisisincontrastto`copy.deepcopy`intheStandardLibrary,whichrecursivelycopiesobjectdata(seeexamplesbelow).While``Index``objectsarecopiedwhen``deep=True``,theunderlyingnumpyarrayisnotcopiedforperformancereasons.Since``Index``isimmutable,theunderlyingdatacanbesafelysharedandacopyisnotneeded.在該函數文檔中可以看出,默認為深複製(deep=True),會創建一個與原數據框不同的數據對象,在副本中修改數據均不會使原數據發生修改,在下面的Notes部分提到,如果數據內容是可變對象依然會改變原數據框內容,原因是pandas的深複製僅是引用python對象使用,也有部分減少性能的消耗,如Index不可變對象可以安全無誤的複製到新對象中,不同於copy.deepcopy會遞歸複製python對象,所以使用pandas.copy複製pandas對象,如果數據內容包含可變對象,仍然是不安全的,修改其內的數據會使原數據發生改變。
(手動水印:原創CSDN宿者朽命,https://blog.csdn.net/weixin_46281427?spm=1011.2124.3001.5343,公眾號A11Dot派)
/ 函數使用
生成df,包含3列數據,A列為數值型,不可變對象, B和C都是可變對象。

查看深淺複製對象,都與原對象不同,說明完成拷貝。

df_shallow會跟着df的改變而發生改變,而df_copy不會發生變化,也證實了df.copy(deep=False)是淺層複製,新建了一個與df數據內容及索引相同的但對象不同的數據框。

在B列修改過程中所有複製出來的數據框都發生了變化,正如Notes所說,是對對象的引用,是直接修改引用到的數據,那麼在數據框顯示部分看到B列的內容發生變化,原始數據內容是否也已經改變,打印data:

data中的B所對應的值也已經發生改變,那麼有什麼方法可以僅改變深複製後的數據對象,又不改變原始數據,這裡需要藉助copy模塊,C列的數據層次與B列一樣,下面修改C列數據。

熟悉pandas的會明白這樣僅讓df_copy中的C列參與了函數執行,沒有實際改變C列數據,但如果沒有第5行中的copy操作,即使沒有return語句也會使df_copy發生改變,原因見修改B列數據部分。如果需要改變C列數據將運行後的結果賦值給C列,由於C列被重新賦值也就不存在修改df_copy中C列數據會影響到df或df_shallow乃至data中的C列數據。
df_copy['C']=df_copy['C'].apply(value_upper)
可以看到僅df_copy['C']發生了變化。
/ 總結偶爾修改pandas對象中的數據時會被提醒所修改的數據視圖會影響原數據框,可以考慮使用df.copy方法避免修改,而當數據中含有可變對象,且只修改其中的一部分內容,卻不會產生這樣的警告,而這樣的結果又不能被接受時,可以查看下函數文檔,pandas中的copy與python對象的複製在使用上有部分不同,例如deepcopy是會對python進行遞歸操作,而pandas.copy僅將數據引用及索引進行複製。如果你問我deepcopy(df)是否可以避免上述情況發生,很遺憾的告訴你不行,對該篇有任何疑問歡迎聯繫作者,簡述你的見解。
當你難以分辨兩者之間是否有某種關聯時,最好的辦法是改變其中一個的特徵。
於二〇二二年三月二十日作