Al seleccionar una sola columna de un DataFrame de pandas (digamos df.iloc[:, 0]
, df['A']
o df.A
, etc.), el vector resultante se convierte automáticamente en una Serie en lugar de en un DataFrame de una sola columna. Sin embargo, estoy escribiendo algunas funciones que toman un DataFrame como argumento de entrada. Por lo tanto, prefiero tratar con DataFrame de una sola columna en lugar de Series para que la función pueda asumir que df.columns es accesible. En este momento tengo que convertir explícitamente la Serie en un DataFrame usando algo como pd.DataFrame(df.iloc[:, 0])
. Este no parece el método más limpio. ¿Existe una forma más elegante de indexar desde un DataFrame directamente para que el resultado sea un DataFrame de una sola columna en lugar de una Serie?
92
Respuestas:
Como menciona @Jeff, hay algunas formas de hacer esto, pero recomiendo usar loc / iloc para ser más explícito (y generar errores temprano si intentas algo ambiguo):
In [10]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B']) In [11]: df Out[11]: A B 0 1 2 1 3 4 In [12]: df[['A']] In [13]: df[[0]] In [14]: df.loc[:, ['A']] In [15]: df.iloc[:, [0]] Out[12-15]: # they all return the same thing: A 0 1 1 3
Las dos últimas opciones eliminan la ambigüedad en el caso de nombres de columnas enteros (precisamente por qué se crearon loc / iloc). Por ejemplo:
In [16]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 0]) In [17]: df Out[17]: A 0 0 1 2 1 3 4 In [18]: df[[0]] # ambiguous Out[18]: A 0 1 1 3
fuente
[]
hace que el resultado sea a enDataFrame
lugar de aSeries
, pero ¿en qué parte de los documentos de pandas se discute este tipo de sintaxis de indexación? Solo estoy tratando de obtener el nombre "oficial" de esta técnica de indexación para que realmente la entienda. ¡Gracias!Como recomienda Andy Hayden , utilizar .iloc / .loc para indexar el marco de datos (de una sola columna) es el camino a seguir; otro punto a tener en cuenta es cómo expresar las posiciones del índice. Use etiquetas / posiciones de índice enumeradas mientras especifica los valores de los argumentos para indexar como Dataframe; si no lo hace, se devolverá un 'pandas.core.series.Series'
Entrada:
A_1 = train_data.loc[:,'Fraudster'] print('A_1 is of type', type(A_1)) A_2 = train_data.loc[:, ['Fraudster']] print('A_2 is of type', type(A_2)) A_3 = train_data.iloc[:,12] print('A_3 is of type', type(A_3)) A_4 = train_data.iloc[:,[12]] print('A_4 is of type', type(A_4))
Salida:
A_1 is of type <class 'pandas.core.series.Series'> A_2 is of type <class 'pandas.core.frame.DataFrame'> A_3 is of type <class 'pandas.core.series.Series'> A_4 is of type <class 'pandas.core.frame.DataFrame'>
fuente
Puede usar
df.iloc[:, 0:1]
, en este caso el vector resultante será unDataFrame
y no una serie.Como puedes ver:
fuente
Se han mencionado estos tres enfoques:
pd.DataFrame(df.loc[:, 'A']) # Approach of the original post df.loc[:,[['A']] # Approach 2 (note: use iloc for positional indexing) df[['A']] # Approach 3
pd.Series.to_frame () es otro enfoque.
Debido a que es un método, se puede utilizar en situaciones en las que el segundo y tercer enfoque anteriores no se aplican. En particular, es útil cuando se aplica algún método a una columna en su marco de datos y desea convertir la salida en un marco de datos en lugar de una serie. Por ejemplo, en un Jupyter Notebook, una serie no tendrá una salida bonita, pero un marco de datos sí.
# Basic use case: df['A'].to_frame() # Use case 2 (this will give you pretty output in a Jupyter Notebook): df['A'].describe().to_frame() # Use case 3: df['A'].str.strip().to_frame() # Use case 4: def some_function(num): ... df['A'].apply(some_function).to_frame()
fuente