Друк списків у вигляді табличних даних


366

Я зовсім новачок у Python, і зараз я борюся за форматування своїх даних для друку.

У мене є один список, який використовується для двох заголовків, і матриця, яка повинна містити вміст таблиці. Так:

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

Зауважте, що назви заголовків не обов’язково однакової довжини. Однак, дані є цілими числами.

Тепер я хочу представити це у форматі таблиці приблизно так:

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

У мене є думка, що для цього повинна бути структура даних, але я не можу її знайти. Я спробував використовувати словник і відформатувати друк, я спробував for-loops з відступом, і я спробував друкувати як рядки.

Я впевнений, що це повинен бути дуже простий спосіб зробити це, але я, мабуть, його пропускаю через відсутність досвіду.


1
+1, я просто намагався зробити те саме, що минулої ночі. Ви просто намагаєтеся надрукувати в командному рядку чи використовуєте модуль GUI?
HellaMad

Просто друк у командному рядку. Однак для цього потрібно пройти тестовий випадок, тому форматування тут досить важливе.
hjweide



Зауважте, що вимога тут досить спеціалізована, оскільки мітки рядків та стовпців однакові. Тож для цього конкретного випадку спеціальний код - хороший приклад того, наскільки це може бути просто. Але інші рішення тут можуть бути кращими для більш загального відображення таблиці.
nealmcb

Відповіді:


189

Деякі спеціальні коди для 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))

Це залежить від str.format()і формату Специфікація Mini-Language .


3
Якщо ви використовуєте python2.6, не забудьте додати індекс team_list на row_format: row_format = "{0:> 15} {1:> 15} {2:> 15}"
Луїс Муньоз

1
Якщо даних у тілі більше, ніж заголовків, ви можете встановити ширину стовпців на основі першого ряду даних. для t в даних [0]: row_format + = "{: <" + str (len (t) +5) + "}"
morgantaschuk

587

Для цього є кілька легких і корисних пакунків python:

1. таблиця : 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

таблиця має багато варіантів, щоб вказати заголовки та формат таблиці.

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 є параметри для читання даних з CSV, HTML, бази даних sql. Також ви можете вибрати підмножину даних, сортувати таблицю та змінити стилі таблиці.

3. текстовий текст : 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  |
+-------+-----+

за допомогою текстового тексту можна керувати горизонтальним / вертикальним вирівнюванням, стилем межі та типами даних.

4. графіки : 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  |
+-------+-----+

за допомогою текстового тексту можна керувати горизонтальним / вертикальним вирівнюванням, стилем межі та типами даних.

Інші варіанти:

  • термінал Легко малювати таблиці в додатках для терміналів / консолей зі списку списків рядків. Підтримує багаторядкові рядки.
  • asciitable Asciitable може читати та записувати широкий спектр форматів таблиць ASCII за допомогою вбудованих класів читання розширень.

13
Я знайшов таблицю дуже корисним інструментом для створення CLI-інструментів, орієнтованих на дані. Це, у поєднанні з click (pip install click), і у вас вийшло справжнє тушковане м'ясо.
alexbw

4
Це чудово, дякую. Особисто, кого б ти не віддав перевагу серед цих трьох?
Джим Рейнор

Блискуча відповідь! PrettyTable просто такий хороший - ідеальний баланс між двома іншими варіантами.
edesz

2
термінали корисні для китайської, можливо, інших не англійських мов
thinker3

5
Я просто грав з основними пакунками та IMO "Beautifultable" - найкращим, підтримуваним, хорошим API та doco, підтримкою кольорових. "texttable" - приємний, підтримуваний, хороший API, але використання кольорового використання виводить таблиці з вирівнювання. "terminaltables" - добре, doco лише з прикладу коду. "PrettyTable" - добре, але старі назви "таблиці" для мене не працюють. "Табличний" - добре, але coalignключове слово вирівнювання стовпців не підтримується в офіційному релізі pypi. "tableprint" - середній, комплекс API, недостатньо поширених прикладів використання.
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        

6
Спасибі це виглядає дуже перспективно, але я намагаюся це зробити, не використовуючи більше імпортованих бібліотек, ніж абсолютно необхідних.
hjweide

26
Використання панд лише для форматування вихідних даних виглядає як Overkill (призначений з великої літери O).
Нільс Бом

66
@NielsBom: приходьте для форматування вихідних даних, зупиніться на аналізі даних та моделюванні :)
jfs

30
@JFSebastian для мене це було більше схоже на "приходьте до формату виходу, біжіть кричати через 10-хвилинну компіляцію нуме, яка зробила мій комп'ютер звуком феном" ;-)
Niels Bom

4
@NielsBom: pip install numpyвикористовує двійкові колеса зараз на більшості платформ (без компіляції) . Очевидно, що інші варіанти бінарної установки були доступні ще до цього.
jfs

68

Python насправді робить це досить просто.

Щось на зразок

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

матиме вихід

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

Значення% в рядку по суті є символом втечі, і символи, що слідують за ним, повідомляють python, який формат повинні мати дані. % За межами та після рядка повідомляє python про те, що ви маєте намір використовувати попередню рядок як рядок формату і що наступні дані слід вводити у вказаний формат.

У цьому випадку я використовував "% -12i" двічі. Щоб розділити кожну частину:

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

З документів: https://docs.python.org/2/library/stdtypes.html#string-formatting


Ця відповідь привела мене в шлях до пошуку того, що я шукав! Для python 3 я в кінцевому підсумку використовував його, як print('%-20.2f' % position['deg'], '%-17.2f' % position['v2'])там, де .2визначена точність поплавцяf
Ross

25

Оновлення відповіді Свена Марнаха для роботи в 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))

9

Коли я це роблю, мені подобається мати певний контроль над деталями форматування таблиці. Зокрема, я хочу, щоб комірки заголовка мали інший формат, ніж комірки тіла, а ширина стовпців таблиці повинна бути лише такою широкою, як кожна повинна бути. Ось моє рішення:

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

Ось результат:

                   | 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

8

Я думаю, що це те, що ти шукаєш.

Це простий модуль, який просто обчислює максимально необхідну ширину для записів таблиці, а потім просто використовує rjust і ljust, щоб зробити гарненький друк даних.

Якщо ви хочете, щоб лівий заголовок вирівнювався праворуч, просто змініть цей виклик:

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

З рядка 53 с:

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

8

Я знаю, що я спізнююсь на вечірку, але я просто створив для цього бібліотеку, яка, на мою думку, справді могла б допомогти. Це надзвичайно просто, тому я вважаю, що вам слід його використовувати. Це називається TableIT .

Основне використання

Для його використання спочатку дотримуйтесь інструкцій із завантаження на сторінці GitHub .

Потім імпортуйте його:

import TableIt

Потім складіть список списків, де кожен внутрішній список є рядком:

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

Тоді все, що вам потрібно зробити - це роздрукувати його:

TableIt.printTable(table)

Це вихід, який ви отримуєте:

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

Імена полів

Ви можете використовувати імена полів, якщо ви хочете ( якщо ви не використовуєте імена полів, вам не потрібно говорити useFieldNames = Неправильно, тому що це встановлено за замовчуванням ):


TableIt.printTable(table, useFieldNames=True)

З цього ви отримаєте:

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

Є й інші способи використання, наприклад, ви можете це зробити:

import TableIt

myList = [
    ["Name", "Email"],
    ["Richard", "richard@fakeemail.com"],
    ["Tasha", "tash@fakeemail.com"]
]

TableIt.print(myList, useFieldNames=True)

З цього:

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

Або ви могли б зробити:

import TableIt

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

TableIt.printTable(myList, useFieldNames=True)

І з цього ви отримуєте:

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

Кольори

Також можна використовувати кольори.

Ви використовуєте кольори, використовуючи опцію кольору ( за замовчуванням встановлено значення None ) та вказуючи значення RGB.

Використовуючи приклад зверху:

import TableIt

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

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

Тоді ви отримаєте:

введіть тут опис зображення

Зверніть увагу, що друк кольорів може не працювати для вас, але він працює точно так само, як і інші бібліотеки, які друкують кольоровий текст. Я протестував і кожен колір працює. Синій колір не псується, як це було б, якби за умовчанням34m послідовну програму ANSI (якщо ви не знаєте, що це не має значення). У будь-якому випадку, все це пов'язано з тим, що кожен колір є значенням RGB, а не системним замовчуванням.

Більше інформації

Для отримання додаткової інформації відвідайте сторінку GitHub


TableIt - це справді приємний інструмент. Простий, але потужний. Єдиним недоліком, на який я думаю, є TableIt не оголосив ЛІЦЕНЗІЮ
Endle_Zhenbo

@Endle_Zhenbo Гей! Велике спасибі, я працюю над цим якнайшвидше!
BeastCoder

@Endle_Zhenbo, я знаю, що минув час, але я нарешті розмістив ліцензію на проект.
BeastCoder

7

Чистий Пітон 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)

Буде надруковано

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

5

Простий спосіб зробити це - перевести цикл на всі стовпці, виміряти їх ширину, створити шаблон row_template для цієї максимальної ширини та надрукувати рядки. Це не зовсім те, що ви шукаєте , адже в цьому випадку спершу потрібно покласти заголовки всередину столу, але я думаю, що це може бути корисним комусь іншому.

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

Ви використовуєте його так:

>>> print_table(table)

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

3

Наступна функція створить запитувану таблицю (з нумером або без) з Python 3 (можливо, також Python 2). Я вирішив встановити ширину кожного стовпця відповідно до найдовшої назви команди. Ви можете змінити його, якщо хочете використовувати довжину назви команди для кожного стовпця, але буде складніше.

Примітка. Для прямого еквівалента в Python 2 ви можете замінити його zipна izipitertools.

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)

Це створить таку таблицю:

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

Якщо ви хочете мати роздільники вертикальних ліній, їх можна замінити " ".joinна " | ".join.

Список літератури:


2

Я б спробував прокрутити список і використовувати формат CSV для представлення потрібних даних.

В якості роздільника можна вказати вкладки, коми або будь-які інші символи.

В іншому випадку просто переведіть список і надрукуйте "\ t" після кожного елемента

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


Це була моя перша спроба, можливо, це можна зробити, але, здається, потрібно докласти чимало зусиль, щоб форматування було ідеальним.
hjweide

2

Я знайшов це просто шукаючи спосіб вивести прості стовпці. Якщо вам просто потрібні стовпці без суєти , ви можете скористатися цим:

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

EDIT: Я намагався бути максимально простим, і тим самим робив деякі речі вручну, замість того, щоб використовувати список команд. Для узагальнення актуального питання ОП:

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

Виходи:

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

Але це вже не здається більш простим, ніж інші відповіді, мабуть з тим, що воно не потребує більше імпорту. Але відповідь @ Campkeith вже відповіла цьому і є більш надійною, оскільки може обробляти більшу різноманітність довжин етикетки.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.