¿Cuál es la diferencia entre usar loc y usar solo corchetes para filtrar las columnas en Pandas / Python?

He notado tres métodos para seleccionar una columna en un DataFrame de Pandas:

Primer método de selección de una columna usando loc:

df_new = df.loc[:, 'col1'] 

Segundo método – parece más simple y más rápido:

 df_new = df['col1'] 

Tercer método – el más conveniente:

 df_new = df.col1 

¿Hay alguna diferencia entre estos tres métodos? No lo creo, en cuyo caso preferiría usar el tercer método.

En general, siento curiosidad por saber por qué parece haber tres métodos para hacer lo mismo.

En las siguientes situaciones, se comportan de la misma manera:

  1. Seleccionar una sola columna ( df['A'] es lo mismo que df.loc[:, 'A'] -> selecciona la columna A)
  2. Seleccionar una lista de columnas ( df[['A', 'B', 'C']] es lo mismo que df.loc[:, ['A', 'B', 'C']] -> selecciona columnas A, B y C)
  3. El corte por filas ( df[1:3] es lo mismo que df.iloc[1:3] -> selecciona las filas 1 y 2. Sin embargo, si corta filas con loc , en lugar de iloc , obtendrá filas 1, 2 y 3 suponiendo que tiene un índice de Rande. Consulte los detalles aquí .

Sin embargo, [] no funciona en las siguientes situaciones:

  1. Puede seleccionar una sola fila con df.loc[row_label]
  2. Puede seleccionar una lista de filas con df.loc[[row_label1, row_label2]]
  3. Puede df.loc[:, 'A':'C'] columnas con df.loc[:, 'A':'C']

Estos tres no se pueden hacer con [] . Más importante aún, si su selección involucra tanto filas como columnas, entonces la asignación se vuelve problemática.

 df[1:3]['A'] = 5 

Esto selecciona las filas 1 y 2, y luego selecciona la columna ‘A’ del objeto que regresa y le asigna un valor 5. El problema es que el objeto devuelto podría ser una copia, por lo que no puede cambiar el DataFrame real. Esto plantea SettingWithCopyWarning . La forma correcta de esta asignación es

 df.loc[1:3, 'A'] = 5 

Con .loc , tiene la garantía de modificar el DataFrame original. También le permite df.loc[:, 'C':'F'] columnas ( df.loc[:, 'C':'F'] ), seleccionar una sola fila ( df.loc[5] ) y seleccionar una lista de filas ( df.loc[[1, 2, 5]] ).

También tenga en cuenta que estos dos no se incluyeron en la API al mismo tiempo. .loc fue agregado mucho más tarde como un indexador más poderoso y explícito. Vea la respuesta de unutbu para más detalles.


Nota: Obtener columnas con [] vs. Es un tema completamente diferente. . solo está ahí por conveniencia. Solo permite acceder a columnas cuyo nombre es un identificador válido de Python (es decir, no pueden contener espacios, no pueden estar compuestos de números …). No se puede utilizar cuando los nombres entran en conflicto con los métodos de Series / DataFrame. Tampoco se puede usar para columnas no existentes (es decir, la asignación df.a = 1 no funcionará si no hay a columna a ). Aparte de eso . y [] son los mismos.

loc es especialmente útil cuando el índice no es numérico (por ejemplo, un índice de Datetime) porque puede obtener filas con tags particulares del índice:

 df.loc['2010-05-04 07:00:00'] df.loc['2010-1-1 0:00:00':'2010-12-31 23:59:59 ','Price'] 

Sin embargo, [] está destinado a obtener columnas con nombres particulares:

 df['Price'] 

Con [] también puedes filtrar filas , pero está más elaborado:

 df[df['Date'] < datetime.datetime(2010,1,1,7,0,0)]['Price'] 

Parece que hay una diferencia entre df.loc [] y df [] al crear un dataframe con varias columnas.

Puede hacer referencia a esta pregunta: ¿Existe una buena forma de generar múltiples columnas usando .loc?

Aquí, no puede generar varias columnas usando df.loc [:, [‘name1’, ‘name2’]], pero puede hacerlo usando el corchete doble df [[‘name1’, ‘name2’]]. (Me pregunto por qué se comportan de manera diferente.)