J'aime les pandas et ont été utilisé pendant des années et crois bien que j'ai une bonne poignée sur la façon de sous-ensemble dataframes et de traiter avec vue sur vs des copies de façon appropriée (même si j'utilise beaucoup d'affirmations pour être sûr). Je sais aussi qu'il y a eu des tonnes de questions sur SettingWithCopyWarning, par exemple, la Façon de traiter avec SettingWithCopyWarning dans les Pandas? et certains grands dernières guides de l'habillage autour de votre tête quand il arrive, par exemple, la Compréhension SettingWithCopyWarning dans les pandas.
Mais je sais aussi des choses spécifiques comme la citation de cette réponse ne sommes plus dans la plus récente docs (0.22.0
) et que beaucoup de choses ont été dépréciés au cours des années (pour certains inapproprié vieux réponses), et que la situation continue d'évoluer.
Récemment, après l'enseignement de pandas à des nouveaux venus avec de très de base en Python connaissances sur des choses comme éviter les enchaînés-indexation (et l'aide d' .iloc
/.loc
- )), je l'ai toujours mal à fournir des règles générales de base pour savoir quand il est important de prêter attention à l' SettingWithCopyWarning
(par exemple, quand il est sûr d'ignorer).
J'ai personnellement trouvé que le motif spécifique de subsetting un dataframe selon de sorte que certains de la règle (par exemple, de découpage ou de l'opération booléenne) et puis de modifier ce sous-ensemble, indépendants de l'original dataframe, il est beaucoup plus commun que les docs suggèrent. Dans cette situation, nous voulons modifier la copie et non l'original , et que l'avertissement est source de confusion/effrayant pour les nouveaux arrivants.
Je sais que c'est pas trivial de savoir à l'avance quand une vue par rapport à un exemplaire est retourné, par exemple
Quelles règles Pandas utiliser pour générer une vue vs une copie?
Vérifier si le bloc de données est de copier ou de la vue dans les Pandas
Donc à la place je suis à la recherche de la réponse à un plus générale (débutants) question: quand l'exécution d'une opération sur un incorporée dans un jeu partiel dataframe affecter l'original dataframe à partir de laquelle il a été créé, et quand sont-ils indépendants?.
J'ai créé certains cas ci-dessous que je pense sembler raisonnable, mais je ne sais pas si il y a une "chasse aux sorcières" je suis absent ou s'il ya un moyen plus facile de penser/vérifier ce point. J'espérais que quelqu'un pouvait confirmer mes intuitions sur les cas d'utilisation suivants sont correctes, comme le rapportent à ma question ci-dessus.
import pandas as pd
df1 = pd.DataFrame({'A':[2,4,6,8,10],'B':[1,3,5,7,9],'C':[10,20,30,40,50]})
1) Avertissement: Aucun
Version originale a été modifiée: Aucune
# df1 will be unaffected because we use .copy() method explicitly
df2 = df1.copy()
#
# Reference: docs
df2.iloc[0,1] = 100
2) Avertissement: Oui (je n'ai pas vraiment compris pourquoi)
Version originale a été modifiée: Aucune
# df1 will be unaffected because .query() always returns a copy
#
# Reference:
# https://stackoverflow.com/a/23296545/8022335
df2 = df1.query('A < 10')
df2.iloc[0,1] = 100
3) Mise En Garde: Oui
Version originale a été modifiée: Aucune
# df1 will be unaffected because boolean indexing with .loc
# always returns a copy
#
# Reference:
# https://stackoverflow.com/a/17961468/8022335
df2 = df1.loc[df1['A'] < 10,:]
df2.iloc[0,1] = 100
4) Avertissement: Aucun
Version originale a été modifiée: Aucune
# df1 will be unaffected because list indexing with .loc (or .iloc)
# always returns a copy
#
# Reference:
# Same as 4)
df2 = df1.loc[[0,3,4],:]
df2.iloc[0,1] = 100
5) Attention: Pas De
Version originale a été modifiée: Oui (source de confusion pour les nouveaux arrivants, mais qui a du sens)
# df1 will be affected because scalar/slice indexing with .iloc/.loc
# always references the original dataframe, but may sometimes
# provide a view and sometimes provide a copy
#
# Reference: docs
df2 = df1.loc[:10,:]
df2.iloc[0,1] = 100
tl;dr
Lors de la création d'un nouveau dataframe de l'original, la modification de la nouvelle dataframe:
Va modifier l'original lors d'un scalaire/tranche d'indexation avec .loc/.lci est utilisé pour créer la nouvelle dataframe.
Va pas modifier l'original quand boolean indexation avec .loc, .query()
ou .copy()
est utilisé pour créer la nouvelle dataframe