2017-07-11 9 views
2

Mit langen Spaltennamen werden DataFrames in einer sehr unübersichtlichen Form angezeigt, egal, was options gesetzt sind.Pandas-Display: Abschneiden der Spaltenanzeige statt Umbrechen

Info: Ich bin in Jupyter QtConsole, Pandas 0.20.1, mit den folgenden entsprechenden Optionen beim Start angegeben:

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

Frage: Wie kann ich den Datenrahmen bei Bedarf kürzen, anstatt die Spalten Einwickeln zu die nächste Zeile, während expand_frame_repr=False beibehalten?

Hier ist ein Beispiel. Auch hier hängt das Problem nicht von der Anzahl der Spalten, sondern von der Länge der Spalten ab.

Dies wird nicht ein Problem verursachen:

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

Da die Ausgabe perfekt lesbar ist und wie folgt aussieht: enter image description here

Das gleiche Datenrahmen mit langen Spaltennamen das Problem verursacht ich spreche:

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

enter image description here

Gibt es eine Möglichkeit, den zweiten Ausgang so anzupassen, dass er wie der erste ist, den ich vermisse? (Durch eine Option angeben, nicht durch .iloc Verwendung jedes Mal, wenn ich sehen möchten.)

+0

Hmm, ist dies kein Problem auf Ipython3. Die Spalten werden durch ein '/' geteilt und nachfolgende Spalten werden unter die erste Gruppe verschoben. –

+0

Was gibt Ihnen 'pd.options.display.line_width'? wenn es korrekt ist, sieht es normalerweise OK aus, aber in einigen Konsolen, die es nicht automatisch berechnen können (qtconsole war wie dieses IIRC), erscheint es als None und die Dinge sehen in diesem Fall nicht immer gut aus ... –

+0

@Coldspeed Ich nehme an, Sie haben 'expand_frame_repr = True'. Ich möchte diese Darstellung vermeiden. Überprüfen Sie Ihre 'pd.options.display.expand_frame_repr' –

Antwort

2

Sieht aus wie es wird eine Erweiterung benötigen. Der entsprechende Code in der repr Funktion erscheint hier zu sein:

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) 

Also entweder Sie passieren expand_frame_repr=True und wickelt auf die Linienbreite, oder Sie passieren expand_frame_repr=False und sollte es nicht. Aber es sieht aus wie es ist ein Fehler im Code ist (dies sollte Pandas 0.20.3 iirc sein):

in 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 

Sieht aus wie es soll tun, was man wollte, war aber unvollendet. Es überprüft max_cols gegen die Nummer der Spalten, nicht die Gesamtbreite der Spalten.

So könnte man entweder eine show_df Funktion erstellen, die die korrekte Anzahl der Spalten berechnen würden und es in einem option_context wie pi2Squared Antwort zeigen, oder es beheben hier (und vielleicht einen Patch einreichen, wenn Sie es verteilt benötigen).

2

Verwenden 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] 

Eine andere Idee ... Offensichtlich nicht genau das, was Sie wollen, aber vielleicht können Sie verdrehen Sie es nach Ihren Bedürfnissen.

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 
+0

Danke, aber ich würde gerne sehen, ob es auch andere Lösungen gibt. Dies würde bedeuten, dass jedes Mal, wenn ich diesen Typ von Datenfilmen mit langen Spalten drucken möchte, 'pd.option_context' gesetzt wird, nein? (Andernfalls würden schönere Datenrahmen unnötigerweise abgeschnitten, wenn die Option ohne Kontext gesetzt wäre. –

+0

Absolut ... Ich kann eine andere Lösung zusammenstellen, die die Optionen bei Interesse nicht ändert. Wird der gesamte Spaltenname angezeigt? – piRSquared

+0

Gute Frage ... Ich bin für beide offen, würde aber bevorzugen, col-Namen abgeschnitten an der colwidth, die ich in Optionen gesetzt haben –

0

Wie andere darauf hingewiesen haben, scheint Pandas selbst hier fehlerhaft oder fehlerhaft zu sein, daher ist ein Workaround erforderlich.

Meistens tritt dieses Problem bei numerischen Spalten auf, da Zahlen relativ kurz sind. Pandas teilen die Spaltenüberschrift auf mehrere Zeilen auf, wenn Leerzeichen darin enthalten sind, sodass Sie das korrekte Verhalten "einhacken" können, indem Sie bei der Anzeige des Datenrahmens Leerzeichen in Spaltenüberschriften für numerische Spalten einfügen. Ich habe einen Einzeiler, dies zu tun:

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) 

tun, um Ihren Datenrahmen anzuzeigen, geben Sie einfach

colfix(your_df) 

zur Kenntnis, dass die Umbenennung nicht dauerhaft sein wird, den Datenrahmen zu ändern, es wird nur hinzufügen, Leerzeichen die Namen für die Zwecke, es einmal zu zeigen.

Ergebnisse (in einem Jupyter Notebook):

Mit colfix:

using colfix

Ohne:

without colfix