Para Pandas DataFrame, ¿cuál es la diferencia entre usar corchetes o puntos para acceder a una columna?

es decir:

import pandas d = {'col1': 2, 'col2': 2.5} df = pandas.DataFrame(data=d, index=[0]) print(df['col2']) print(df.col2) 

La salida es la misma.

¿Esta respuesta se aplica a este caso?

¿Cuál es la diferencia entre el corchete y las notaciones de puntos en Python?

La “notación de puntos”, es decir, df.col2 es el atributo de acceso que se expone como una conveniencia.

Puede acceder a un índice en una Serie, a una columna en un DataFrame, y a un elemento en un Panel directamente como un atributo:

df['col2'] hace lo mismo: devuelve un pd.Series de la columna.

Algunas advertencias sobre el acceso de atributos:

  • no puede agregar una columna ( df.new_col = x no funcionará, lo que es peor: en realidad creará un nuevo atributo en lugar de una columna, piense en parches de mono aquí)
  • no funcionará si tiene espacios en el nombre de la columna o si el nombre de la columna es un entero.

Son iguales siempre que accedas a una sola columna con un nombre simple, pero puedes hacer más con la notación de corchetes. Solo puede usar df.col si el nombre de la columna es un identificador válido de Python (por ejemplo, no contiene espacios y otras cosas similares). Además, puede encontrar sorpresas si su nombre de columna choca con un nombre de método de pandas (como sum ). Con los corchetes puede seleccionar varias columnas (por ejemplo, df[['col1', 'col2']] ) o agregar una nueva columna ( df['newcol'] = ... ), que no se puede hacer con acceso de punto .

La otra pregunta a la que te vinculas se aplica, pero esa es una pregunta mucho más general. Los objetos de Python llegan a definir cómo el . y los operadores [] aplican a ellos. Pandas DataFrames ha elegido hacerlos iguales para este caso limitado de acceso a columnas individuales, con las advertencias descritas anteriormente.

Respuesta corta para las diferencias:

  • [] indexación (acceso entre corchetes) tiene la funcionalidad completa para operar en los datos de la columna DataFrame.
  • Mientras que el acceso a los atributos ( acceso a puntos) es principalmente por conveniencia de acceder a los datos de la columna DataFrame existente, pero en ocasiones tiene sus limitaciones (por ejemplo, nombres de columnas especiales, creando una nueva columna).

Más explicaciones, Seires y DataFrame son clases centrales y estructuras de datos en pandas, y por supuesto también son clases de Python, por lo que hay una pequeña distinción cuando se trata de atributos de acceso entre atributos DataFrame y objetos normales de Python. Pero está bien documentado y se puede entender fácilmente. Sólo algunos puntos a tener en cuenta:

  1. En Python, los usuarios pueden agregar dinámicamente sus propios atributos de datos a un objeto de instancia mediante el acceso a atributos.

     >>> class Dog(object): ... pass >>> dog = Dog() >>> vars(dog) {} >>> superdog = Dog() >>> vars(superdog) {} >>> dog.legs = 'I can run.' >>> superdog.wings = 'I can fly.' >>> vars(dog) {'legs': 'I can run.'} >>> vars(superdog) {'wings': 'I can fly.'} 
  2. En pandas, el índice y la columna están estrechamente relacionados con la estructura de datos, puede acceder a un índice en una serie, columna en un DataFrame como un atributo .

     >>> import pandas as pd >>> import numpy as np >>> data = np.random.randint(low=0, high=10, size=(2,2)) >>> df = pd.DataFrame(data, columns=['a', 'b']) >>> df ab 0 7 6 1 5 8 >>> vars(df) {'_is_copy': None, '_data': BlockManager Items: Index(['a', 'b'], dtype='object') Axis 1: RangeIndex(start=0, stop=2, step=1) IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64, '_item_cache': {}} 
  3. Pero, el acceso a los atributos de pandas es principalmente una conveniencia para leer y modificar un elemento existente de una Serie o columna de un DataFrame.

     >>> df.a 0 7 1 5 Name: a, dtype: int64 >>> df.b = [1, 1] >>> df ab 0 7 1 1 5 1 
  4. Y, la conveniencia es un compromiso para la funcionalidad completa. Por ejemplo, puede crear un objeto DataFrame con nombres de columna ['space bar', '1', 'loc', 'min', 'index'] , pero no puede acceder a ellos como un atributo, ya que no son un Identificador de Python válido 1 , space bar o conflictos con un nombre de método existente.

     >>> data = np.random.randint(0, 10, size=(2, 5)) >>> df_special_col_names = pd.DataFrame(data, columns=['space bar', '1', 'loc', 'min', 'index']) >>> df_special_col_names space bar 1 loc min index 0 4 4 4 8 9 1 3 0 1 2 3 
  5. En estos casos, la .loc , .iloc y [] es la forma definida de acceder / operar completamente el índice y las columnas de los objetos Series y DataFrame.

     >>> df_special_col_names['space bar'] 0 4 1 3 Name: space bar, dtype: int64 >>> df_special_col_names.loc[:, 'min'] 0 8 1 2 Name: min, dtype: int64 >>> df_special_col_names.iloc[:, 1] 0 4 1 0 Name: 1, dtype: int64 
  6. Otra diferencia importante es cuando se trata de crear una nueva columna para DataFrame. Como puede ver, df.c = df.a + df.b acaba de crear un nuevo atributo junto a la estructura de datos del núcleo , por lo que a partir de la versión 0.21.0 y posterior, este comportamiento generará una UserWarning (no más silencioso) .

     >>> df ab 0 7 1 1 5 1 >>> df.c = df.a + df.b __main__:1: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access >>> df['d'] = df.a + df.b >>> df abd 0 7 1 8 1 5 1 6 >>> df.c 0 8 1 6 dtype: int64 >>> vars(df) {'_is_copy': None, '_data': BlockManager Items: Index(['a', 'b', 'd'], dtype='object') Axis 1: RangeIndex(start=0, stop=2, step=1) IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64 IntBlock: slice(2, 3, 1), 1 x 2, dtype: int64, '_item_cache': {}, 'c': 0 8 1 6 dtype: int64} 
  7. Finalmente, para crear una nueva columna para DataFrame, nunca use el acceso a los atributos , la forma correcta es usar la indexación [] o .loc :

     >>> df ab 0 7 6 1 5 8 >>> df['c'] = df.a + df.b >>> # OR >>> df.loc[:, 'c'] = df.a + df.b >>> df # c is an new added column abc 0 7 6 13 1 5 8 13