Mencetak Daftar sebagai Data Tabular

366

Saya cukup baru untuk Python dan sekarang saya berjuang dengan memformat data saya dengan baik untuk hasil cetak.

Saya punya satu daftar yang digunakan untuk dua pos, dan sebuah matriks yang harus menjadi isi tabel. Seperti itu:

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

Perhatikan bahwa nama judul tidak harus panjangnya sama. Entri data semuanya bilangan bulat.

Sekarang, saya ingin mewakili ini dalam format tabel, sesuatu seperti ini:

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

Saya punya firasat bahwa harus ada struktur data untuk ini, tetapi saya tidak dapat menemukannya. Saya telah mencoba menggunakan kamus dan memformat pencetakan, saya telah mencoba untuk-loop dengan lekukan dan saya telah mencoba mencetak sebagai string.

Saya yakin pasti ada cara yang sangat sederhana untuk melakukan ini, tetapi saya mungkin melewatkannya karena kurangnya pengalaman.

sampai jumpa
sumber
1
+1, saya hanya mencoba melakukan hal yang sama tadi malam. Apakah Anda hanya mencoba mencetak ke baris perintah atau Anda menggunakan modul GUI?
HellaMad
Hanya mencetak ke baris perintah. Namun, itu perlu melewati kasus unit test, jadi pemformatan cukup penting di sini.
hjweide
3
kemungkinan rangkap dari Mencetak data tabel dalam Python
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
Kemungkinan duplikat dari Python: tabel ascii yang tercetak cantik?
Martin Thoma
Perhatikan bahwa persyaratan di sini cukup khusus, karena label baris dan kolom sama. Jadi untuk kasus khusus ini, kode ad-hoc adalah contoh yang bagus tentang betapa mudahnya hal ini. Tetapi solusi lain di sini mungkin lebih baik untuk tampilan tabel yang lebih umum.
nealmcb

Jawaban:

189

Beberapa kode ad-hoc untuk 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))

Ini bergantung pada str.format()dan Spesifikasi Format Mini-Bahasa .

Sven Marnach
sumber
3
Jika menggunakan python2.6 ingatlah untuk menambahkan indeks team_list di row_format: row_format = "{0:> 15} {1:> 15} {2:> 15}"
Luis Muñoz
1
Jika data dalam tubuh lebih besar dari header, Anda dapat mengatur lebar kolom berdasarkan baris data pertama. untuk t dalam data [0]: row_format + = "{: <" + str (len (t) +5) + "}"
morgantaschuk
587

Ada beberapa paket python yang ringan dan berguna untuk tujuan ini:

1. tabulasi : 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 memiliki banyak opsi untuk menentukan header dan format tabel.

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 memiliki opsi untuk membaca data dari csv, html, sql database. Anda juga dapat memilih subset data, mengurutkan tabel dan mengubah gaya tabel.

3. texttable : 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  |
+-------+-----+

dengan texttable Anda dapat mengontrol perataan horizontal / vertikal, gaya perbatasan, dan tipe data.

4. termtables : 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  |
+-------+-----+

dengan texttable Anda dapat mengontrol perataan horizontal / vertikal, gaya perbatasan, dan tipe data.

Pilihan lain:

  • terminaltables Mudah menggambar tabel dalam aplikasi terminal / konsol dari daftar daftar string. Mendukung baris multi-line.
  • asciitable Asciitable dapat membaca dan menulis berbagai format tabel ASCII melalui Kelas Pembaca Ekstensi bawaan.
iman
sumber
13
Saya menemukan tabulasi sebagai alat yang sangat berguna untuk membangun alat CLI data-sentris. Itu, dikombinasikan dengan klik (klik instalasi pip), dan Anda mendapatkan sup nyata.
alexbw
4
Ini luar biasa, terima kasih. Secara pribadi, mana yang akan Anda pilih di antara ketiganya?
Jim Raynor
Balasan brilian! PrettyTable sangat baik - keseimbangan sempurna antara dua opsi lainnya.
edesz
2
terminaltables baik untuk Cina, mungkin bahasa non-Inggris lainnya
thinker3
5
Saya baru saja bermain dengan paket utama dan IMO "beautifultable" - terbaik, terawat, baik API & doco, dukungan untuk berwarna. "texttable" - API yang bagus, terpelihara, baik tetapi penggunaan warna menggunakan membuat tabel tidak sejajar. "terminaltables" - bagus, doco hanya melalui contoh kode. "PrettyTable" - ok, tapi tua, judul 'tabel' tidak bekerja untuk saya. "Tabulasi" - bagus, tetapi coalignkata kunci penyelarasan kolom tidak didukung dalam rilis pypi resmi. "tableprint" - rata-rata, kompleks API, tidak cukup contoh penggunaan umum.
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
sumber
6
Ini terlihat sangat menjanjikan, terima kasih, tetapi saya mencoba melakukan ini tanpa menggunakan perpustakaan yang diimpor lebih dari yang diperlukan.
hjweide
26
Menggunakan panda hanya untuk memformat keluaran sepertinya Overkill (huruf kapital O dimaksudkan).
Niels Bom
66
@NielsBom: datang untuk memformat output, tetap untuk analisis dan pemodelan data :)
jfs
30
@JFSebastian bagi saya itu lebih seperti "datang untuk memformat output, lari berteriak karena kompilasi numpy 10 menit yang membuat komputer saya terdengar seperti pengering rambut" ;-)
Niels Bom
4
@NielsBom: pip install numpymenggunakan roda biner sekarang di sebagian besar platform (tanpa kompilasi) . Jelas, opsi instalasi biner lainnya sudah tersedia bahkan sebelum itu.
jfs
68

Python sebenarnya membuat ini sangat mudah.

Sesuatu seperti

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

akan memiliki output

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

% Dalam string pada dasarnya adalah karakter pelarian dan karakter yang mengikutinya memberi tahu python format apa yang harus dimiliki data. % Di luar dan setelah string memberi tahu python bahwa Anda bermaksud menggunakan string sebelumnya sebagai string format dan bahwa data berikut harus dimasukkan ke dalam format yang ditentukan.

Dalam hal ini saya menggunakan "% -12i" dua kali. Untuk memecah setiap bagian:

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

Dari dokumen: https://docs.python.org/2/library/stdtypes.html#string-formatting

Austin
sumber
Jawaban ini membuat saya di jalur untuk menemukan apa yang saya cari! Untuk python 3, saya akhirnya menggunakannya seperti di print('%-20.2f' % position['deg'], '%-17.2f' % position['v2'])mana .2menentukan presisi floatf
Ross
25

Memperbarui jawaban Sven Marnach untuk bekerja di 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 berhenti karena Monica
sumber
9

Ketika saya melakukan ini, saya ingin memiliki kontrol atas detail bagaimana tabel diformat. Secara khusus, saya ingin sel header memiliki format yang berbeda dari sel tubuh, dan lebar kolom tabel hanya selebar masing-masing. Inilah solusi saya:

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', ' | ')

Inilah hasilnya:

                   | 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
kemah perkemahan
sumber
8

Saya pikir ini yang Anda cari.

Ini adalah modul sederhana yang hanya menghitung lebar maksimum yang diperlukan untuk entri tabel dan kemudian hanya menggunakan rjust dan ljust untuk melakukan pencetakan data yang cantik.

Jika Anda ingin judul kiri Anda selaras, ubah saja panggilan ini:

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

Dari baris 53 dengan:

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

Saya tahu bahwa saya terlambat ke pesta, tetapi saya hanya membuat perpustakaan untuk ini yang saya pikir bisa sangat membantu. Ini sangat sederhana, itu sebabnya saya pikir Anda harus menggunakannya. Ini disebut TableIT .

Penggunaan Dasar

Untuk menggunakannya, pertama-tama ikuti instruksi pengunduhan di Halaman GitHub .

Kemudian impor:

import TableIt

Kemudian buat daftar daftar di mana setiap daftar bagian dalam adalah baris:

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

Maka yang harus Anda lakukan adalah mencetaknya:

TableIt.printTable(table)

Ini adalah output yang Anda dapatkan:

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

Nama Bidang

Anda dapat menggunakan nama bidang jika Anda ingin ( jika Anda tidak menggunakan nama bidang, Anda tidak harus mengatakan useFieldNames = Salah karena diatur secara default ):


TableIt.printTable(table, useFieldNames=True)

Dari sana Anda akan mendapatkan:

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

Ada kegunaan lain untuk, misalnya Anda bisa melakukan ini:

import TableIt

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

TableIt.print(myList, useFieldNames=True)

Dari itu:

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

Atau Anda bisa melakukannya:

import TableIt

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

TableIt.printTable(myList, useFieldNames=True)

Dan dari yang Anda dapatkan:

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

Warna

Anda juga bisa menggunakan warna.

Anda menggunakan warna dengan menggunakan opsi warna ( secara default diatur ke Tidak Ada ) dan menentukan nilai RGB.

Menggunakan contoh dari atas:

import TableIt

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

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

Maka Anda akan mendapatkan:

masukkan deskripsi gambar di sini

Harap dicatat bahwa pencetakan warna mungkin tidak cocok untuk Anda, tetapi itu berfungsi sama persis dengan perpustakaan lain yang mencetak teks berwarna. Saya telah menguji dan setiap warna berfungsi. Biru tidak akan berantakan seperti halnya jika menggunakan 34murutan melarikan diri ANSI default (jika Anda tidak tahu apa itu tidak masalah). Bagaimanapun, itu semua berasal dari fakta bahwa setiap warna adalah nilai RGB daripada standar sistem.

Info lebih lanjut

Untuk info lebih lanjut, periksa Halaman GitHub

BeastCoder
sumber
TableIt benar-benar alat yang bagus. Sederhana tapi kuat. Satu-satunya kelemahan saya pikir TableIt belum menyatakan LISENSI
Endle_Zhenbo
@Endle_Zhenbo Hey! Terima kasih banyak, saya akan mengerjakannya sesegera mungkin!
BeastCoder
@Endle_Zhenbo, saya tahu sudah lama, tapi saya akhirnya menempatkan lisensi pada proyek.
BeastCoder
7

Python murni 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)

Akan dicetak

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
Ilmuwan Data
sumber
5

Cara mudah untuk melakukan ini adalah untuk mengulang semua kolom, mengukur lebarnya, membuat row_template untuk lebar maks, dan kemudian mencetak baris. Ini bukan apa yang Anda cari , karena dalam hal ini, pertama-tama Anda harus meletakkan judul di dalam tabel, tetapi saya pikir itu mungkin berguna bagi orang lain.

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))

Anda menggunakannya seperti ini:

>>> 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
sumber
3

Fungsi berikut akan membuat tabel yang diminta (dengan atau tanpa numpy) dengan Python 3 (mungkin juga Python 2). Saya telah memilih untuk mengatur lebar setiap kolom agar sesuai dengan nama tim yang paling panjang. Anda dapat memodifikasinya jika Anda ingin menggunakan panjang nama tim untuk setiap kolom, tetapi akan lebih rumit.

Catatan: Untuk persamaan langsung dalam Python 2 Anda bisa mengganti zipdengan izipdari 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)

Ini akan menghasilkan tabel berikut:

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

Jika Anda ingin memiliki pemisah garis vertikal, Anda dapat menggantinya " ".joindengan " | ".join.

Referensi:

Diomedea
sumber
2

Saya akan mencoba untuk mengulang daftar dan menggunakan formatter CSV untuk mewakili data yang Anda inginkan.

Anda dapat menentukan tab, koma, atau karakter lain sebagai pembatas.

Jika tidak, lewati saja daftar dan cetak "\ t" setelah setiap elemen

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

Jeffrey Kevin Pry
sumber
Ini adalah upaya awal saya, mungkin bisa dilakukan, tetapi tampaknya banyak upaya untuk mendapatkan format yang sempurna.
hjweide
2

Saya menemukan ini hanya mencari cara untuk menghasilkan kolom sederhana. Jika Anda hanya perlu kolom tanpa kerepotan , maka Anda dapat menggunakan ini:

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

EDIT: Saya berusaha sesederhana mungkin, dan dengan demikian melakukan beberapa hal secara manual daripada menggunakan daftar tim. Untuk menggeneralisasi ke pertanyaan aktual OP:

#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()

Ouputs:

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

Tetapi ini tampaknya tidak lagi lebih sederhana dari jawaban yang lain, mungkin dengan manfaatnya tidak memerlukan impor lagi. Tapi jawaban @ campkeith sudah memenuhi itu dan lebih kuat karena dapat menangani berbagai panjang label yang lebih luas.

pr3sidentspence
sumber
1
ini dibahas pada meta meta.stackoverflow.com/questions/381571/…
Félix Gagnon-Grenier