Quelqu'un pourrait-il m'expliquer une différence entre
df2 = df1
df2 = df1.copy()
df3 = df1.copy(deep=False)
J'ai essayé toutes les options et fait comme suit:
df1 = pd.DataFrame([1,2,3,4,5])
df2 = df1
df3 = df1.copy()
df4 = df1.copy(deep=False)
df1 = pd.DataFrame([9,9,9])
et retourné comme suit:
df1: [9,9,9]
df2: [1,2,3,4,5]
df3: [1,2,3,4,5]
df4: [1,2,3,4,5]
Donc, je n’observe aucune différence dans la sortie entre .copy()
et .copy(deep=False)
. Pourquoi?
J'attendrais l'une des options '=', copy (), copy (deep = False) pour renvoyer [9,9,9]
Qu'est-ce qui me manque s'il vous plaît?
Si vous voyez les ID d'objet des différents DataFrames que vous créez, vous pouvez clairement voir ce qui se passe.
Lorsque vous écrivez df2 = df1
, vous créez une variable nommée df2
et la liez avec un objet portant l'id 4541269200
. Lorsque vous écrivez df1 = pd.DataFrame([9,9,9])
, vous créez un objet new avec id 4541271120
et le liez à la variable df1
, mais l’objet avec id 4541269200
qui était précédemment lié à df1
continue à vivre. S'il n'y a pas de variables liées à cet objet, les ordures collectées par Python seront récupérées.
In[33]: import pandas as pd
In[34]: df1 = pd.DataFrame([1,2,3,4,5])
In[35]: id(df1)
Out[35]: 4541269200
In[36]: df2 = df1
In[37]: id(df2)
Out[37]: 4541269200 # Same id as df1
In[38]: df3 = df1.copy()
In[39]: id(df3)
Out[39]: 4541269584 # New object, new id.
In[40]: df4 = df1.copy(deep=False)
In[41]: id(df4)
Out[41]: 4541269072 # New object, new id.
In[42]: df1 = pd.DataFrame([9, 9, 9])
In[43]: id(df1)
Out[43]: 4541271120 # New object created and bound to name 'df1'.
In[44]: id(df2)
Out[44]: 4541269200 # Old object's id not impacted.
Edit: Ajouté le 30/07/2018
La copie en profondeur ne fonctionne pas dans les pandas et les développeurs envisagent de placer des objets mutables dans un DataFrame en tant qu'antipattern. Considérer ce qui suit:
In[10]: arr1 = [1, 2, 3]
In[11]: arr2 = [1, 2, 3, 4]
In[12]: df1 = pd.DataFrame([[arr1], [arr2]], columns=['A'])
In[13]: df1.applymap(id)
Out[13]:
A
0 4515714832
1 4515734952
In[14]: df2 = df1.copy(deep=True)
In[15]: df2.applymap(id)
Out[15]:
A
0 4515714832
1 4515734952
In[16]: df2.loc[0, 'A'].append(55)
In[17]: df2
Out[17]:
A
0 [1, 2, 3, 55]
1 [1, 2, 3, 4]
In[18]: df1
Out[18]:
A
0 [1, 2, 3, 55]
1 [1, 2, 3, 4]
df2
, si c’était une vraie copie profonde, aurait dû avoir de nouveaux identifiants pour les listes qu’il contient. Par conséquent, lorsque vous modifiez une liste dans df2, cela affecte également la liste dans df1, car ce sont les mêmes objets.
Deep Copy crée un nouvel identifiant pour chaque objet qu’il contient, tandis que la copie normale ne copie que les éléments du parent et crée un nouvel identifiant pour une variable dans laquelle il est copié.
La raison pour laquelle aucun df2
, df3
et df4
affichant [9,9,9]
n'est:
In[33]: import pandas as pd
In[34]: df1 = pd.DataFrame([1,2,3,4,5])
In[35]: id(df1)
Out[35]: 4541269200
In[36]: df2 = df1
In[37]: id(df2)
Out[37]: 4541269200 # Same id as df1
In[38]: df3 = df1.copy()
In[39]: id(df3)
Out[39]: 4541269584 # New object, new id.
In[40]: df4 = df1.copy(deep=False)
In[41]: id(df4)
Out[41]: 4541269072 # New object, new id.
In[42]: df1 = pd.DataFrame([9, 9, 9])
In[43]: id(df1)
Out[43]: 4541271120 # New object created and bound to name 'df1'.
Vous devez modifier les éléments de df individuellement. Essayez ce qui suit
df1 = pd.DataFrame([1,2,3,4,5])
df2 = df1
df3 = df1.copy()
df4 = df1.copy(deep=False)
df1.iloc[0,0] = 6
df2.iloc[1,0] = 7
df4.iloc[2,0] = 8
print(df1)
print(df2)
print(df3)
print(df4)