Печать списков в виде табличных данных
Я новичок в 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 с отступом и я пытался печатать как строки.
Я уверен, что должен быть очень простой способ сделать это, но я, вероятно, скучаю по нему из-за отсутствия опыта.
Ответы
Ответ 1
Некоторый специальный код для 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()
и мини-языка спецификации формата.
Ответ 2
Для этого есть несколько легких и полезных пакетов 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
В tabulate есть много опций для указания заголовков и формата таблицы.
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 |
+-------+-----+
с помощью texttable вы можете контролировать горизонтальное/вертикальное выравнивание, стиль границы и типы данных.
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 |
+-------+-----+
с помощью texttable вы можете контролировать горизонтальное/вертикальное выравнивание, стиль границы и типы данных.
Другие опции:
- Terminaltables Легко рисовать таблицы в терминальных/консольных приложениях из списка списков строк. Поддерживает многострочные строки.
- asciitable Asciitable может читать и записывать широкий спектр форматов таблиц ASCII через встроенные классы расширений Reader.
Ответ 3
>>> 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
Ответ 4
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
Внутри строки, по сути, есть escape-символ, а последующие символы указывают 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
Ответ 5
Обновление Sven Marnach отвечает на работу в 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))
Ответ 6
BeautifulTable и Tabulate - некоторые из множества пакетов, которые вы можете использовать для решения своей проблемы.
Вот пример из beautifultable документации
>>> from beautifultable import BeautifulTable
>>> table = BeautifulTable()
>>> table.column_headers = ["name", "rank", "gender"]
>>> table.append_row(["Jacob", 1, "boy"])
>>> table.append_row(["Isabella", 1, "girl"])
>>> table.append_row(["Ethan", 2, "boy"])
>>> table.append_row(["Sophia", 2, "girl"])
>>> table.append_row(["Michael", 3, "boy"])
>>> print(table)
+----------+------+--------+
| name | rank | gender |
+----------+------+--------+
| Jacob | 1 | boy |
+----------+------+--------+
| Isabella | 1 | girl |
+----------+------+--------+
| Ethan | 2 | boy |
+----------+------+--------+
| Sophia | 2 | girl |
+----------+------+--------+
| Michael | 3 | boy |
+----------+------+--------+
Ответ 7
Когда я это делаю, мне нравится иметь некоторый контроль над деталями форматирования таблицы. В частности, я хочу, чтобы ячейки заголовков имели другой формат, чем ячейки тела, а ширина столбцов таблицы была такой же широкой, как и каждая из них. Здесь мое решение:
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),
Ответ 9
Чистый Питон 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
Ответ 10
Я попытался бы прокрутить список и использовать форматировщик CSV для представления данных, которые вы хотите.
В качестве разделителя можно указать вкладки, запятые или любые другие char.
В противном случае просто прокрутите список и напечатайте "\ t" после каждого элемента
http://docs.python.org/library/csv.html
Ответ 11
Следующая функция создаст запрошенную таблицу (с numpy или без) с Python 3 (возможно, также Python 2). Я выбрал ширину каждого столбца, соответствующую ширине самого длинного имени команды. Вы можете изменить его, если хотите использовать длину имени команды для каждого столбца, но это будет более сложным.
Примечание: для прямого эквивалента в Python 2 вы можете заменить zip
на izip
из 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)
Это приведет к следующей таблице:
Man Utd Man City T Hotspur
Man Utd 1 2 1
Man City 0 1 0
T Hotspur 2 4 2
Если вы хотите иметь вертикальные разделители строк, вы можете заменить " ".join
на " | ".join
.
Рекомендации:
Ответ 12
Простой способ сделать это - перебрать все столбцы, измерить их ширину, создать 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
Ответ 13
Я нашел это просто в поисках способа вывода простых столбцов. Если вам просто нужны столбцы без суеты, то вы можете использовать это:
print("Titlex\tTitley\tTitlez")
for x, y, z in data:
print(x, "\t", y, "\t", z)
РЕДАКТИРОВАТЬ: Я пытался быть как можно проще, и поэтому сделал некоторые вещи вручную, вместо того, чтобы использовать список команд. Для обобщения на ФП актуальный вопрос:
#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 уже встречал это и является более надежным, поскольку он может обрабатывать самые разные длины меток.