visualización de pandas: truncar la visualización de columnas en lugar de envolver

Con nombres de columnas extensos, los DataFrames se mostrarán en una forma muy desordenada, aparentemente sin importar qué opciones estén configuradas.

Información: Estoy en Jupyter QtConsole, pandas 0.20.1, con las siguientes opciones relevantes especificadas al inicio:

pd.set_option('display.max_colwidth', 20) pd.set_option('expand_frame_repr', False) pd.set_option('display.max_rows', 25) 

Pregunta: ¿Cómo puedo truncar el dataframe si es necesario en lugar de ajustar las columnas a la siguiente línea, mientras expand_frame_repr=False ?

Aquí hay un ejemplo. Nuevamente, el problema no depende del número de columnas sino de la longitud de las columnas.

Esto no causará un problema:

 df = pd.DataFrame(np.random.randn(1000, 1000), columns=['col' + str(i) for i in range(1000)]) 

Como la salida es perfectamente legible y se ve como: introduzca la descripción de la imagen aquí

El mismo DataFrame con nombres de columna largos causa el problema del que estoy hablando:

 df = pd.DataFrame(np.random.randn(1000, 1000), columns=['very_long_col_name_' + str(i) for i in range(1000)]) 

introduzca la descripción de la imagen aquí

¿Hay alguna forma de conformar la segunda salida para que sea como la primera que me falta? (Al especificar una opción, no mediante el uso de .iloc cada vez que quiero ver).

Parece que va a necesitar una mejora. El código relevante en la función de repr parece estar aquí:

  max_rows = get_option("display.max_rows") max_cols = get_option("display.max_columns") show_dimensions = get_option("display.show_dimensions") if get_option("display.expand_frame_repr"): width, _ = console.get_console_size() else: width = None self.to_string(buf=buf, max_rows=max_rows, max_cols=max_cols, line_width=width, show_dimensions=show_dimensions) 

Entonces, ya sea que pase expand_frame_repr=True y se expand_frame_repr=True al ancho de la línea, o que pase expand_frame_repr=False y no debería. Pero parece que hay un error en el código (esto debería ser pandas 0.20.3 iirc):

en pd.io.formats.format.DataFrameFormatter :

 def _chk_truncate(self): """ Checks whether the frame should be truncated. If so, slices the frame up. """ from pandas.core.reshape.concat import concat # Column of which first element is used to determine width of a dot col self.tr_size_col = -1 # Cut the data to the information actually printed max_cols = self.max_cols max_rows = self.max_rows if max_cols == 0 or max_rows == 0: # assume we are in the terminal # (why else = 0) (w, h) = get_terminal_size() self.w = w self.h = h if self.max_rows == 0: dot_row = 1 prompt_row = 1 if self.show_dimensions: show_dimension_rows = 3 n_add_rows = (self.header + dot_row + show_dimension_rows + prompt_row) # rows available to fill with actual data max_rows_adj = self.h - n_add_rows self.max_rows_adj = max_rows_adj # Format only rows and columns that could potentially fit the # screen if max_cols == 0 and len(self.frame.columns) > w: max_cols = w if max_rows == 0 and len(self.frame) > h: max_rows = h 

Parece que tenía la intención de hacer lo que querías, pero no estaba terminado. Está max_cols con el número de columnas, no con el ancho total de las columnas.

Por lo tanto, puede crear una función show_df que calcule el número correcto de columnas y mostrarlo en un option_context como la respuesta de pi2Squared, o corregirlo aquí (y tal vez enviar un parche si lo necesita distribuido).

Utilizar max_columns

 from string import ascii_letters df = pd.DataFrame(np.random.randint(10, size=(5, 52)), columns=list(ascii_letters)) with pd.option_context( 'display.max_colwidth', 20, 'expand_frame_repr', False, 'display.max_rows', 25, 'display.max_columns', 5, ): print(df.add_prefix('really_long_column_name_')) really_long_column_name_a really_long_column_name_b ... really_long_column_name_Y really_long_column_name_Z 0 8 1 ... 1 9 1 8 5 ... 2 1 2 5 0 ... 9 9 3 6 8 ... 0 9 4 1 2 ... 7 1 [5 rows x 52 columns] 

Otra idea … Obviamente no es exactamente lo que quieres, pero quizás puedas adaptarlo a tus necesidades.

 d1 = df.add_suffix('_really_long_column_name') with pd.option_context('display.max_colwidth', 4, 'expand_frame_repr', False): mw = pd.get_option('display.max_colwidth') print(d1.rename(columns=lambda x: x[:mw-3] + '...' if len(x) > mw else x)) a... b... c... d... e... f... g... h... i... j... ... Q... R... S... T... U... V... W... X... Y... Z... 0 6 5 5 5 8 3 5 0 7 6 ... 9 0 6 9 6 8 4 0 6 7 1 0 5 4 7 2 5 4 3 8 7 ... 8 1 5 3 5 9 4 5 5 3 2 7 2 1 6 5 1 0 1 3 1 ... 6 7 0 9 9 5 2 8 2 2 3 1 8 7 1 4 5 5 8 8 3 ... 3 6 5 7 1 0 8 1 4 0 4 7 5 6 2 4 9 7 9 0 5 ... 6 8 1 6 3 5 4 2 3 2 

Como otros han señalado, las pandas en sí parecen tener errores o están mal diseñadas aquí, por lo que se requiere una solución.

La mayoría de las veces este problema ocurre con columnas numéricas, ya que los números son relativamente cortos. Pandas dividirá el encabezado de la columna en varias líneas si hay espacios en él, de modo que pueda “hackear” el comportamiento correcto insertando espacios en los encabezados de las columnas para columnas numéricas cuando muestre el dataframe. Tengo una sola línea para hacer esto:

 def colfix(df, L=5): return df.rename(columns=lambda x: ' '.join(x.replace('_', ' ')[i:i+L] for i in range(0,len(x),L)) if df[x].dtype in ['float64','int64'] else x ) 

mostrar su dataframe, simplemente escriba

 colfix(your_df) 

tenga en cuenta que el cambio de nombre no cambiará permanentemente el dataframe, solo agregará espacios a los nombres con el fin de mostrarlo esa vez.

Resultados (en un cuaderno de Jupyter):

Con colfix :

usando colfix

Sin:

sin colfix