¿Qué reglas usa Pandas para generar una vista frente a una copia?

Estoy confundido acerca de las reglas que usa Pandas cuando decide que una selección de un dataframe es una copia del dataframe original, o una vista del original.

Si tengo, por ejemplo,

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

Entiendo que una query devuelve una copia para que algo como

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

no tendrá ningún efecto en el dataframe original, df . También entiendo que los segmentos escalares o con nombre devuelven una vista, por lo que las asignaciones a estos, como

 df.iloc[3] = 70 

o

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

cambiará df . Pero estoy perdido cuando se trata de casos más complicados. Por ejemplo,

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

cambios df , pero

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

no.

¿Hay una regla simple que Pandas está usando que solo me estoy perdiendo? ¿Qué está pasando en estos casos específicos? y en particular, ¿cómo puedo cambiar todos los valores (o un subconjunto de valores) en un dataframe que satisfaga una consulta en particular (como bash hacer en el último ejemplo anterior)?


Nota: Esto no es lo mismo que esta pregunta ; y he leído la documentación , pero no estoy iluminado por ella. También he leído las preguntas “Relacionadas” sobre este tema, pero aún me falta la regla simple que usan Pandas, y cómo la aplico, por ejemplo, para modificar los valores (o un subconjunto de valores) en un dataframe que satisfacen una consulta particular.

Aquí están las reglas, anulación subsiguiente:

  • Todas las operaciones generan una copia.

  • Si se proporciona inplace=True , se modificará in situ; solo algunas operaciones apoyan esto

  • Un indexador que establece, por ejemplo, .loc/.ix/.iloc/.iat/.at se establecerá in situ.

  • Un indexador que se coloca en un objeto con un solo dtyped es casi siempre una vista (dependiendo del diseño de la memoria, puede que no sea por eso que no es confiable). Esto es principalmente para la eficiencia. (el ejemplo de arriba es para .query ; esto siempre devolverá una copia como se evalúa mediante numexpr )

  • Un indexador que obtiene en un objeto de múltiples dtyped siempre es una copia.

Tu ejemplo de chained indexing

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

no se garantiza que funcione (y por lo tanto nunca deberías hacer esto).

En su lugar haz:

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

ya que esto es más rápido y siempre funcionará

La indexación encadenada es 2 operaciones de python separadas y, por lo tanto, los pandas no pueden interceptarla de manera confiable (muchas veces obtendrá un SettingWithCopyWarning , pero eso tampoco es 100% detectable). Los documentos de desarrollo , que usted señaló, ofrecen una explicación mucho más completa.