Drucken von Listen als Tabellendaten

366

Ich bin ziemlich neu in Python und habe jetzt Probleme damit, meine Daten für die Druckausgabe gut zu formatieren.

Ich habe eine Liste, die für zwei Überschriften verwendet wird, und eine Matrix, die den Inhalt der Tabelle enthalten soll. Wie so:

teams_list = ["Man Utd", "Man City", "T Hotspur"]
data = np.array([[1, 2, 1],
                 [0, 1, 0],
                 [2, 4, 2]])

Beachten Sie, dass die Überschriften nicht unbedingt gleich lang sind. Die Dateneinträge sind jedoch alle Ganzzahlen.

Jetzt möchte ich dies in einem Tabellenformat darstellen, ungefähr so:

            Man Utd   Man City   T Hotspur
  Man Utd         1          0           0
 Man City         1          1           0
T Hotspur         0          1           2

Ich habe die Vermutung, dass es dafür eine Datenstruktur geben muss, aber ich kann sie nicht finden. Ich habe versucht, ein Wörterbuch zu verwenden und den Druck zu formatieren, ich habe for-Schleifen mit Einrückung versucht und ich habe versucht, als Zeichenfolgen zu drucken.

Ich bin mir sicher, dass es einen sehr einfachen Weg geben muss, aber ich vermisse ihn wahrscheinlich aufgrund mangelnder Erfahrung.

hjweide
quelle
1
+1, ich habe letzte Nacht nur versucht, dasselbe zu tun. Versuchen Sie nur, in die Befehlszeile zu drucken, oder verwenden Sie ein GUI-Modul?
HellaMad
Einfach in die Kommandozeile drucken. Es muss jedoch ein Unit-Test-Fall bestanden werden, daher ist die Formatierung hier ziemlich wichtig.
hjweide
3
Mögliches Duplikat des Druckens von Tabellendaten in Python
Ciro Santilli 法轮功 冠状 病 病 六四
1
Mögliches Duplikat von Python: hübsch druckende ASCII-Tabellen?
Martin Thoma
Beachten Sie, dass die Anforderung hier ziemlich spezialisiert ist, da die Zeilen- und Spaltenbeschriftungen identisch sind. In diesem speziellen Fall ist der Ad-hoc-Code ein gutes Beispiel dafür, wie einfach dies sein kann. Die anderen Lösungen hier sind jedoch möglicherweise besser für eine allgemeinere Tabellenanzeige.
Nealmcb

Antworten:

189

Einige Ad-hoc-Codes für Python 2.7:

row_format ="{:>15}" * (len(teams_list) + 1)
print(row_format.format("", *teams_list))
for team, row in zip(teams_list, data):
    print(row_format.format(team, *row))

Dies hängt von str.format()der Formatspezifikation Mini-Language ab .

Sven Marnach
quelle
3
Wenn Sie python2.6 verwenden, denken Sie daran, den team_list-Index für row_format hinzuzufügen: row_format = "{0:> 15} {1:> 15} {2:> 15}"
Luis Muñoz
1
Wenn die Daten im Hauptteil größer als die Überschriften sind, können Sie die Spaltenbreite basierend auf der ersten Datenzeile festlegen. für t in Daten [0]: row_format + = "{: <" + str (len (t) +5) + "}"
morgantaschuk
587

Zu diesem Zweck gibt es einige leichte und nützliche Python-Pakete:

1. tabellieren : https://pypi.python.org/pypi/tabulate

from tabulate import tabulate
print(tabulate([['Alice', 24], ['Bob', 19]], headers=['Name', 'Age']))
Name      Age
------  -----
Alice      24
Bob        19

tabulate bietet viele Optionen zum Festlegen von Kopfzeilen und Tabellenformaten.

print(tabulate([['Alice', 24], ['Bob', 19]], headers=['Name', 'Age'], tablefmt='orgtbl'))
| Name   |   Age |
|--------+-------|
| Alice  |    24 |
| Bob    |    19 |

2. PrettyTable : https://pypi.python.org/pypi/PrettyTable

from prettytable import PrettyTable
t = PrettyTable(['Name', 'Age'])
t.add_row(['Alice', 24])
t.add_row(['Bob', 19])
print(t)
+-------+-----+
|  Name | Age |
+-------+-----+
| Alice |  24 |
|  Bob  |  19 |
+-------+-----+

PrettyTable bietet Optionen zum Lesen von Daten aus der CSV-, HTML- und SQL-Datenbank. Sie können auch eine Teilmenge von Daten auswählen, Tabellen sortieren und Tabellenstile ändern.

3. Texttabelle : https://pypi.python.org/pypi/texttable

from texttable import Texttable
t = Texttable()
t.add_rows([['Name', 'Age'], ['Alice', 24], ['Bob', 19]])
print(t.draw())
+-------+-----+
| Name  | Age |
+=======+=====+
| Alice | 24  |
+-------+-----+
| Bob   | 19  |
+-------+-----+

Mit der Texttabelle können Sie die horizontale / vertikale Ausrichtung, den Rahmenstil und die Datentypen steuern.

4. Termtabellen : https://github.com/nschloe/termtables

import termtables as tt

string = tt.to_string(
    [["Alice", 24], ["Bob", 19]],
    header=["Name", "Age"],
    style=tt.styles.ascii_thin_double,
    # alignment="ll",
    # padding=(0, 1),
)
print(string)
+-------+-----+
| Name  | Age |
+=======+=====+
| Alice | 24  |
+-------+-----+
| Bob   | 19  |
+-------+-----+

Mit der Texttabelle können Sie die horizontale / vertikale Ausrichtung, den Rahmenstil und die Datentypen steuern.

Andere Optionen:

  • terminaltables Zeichnen Sie einfach Tabellen in Terminal- / Konsolenanwendungen aus einer Liste von Zeichenfolgenlisten. Unterstützt mehrzeilige Zeilen.
  • asciitable Asciitable kann eine Vielzahl von ASCII-Tabellenformaten über integrierte Erweiterungsleserklassen lesen und schreiben.
Iman
quelle
13
Ich habe festgestellt, dass tabulate ein sehr nützliches Tool zum Erstellen datenzentrierter CLI-Tools ist. Das, kombiniert mit Klick (Pip Install Click), und Sie haben einen echten Eintopf in Gang.
Alexbw
4
Das ist wunderbar, danke. Welches würden Sie persönlich unter diesen drei bevorzugen?
Jim Raynor
Geniale Antwort! PrettyTable ist einfach so gut - die perfekte Balance zwischen den beiden anderen Optionen.
Edesz
2
terminaltables ist gut für Chinesisch, vielleicht andere nicht-englische Sprachen
thinker3
5
Ich habe gerade mit den Hauptpaketen und IMO "beautifulifultable" gespielt - am besten, gepflegt, gute API & Doco, Unterstützung für farbige. "texttable" - nette, gepflegte, gute API, aber die Verwendung von farbigem Gebrauch wirft Tabellen aus der Ausrichtung. "terminaltables" - gut, doco nur über Codebeispiele. "PrettyTable" - ok, aber alte Tabellentitel funktionieren bei mir nicht. "Tabulate" - gut, aber das coalignSchlüsselwort für die Spaltenausrichtung wird in der offiziellen Pypi-Version nicht unterstützt. "tableprint" - Durchschnitt, API-Komplex, nicht genügend Beispiele für die allgemeine Verwendung.
Abulka
79
>>> import pandas
>>> pandas.DataFrame(data, teams_list, teams_list)
           Man Utd  Man City  T Hotspur
Man Utd    1        2         1        
Man City   0        1         0        
T Hotspur  2        4         2        
jfs
quelle
6
Das sieht sehr vielversprechend aus, danke, aber ich versuche dies zu tun, ohne mehr importierte Bibliotheken als unbedingt notwendig zu verwenden.
hjweide
26
Die Verwendung von Pandas nur für die Ausgabeformatierung scheint Overkill zu sein (Großbuchstabe O beabsichtigt).
Niels Bom
66
@NielsBom: kommen Sie für die Ausgabeformatierung, bleiben Sie für die Datenanalyse und Modellierung :)
jfs
30
@JFSebastian für mich war es eher wie "Komm für die Ausgabeformatierung, lauf schreiend weg wegen der 10-minütigen Numpy-Kompilierung, die meinen Computer wie einen Haartrockner klingen ließ" ;-)
Niels Bom
4
@NielsBom: pip install numpyVerwendet jetzt auf den meisten Plattformen binäre Räder (keine Kompilierung) . Offensichtlich waren bereits zuvor andere binäre Installationsoptionen verfügbar.
JFS
68

Python macht das eigentlich ganz einfach.

Etwas wie

for i in range(10):
    print '%-12i%-12i' % (10 ** i, 20 ** i)

wird die Ausgabe haben

1           1           
10          20          
100         400         
1000        8000        
10000       160000      
100000      3200000     
1000000     64000000    
10000000    1280000000  
100000000   25600000000
1000000000  512000000000

Das% in der Zeichenfolge ist im Wesentlichen ein Escape-Zeichen, und die darauf folgenden Zeichen geben Python an, welches Format die Daten haben sollen. Das% außerhalb und nach der Zeichenfolge teilt Python mit, dass Sie die vorherige Zeichenfolge als Formatzeichenfolge verwenden möchten und dass die folgenden Daten in das angegebene Format eingegeben werden sollen.

In diesem Fall habe ich zweimal "% -12i" verwendet. So zerlegen Sie jeden Teil:

'-' (left align)
'12' (how much space to be given to this part of the output)
'i' (we are printing an integer)

Aus den Dokumenten: https://docs.python.org/2/library/stdtypes.html#string-formatting

Austin
quelle
Diese Antwort brachte mich auf den richtigen Weg, um das zu finden, wonach ich suchte! Für Python 3 habe ich es so verwendet, wie es print('%-20.2f' % position['deg'], '%-17.2f' % position['v2'])die .2Genauigkeit des f
Ross
25

Aktualisierung der Antwort von Sven Marnach auf Python 3.4:

row_format ="{:>15}" * (len(teams_list) + 1)
print(row_format.format("", *teams_list))
for team, row in zip(teams_list, data):
    print(row_format.format(team, *row))
SmrtGrunt hat wegen Monica gekündigt
quelle
9

Wenn ich das mache, möchte ich die Details der Formatierung der Tabelle steuern. Insbesondere möchte ich, dass Header-Zellen ein anderes Format als Body-Zellen haben und die Spaltenbreiten der Tabellen nur so breit sind, wie sie jeweils benötigt werden. Hier ist meine Lösung:

def format_matrix(header, matrix,
                  top_format, left_format, cell_format, row_delim, col_delim):
    table = [[''] + header] + [[name] + row for name, row in zip(header, matrix)]
    table_format = [['{:^{}}'] + len(header) * [top_format]] \
                 + len(matrix) * [[left_format] + len(header) * [cell_format]]
    col_widths = [max(
                      len(format.format(cell, 0))
                      for format, cell in zip(col_format, col))
                  for col_format, col in zip(zip(*table_format), zip(*table))]
    return row_delim.join(
               col_delim.join(
                   format.format(cell, width)
                   for format, cell, width in zip(row_format, row, col_widths))
               for row_format, row in zip(table_format, table))

print format_matrix(['Man Utd', 'Man City', 'T Hotspur', 'Really Long Column'],
                    [[1, 2, 1, -1], [0, 1, 0, 5], [2, 4, 2, 2], [0, 1, 0, 6]],
                    '{:^{}}', '{:<{}}', '{:>{}.3f}', '\n', ' | ')

Hier ist die Ausgabe:

                   | Man Utd | Man City | T Hotspur | Really Long Column
Man Utd            |   1.000 |    2.000 |     1.000 |             -1.000
Man City           |   0.000 |    1.000 |     0.000 |              5.000
T Hotspur          |   2.000 |    4.000 |     2.000 |              2.000
Really Long Column |   0.000 |    1.000 |     0.000 |              6.000
Campkeith
quelle
8

Ich denke das ist es, wonach Sie suchen.

Es ist ein einfaches Modul, das nur die maximal erforderliche Breite für die Tabelleneinträge berechnet und dann nur rjust und ljust verwendet , um einen hübschen Druck der Daten zu erstellen.

Wenn Sie möchten, dass Ihre linke Überschrift nach rechts ausgerichtet ist, ändern Sie einfach diesen Aufruf:

 print >> out, row[0].ljust(col_paddings[0] + 1),

Ab Zeile 53 mit:

 print >> out, row[0].rjust(col_paddings[0] + 1),
Bogdan
quelle
8

Ich weiß, dass ich zu spät zur Party komme, aber ich habe gerade eine Bibliothek dafür erstellt, von der ich denke, dass sie wirklich helfen könnte. Es ist sehr einfach, deshalb denke ich, dass Sie es verwenden sollten. Es heißt TableIT .

Grundlegende Verwendung

Befolgen Sie dazu zunächst die Download-Anweisungen auf der GitHub-Seite .

Dann importieren Sie es:

import TableIt

Erstellen Sie dann eine Liste mit Listen, wobei jede innere Liste eine Zeile ist:

table = [
    [4, 3, "Hi"],
    [2, 1, 808890312093],
    [5, "Hi", "Bye"]
]

Dann müssen Sie es nur noch ausdrucken:

TableIt.printTable(table)

Dies ist die Ausgabe, die Sie erhalten:

+--------------------------------------------+
| 4            | 3            | Hi           |
| 2            | 1            | 808890312093 |
| 5            | Hi           | Bye          |
+--------------------------------------------+

Feldnamen

Sie können Feldnamen verwenden, wenn Sie möchten ( wenn Sie keine Feldnamen verwenden, müssen Sie nicht useFieldNames = False sagen, da dies standardmäßig festgelegt ist ):


TableIt.printTable(table, useFieldNames=True)

Daraus erhalten Sie:

+--------------------------------------------+
| 4            | 3            | Hi           |
+--------------+--------------+--------------+
| 2            | 1            | 808890312093 |
| 5            | Hi           | Bye          |
+--------------------------------------------+

Es gibt andere Verwendungszwecke, zum Beispiel könnten Sie dies tun:

import TableIt

myList = [
    ["Name", "Email"],
    ["Richard", "[email protected]"],
    ["Tasha", "[email protected]"]
]

TableIt.print(myList, useFieldNames=True)

Davon:

+-----------------------------------------------+
| Name                  | Email                 |
+-----------------------+-----------------------+
| Richard               | richard@fakeemail.com |
| Tasha                 | tash@fakeemail.com    |
+-----------------------------------------------+

Oder Sie könnten tun:

import TableIt

myList = [
    ["", "a", "b"],
    ["x", "a + x", "a + b"],
    ["z", "a + z", "z + b"]
]

TableIt.printTable(myList, useFieldNames=True)

Und daraus erhalten Sie:

+-----------------------+
|       | a     | b     |
+-------+-------+-------+
| x     | a + x | a + b |
| z     | a + z | z + b |
+-----------------------+

Farben

Sie können auch Farben verwenden.

Sie verwenden Farben, indem Sie die Farboption ( standardmäßig auf Keine eingestellt ) verwenden und RGB-Werte angeben.

Verwenden Sie das Beispiel von oben:

import TableIt

myList = [
    ["", "a", "b"],
    ["x", "a + x", "a + b"],
    ["z", "a + z", "z + b"]
]

TableIt.printTable(myList, useFieldNames=True, color=(26, 156, 171))

Dann erhalten Sie:

Geben Sie hier die Bildbeschreibung ein

Bitte beachten Sie, dass das Drucken von Farben möglicherweise nicht für Sie funktioniert, jedoch genauso wie die anderen Bibliotheken, die farbigen Text drucken. Ich habe getestet und jede einzelne Farbe funktioniert. Das Blau ist auch nicht durcheinander, wie es bei Verwendung der Standard- 34mANSI-Escape-Sequenz der Fall wäre (wenn Sie nicht wissen, was das ist, spielt es keine Rolle). Wie auch immer, alles kommt von der Tatsache, dass jede Farbe eher ein RGB-Wert als ein Systemstandard ist.

Mehr Info

Weitere Informationen finden Sie auf der GitHub-Seite

BeastCoder
quelle
TableIt ist wirklich ein schönes Werkzeug. Einfach aber kraftvoll. Der einzige Nachteil, den ich denke, ist TableIt hat keine LIZENZ deklariert
Endle_Zhenbo
@ Endle_Zhenbo Hey! Vielen Dank, ich werde so schnell wie möglich daran arbeiten!
BeastCoder
@Endle_Zhenbo, ich weiß, dass es eine Weile her ist, aber ich habe endlich eine Lizenz für das Projekt vergeben.
BeastCoder
7

Pure Python 3

def print_table(data, cols, wide):
    '''Prints formatted data on columns of given width.'''
    n, r = divmod(len(data), cols)
    pat = '{{:{}}}'.format(wide)
    line = '\n'.join(pat * cols for _ in range(n))
    last_line = pat * r
    print(line.format(*data))
    print(last_line.format(*data[n*cols:]))

data = [str(i) for i in range(27)]
print_table(data, 6, 12)

Wird gedruckt

0           1           2           3           4           5           
6           7           8           9           10          11          
12          13          14          15          16          17          
18          19          20          21          22          23          
24          25          26
Der Datenwissenschaftler
quelle
5

Eine einfache Möglichkeit, dies zu tun, besteht darin, alle Spalten zu durchlaufen, ihre Breite zu messen, eine row_template für diese maximale Breite zu erstellen und dann die Zeilen zu drucken. Es ist nicht genau das, wonach Sie suchen , denn in diesem Fall müssen Sie zuerst Ihre Überschriften in den Tisch legen, aber ich denke, es könnte für jemand anderen nützlich sein.

table = [
    ["", "Man Utd", "Man City", "T Hotspur"],
    ["Man Utd", 1, 0, 0],
    ["Man City", 1, 1, 0],
    ["T Hotspur", 0, 1, 2],
]
def print_table(table):
    longest_cols = [
        (max([len(str(row[i])) for row in table]) + 3)
        for i in range(len(table[0]))
    ]
    row_format = "".join(["{:>" + str(longest_col) + "}" for longest_col in longest_cols])
    for row in table:
        print(row_format.format(*row))

Sie verwenden es so:

>>> print_table(table)

            Man Utd   Man City   T Hotspur
  Man Utd         1          0           0
 Man City         1          1           0
T Hotspur         0          1           2
Emil Stenström
quelle
3

Die folgende Funktion erstellt die angeforderte Tabelle (mit oder ohne Numpy) mit Python 3 (möglicherweise auch Python 2). Ich habe mich dafür entschieden, die Breite jeder Spalte so einzustellen, dass sie mit der des längsten Teamnamens übereinstimmt. Sie können es ändern, wenn Sie die Länge des Teamnamens für jede Spalte verwenden möchten, dies ist jedoch komplizierter.

Hinweis: Für eine direkte Entsprechung in Python 2 Sie die ersetzen könnten zipmit izipvon itertools.

def print_results_table(data, teams_list):
    str_l = max(len(t) for t in teams_list)
    print(" ".join(['{:>{length}s}'.format(t, length = str_l) for t in [" "] + teams_list]))
    for t, row in zip(teams_list, data):
        print(" ".join(['{:>{length}s}'.format(str(x), length = str_l) for x in [t] + row]))

teams_list = ["Man Utd", "Man City", "T Hotspur"]
data = [[1, 2, 1],
        [0, 1, 0],
        [2, 4, 2]]

print_results_table(data, teams_list)

Dadurch wird die folgende Tabelle erstellt:

            Man Utd  Man City T Hotspur
  Man Utd         1         2         1
 Man City         0         1         0
T Hotspur         2         4         2

Wenn Sie vertikale Linie Separatoren haben wollen, können Sie ersetzen " ".joinmit " | ".join.

Verweise:

Diomedea
quelle
2

Ich würde versuchen, die Liste zu durchlaufen und einen CSV-Formatierer zu verwenden, um die gewünschten Daten darzustellen.

Sie können Tabulatoren, Kommas oder andere Zeichen als Trennzeichen angeben.

Andernfalls durchlaufen Sie einfach die Liste und drucken nach jedem Element "\ t"

http://docs.python.org/library/csv.html

Jeffrey Kevin Pry
quelle
Dies war mein erster Versuch, es kann wahrscheinlich gemacht werden, aber es scheint eine Menge Aufwand zu sein, um die Formatierung perfekt zu machen.
hjweide
2

Ich fand dies nur auf der Suche nach einer Möglichkeit, einfache Spalten auszugeben. Wenn Sie nur unkomplizierte Spalten benötigen , können Sie Folgendes verwenden:

print("Titlex\tTitley\tTitlez")
for x, y, z in data:
    print(x, "\t", y, "\t", z)

EDIT: Ich habe versucht, so einfach wie möglich zu sein, und dabei einige Dinge manuell erledigt, anstatt die Teamliste zu verwenden. Um auf die eigentliche Frage des OP zu verallgemeinern:

#Column headers
print("", end="\t")
for team in teams_list:
    print(" ", team, end="")
print()
# rows
for team, row in enumerate(data):
    teamlabel = teams_list[team]
    while len(teamlabel) < 9:
        teamlabel = " " + teamlabel
    print(teamlabel, end="\t")
    for entry in row:
        print(entry, end="\t")
    print()

Ausgaben:

          Man Utd  Man City  T Hotspur
  Man Utd       1       2       1   
 Man City       0       1       0   
T Hotspur       2       4       2   

Dies scheint jedoch nicht mehr einfacher zu sein als die anderen Antworten, mit dem Vorteil, dass keine weiteren Importe erforderlich sind. Die Antwort von @ campkeith hat dies jedoch bereits erfüllt und ist robuster, da sie eine größere Vielfalt von Etikettenlängen verarbeiten kann.

pr3sidentspence
quelle
1
Dies wird auf meta meta.stackoverflow.com/questions/381571/…
Félix Gagnon-Grenier