Quelles règles les Pandas utilisent-ils pour générer une vue par rapport à une copie?

119

Je ne comprends pas les règles que Pandas utilise pour décider qu'une sélection à partir d'un dataframe est une copie du dataframe original, ou une vue sur l'original.

Si j'ai, par exemple,

df = pd.DataFrame(np.random.randn(8,8), columns=list('ABCDEFGH'), index=range(1,9))

Je comprends que a queryrenvoie une copie de sorte que quelque chose comme

foo = df.query('2 < index <= 5')
foo.loc[:,'E'] = 40

n'aura aucun effet sur le dataframe d'origine, df . Je comprends également que les tranches scalaires ou nommées renvoient une vue, de sorte que les affectations à celles-ci, telles que

df.iloc[3] = 70

ou

df.ix[1,'B':'E'] = 222

changera df . Mais je suis perdu quand il s'agit de cas plus compliqués. Par exemple,

df[df.C <= df.B] = 7654321

changements df , mais

df[df.C <= df.B].ix[:,'B':'E']

ne fait pas.

Existe-t-il une règle simple que Pandas utilise et qui me manque tout simplement? Que se passe-t-il dans ces cas spécifiques? et en particulier, comment changer toutes les valeurs (ou un sous-ensemble de valeurs) dans un dataframe qui satisfont une requête particulière (comme j'essaye de le faire dans le dernier exemple ci-dessus)?


Remarque: ce n'est pas la même chose que cette question ; et j'ai lu la documentation , mais je ne suis pas éclairé par elle. J'ai également lu les questions "connexes" sur ce sujet, mais il me manque toujours la règle simple que Pandas utilise et comment je l'appliquerais, par exemple, pour modifier les valeurs (ou un sous-ensemble de valeurs) dans une trame de données qui satisfont une requête particulière.

orome
la source

Réponses:

138

Voici les règles, remplacement ultérieur:

  • Toutes les opérations génèrent une copie

  • S'il inplace=Trueest fourni, il modifiera en place; seules certaines opérations prennent en charge cela

  • Un indexeur qui définit, par exemple, .loc/.iloc/.iat/.atsera mis en place.

  • Un indexeur qui obtient sur un seul objet dtypé est presque toujours une vue (en fonction de la disposition de la mémoire, ce n'est peut-être pas la raison pour laquelle ce n'est pas fiable). C'est principalement pour l'efficacité. (l'exemple ci-dessus est pour .query; cela retournera toujours une copie telle qu'elle est évaluée par numexpr)

  • Un indexeur qui obtient sur un objet à plusieurs dtypes est toujours une copie.

Votre exemple de chained indexing

df[df.C <= df.B].loc[:,'B':'E']

n'est pas garanti de fonctionner (et donc vous devriez ne jamais faire cela).

Faites plutôt:

df.loc[df.C <= df.B, 'B':'E']

comme c'est plus rapide et fonctionnera toujours

L'indexation chaînée consiste en 2 opérations python distinctes et ne peut donc pas être interceptée de manière fiable par les pandas (vous obtiendrez souvent un SettingWithCopyWarning, mais ce n'est pas non plus détectable à 100%). Les documents de développement que vous avez mentionnés offrent une explication beaucoup plus complète.

Jeff
la source
3
.queryretournera TOUJOURS une copie à cause de ce qu'il fait (et non d'une vue), car il est évalué par n numexpr. Je vais donc ajouter cela aux `` règles ''
Jeff
3
pandas s'appuie sur numpy pour déterminer si une vue est générée. Dans un seul cas dtype (qui pourrait être un 1-d pour une série, un 2-d pour une trame, etc.). numpy peut générer une vue; cela dépend de ce que vous tranchez; parfois vous pouvez avoir une vue et parfois non. pandas ne s'appuie pas du tout sur ce fait car il n'est pas toujours évident qu'une vue soit générée. mais cela n'a pas d'importance car loc ne compte pas sur cela lors du réglage. Cependant, lors de l'indexation de chaîne, c'est très important (et donc pourquoi l'indexation de chaîne est mauvaise)
Jeff
3
Merci beaucoup Jeff, votre réponse est très utile. Quelle est votre source / référence sur ce sujet?
Kamixave
4
Alors d'abord, merci pour votre excellent travail! Et deuxièmement, si vous avez suffisamment de temps, je pense que ce serait formidable d'ajouter un paragraphe similaire à votre réponse principale dans le document.
Kamixave
2
serait certainement une pull-request pour ajouter / réviser les documents. fonce.
Jeff