将列表打印为表格数据
- 2024-11-22 08:48:00
- admin 原创
- 155
问题描述:
我对 Python 还很陌生,现在正在努力格式化我的数据以便打印输出。
我有一个用于两个标题的列表和一个应为表格内容的矩阵。如下所示:
teams_list = ["Man Utd", "Man City", "T Hotspur"]
data = np.array([[1, 2, 1],
[0, 1, 0],
[2, 4, 2]])
注意,标题名称的长度不一定相同。不过,数据条目都是整数。
现在,我想以表格形式表示它,如下所示:
曼联 | 曼城 | 热刺队 | |
---|---|---|---|
曼联 | 1 | 0 | 0 |
曼城 | 1 | 1 | 0 |
热刺队 | 0 | 1 | 2 |
我有一种预感,这肯定有一个数据结构,但我找不到它。我试过使用字典并格式化打印,试过使用缩进的 for 循环,试过打印为字符串。
我确信一定有一种非常简单的方法可以做到这一点,但我可能由于缺乏经验而错过了它。
解决方案 1:
有一些轻量且实用的 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 表格式。
解决方案 2:
一些临时代码:
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()
格式规范小语言。
解决方案 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
字符串中的 % 本质上是一个转义字符,其后的字符告诉 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:
我知道我来晚了,但我刚刚为此创建了一个库,我认为它真的很有用。它非常简单,这就是我认为你应该使用它的原因。它被称为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=False,因为它默认设置为):
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 |
+-----------------------+
颜色
您还可以使用颜色。
您可以使用颜色选项(默认设置为无)并指定 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 页面
解决方案 7:
只需使用
from beautifultable import BeautifulTable
table = BeautifulTable()
table.column_headers = ["", "Man Utd","Man City","T Hotspur"]
table.append_row(['Man Utd', 1, 2, 3])
table.append_row(['Man City', 7, 4, 1])
table.append_row(['T Hotspur', 3, 2, 2])
print(table)
结果,你会得到一张整洁的桌子,就是这样。
解决方案 8:
尝试丰富: https: //github.com/Textualize/rich
from rich.console import Console
from rich.table import Table
console = Console()
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Date", style="dim", width=12)
table.add_column("Title")
table.add_column("Production Budget", justify="right")
table.add_column("Box Office", justify="right")
table.add_row(
"Dec 20, 2019", "Star Wars: The Rise of Skywalker", "$275,000,000", "$375,126,118"
)
table.add_row(
"May 25, 2018",
"[red]Solo[/red]: A Star Wars Story",
"$275,000,000",
"$393,151,347",
)
table.add_row(
"Dec 15, 2017",
"Star Wars Ep. VIII: The Last Jedi",
"$262,000,000",
"[bold]$1,332,539,889[/bold]",
)
console.print(table)
https://github.com/willmcgugan/rich/raw/master/imgs/table.png
解决方案 9:
一个简单的方法是循环遍历所有列,测量它们的宽度,为最大宽度创建一个 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
解决方案 10:
当我这样做时,我希望能够控制表格格式的细节。特别是,我希望标题单元格的格式与正文单元格不同,并且表格列的宽度仅与每个列所需的宽度相同。这是我的解决方案:
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]] \n + 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}', '
', ' | ')
输出如下:
| 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
解决方案 11:
table_data= [[1,2,3],[4,5,6],[7,8,9]]
for row in table_data:
print("{: >20} {: >20} {: >20}".format(*row))
输出:
1 2 3
4 5 6
7 8 9
其中 f 字符串格式化
“>” 用于右对齐
“<”用于左对齐
20是可以根据需要改变的空间宽度。
解决方案 12:
纯 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 = '
'.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
解决方案 13:
我想这就是你要找的。
这是一个简单的模块,只需计算表格条目所需的最大宽度,然后使用rjust和ljust对数据进行漂亮的打印。
如果您希望左标题右对齐,只需更改此调用:
print >> out, row[0].ljust(col_paddings[0] + 1),
从第 53 行开始:
print >> out, row[0].rjust(col_paddings[0] + 1),
解决方案 14:
另一个无库解决方案,它考虑每列中最长的元素:
def pretty_print_table(rows, line_between_rows=True):
"""
Example Output
┌──────┬─────────────┬────┬───────┐
│ True │ short │ 77 │ catty │
├──────┼─────────────┼────┼───────┤
│ 36 │ long phrase │ 9 │ dog │
├──────┼─────────────┼────┼───────┤
│ 8 │ medium │ 3 │ zebra │
└──────┴─────────────┴────┴───────┘
"""
# find the max length of each column
max_col_lens = list(map(max, zip(*[(len(str(cell)) for cell in row) for row in rows])))
# print the table's top border
print('┌' + '┬'.join('─' * (n + 2) for n in max_col_lens) + '┐')
rows_separator = '├' + '┼'.join('─' * (n + 2) for n in max_col_lens) + '┤'
row_fstring = ' │ '.join("{: <%s}" % n for n in max_col_lens)
for i, row in enumerate(rows):
print('│', row_fstring.format(*map(str, row)), '│')
if line_between_rows and i < len(rows) - 1:
print(rows_separator)
# print the table's bottom border
print('└' + '┴'.join('─' * (n + 2) for n in max_col_lens) + '┘')
例子:
rows = [
[True, "short", 77, "catty"],
[36, "long phrase", 9, "dog"],
[8, 'medium', 3, "zebra"],
]
pretty_print_table(rows)
'''
┌──────┬─────────────┬────┬───────┐
│ True │ short │ 77 │ catty │
├──────┼─────────────┼────┼───────┤
│ 36 │ long phrase │ 9 │ dog │
├──────┼─────────────┼────┼───────┤
│ 8 │ medium │ 3 │ zebra │
└──────┴─────────────┴────┴───────┘
'''
pretty_print_table(rows, line_between_rows=False)
'''
┌──────┬─────────────┬────┬───────┐
│ True │ short │ 77 │ catty │
│ 36 │ long phrase │ 9 │ dog │
│ 8 │ medium │ 3 │ zebra │
└──────┴─────────────┴────┴───────┘
'''
解决方案 15:
以下函数将使用 Python 3(也可能是 Python 2)创建请求的表(带或不带 numpy)。我选择将每列的宽度设置为与最长的球队名称相匹配。如果您想对每列使用球队名称的长度,您可以修改它,但会更复杂。
注意:对于 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
。
参考:
关于格式化的大量信息https://pyformat.info/(旧的和新的格式样式)
官方 Python 教程(相当不错)-
https://docs.python.org/3/tutorial/inputoutput.html#the-string-format-method官方 Python 信息(可能难以阅读) -
https://docs.python.org/3/library/string.html#string-formatting另一个资源 -
https://www.python-course.eu/python3_formatted_output.php
解决方案 16:
对于简单的情况,您只需使用现代字符串格式(简化的Sven的答案)即可
f'{column1_value:15} {column2_value}'
::
table = {
'Amplitude': [round(amplitude, 3), 'm³/h'],
'MAE': [round(mae, 2), 'm³/h'],
'MAPE': [round(mape, 2), '%'],
}
for metric, value in table.items():
print(f'{metric:14} : {value[0]:>6.3f} {value[1]}')
输出:
Amplitude : 1.438 m³/h
MAE : 0.171 m³/h
MAPE : 27.740 %
来源:https ://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals
解决方案 17:
我发现这只是在寻找一种输出简单列的方法。如果你只需要简单的列,那么你可以使用这个:
print("Titlex Titley Titlez")
for x, y, z in data:
print(x, " ", y, " ", z)
编辑:我试图尽可能简单,因此手动做了一些事情,而不是使用团队列表。概括一下 OP 的实际问题:
#Column headers
print("", end=" ")
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=" ")
for entry in row:
print(entry, end=" ")
print()
输出:
Man Utd Man City T Hotspur
Man Utd 1 2 1
Man City 0 1 0
T Hotspur 2 4 2
但这似乎不再比其他答案更简单,也许好处是它不需要更多导入。但@campkeith 的答案已经满足了这一点,而且更强大,因为它可以处理更多种类的标签长度。
解决方案 18:
我会尝试循环遍历列表并使用 CSV 格式化程序来表示您想要的数据。
您可以指定制表符、逗号或任何其他字符作为分隔符。
否则,只需循环遍历列表并在每个元素后打印“\t”
http://docs.python.org/library/csv.html
解决方案 19:
我找到了一个更好的,可以节省很多空间。
table = [
['number1', 'x', 'name'],
["4x", "3", "Hi"],
["2", "1", "808890312093"],
["5", "Hi", "Bye"]
]
column_max_width = [max(len(row[column_index]) for row in table) for column_index in range(len(table[0]))]
row_format = ["{:>"+str(width)+"}" for width in column_max_width]
for row in table:
print("|".join([print_format.format(value) for print_format, value in zip(row_format, row)]))
输出:
number1| x| name
4x| 3| Hi
2| 1|808890312093
5|Hi| Bye
解决方案 20:
要创建一个简单的表格,请terminaltables
打开终端或命令提示符并运行pip install terminaltables
。
您可以按如下方式打印 Python 列表:
from terminaltables import AsciiTable
l = [
['Head', 'Head'],
['R1 C1', 'R1 C2'],
['R2 C1', 'R2 C2'],
['R3 C1', 'R3 C2']
]
table = AsciiTable(l)
print(table.table)
解决方案 21:
print(a, " ", b)
最小无依赖左对齐 Python 实现,与任何现有语句向后兼容:
class AlignedPrinter:
def __init__(self):
self._col_widths = {}
self._lines = []
def __del__(self):
self.aligned_print()
def print(self, *args):
line = ' '.join([str(x) for x in args])
cols = line.split(' ')
self._lines.append(cols)
for i in range(len(cols)):
self._col_widths[i] = max(len(cols[i]), self._col_widths.get(i, 0))
def aligned_print(self):
for line in self._lines:
aligned = []
for i in range(len(line)):
col = line[i]
aligned.append(col + ' ' * (self._col_widths[i] - len(col)))
print(' '.join(aligned))
self.__init__()
这将允许您轻松转换大多数
基于工作的打印件:
print(' ', ' '.join(teams_list))
for i in range(len(data)):
print(teams_list[i], ' ', ' '.join(str(x) for x in data[i]))
和:
a = AlignedPrinter()
a.print(' ', ' '.join(teams_list))
for i in range(len(data)):
a.print(teams_list[i], ' ', ' '.join(str(x) for x in data[i]))
a.aligned_print()
为您提供:
Man Utd Man City T Hotspur
Man Utd 1 2 1
Man City 0 1 0
T Hotspur 2 4 2
解决方案 22:
matrepr在标记矩阵方面做得很好:
from matrepr import mprint
teams = ["Man Utd", "Man City", "T Hotspur"]
data = np.array([[1, 2, 1], [0, 1, 0], [2, 4, 2]])
mprint(data, title=False, row_labels=teams, col_labels=teams)
Man Utd Man City T Hotspur
┌ ┐
Man Utd │ 1 2 1 │
Man City │ 0 1 0 │
T Hotspur │ 2 4 2 │
└ ┘
除了 numpy 数组之外,还可以使用稀疏矩阵(scipy、pydata),并输出为 HTML 和 Latex。
解决方案 23:
list1 = [1, 2, 3]
list2 = [10, 20, 30]
l = []
for i in range(0, len(list1)):
l.append(list1[i]), l.append(list2[i])
# print(l)
for i in range(0, len(l), 2):
print(l[i], "", l[i + 1])