将列表打印为表格数据

580

我是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循环和字符串打印。

我相信一定有一种非常简单的方法来解决这个问题,但是由于缺乏经验,我可能错过了它。


2
+1,昨晚我也正在尝试做同样的事情。你只是想打印到命令行还是使用GUI模块? - HellaMad
只是在命令行打印。然而,它需要通过一个单元测试用例,因此格式非常重要。 - hjweide
3
可能是在Python中打印表格数据的重复问题。 - Ciro Santilli OurBigBook.com
1
可能是Python:漂亮打印ASCII表格?的重复问题。 - Martin Thoma
请注意,此处的要求相当专业化,因为行和列标签相同。因此,对于这种特殊情况,临时代码是如何简单实现的一个很好的例子。但其他解决方案在更通用的表格显示方面可能更好。 - nealmcb
22个回答

10
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字符串格式化时:

  1. ">"用于右对齐
  2. "<"用于左对齐

20是可以根据需要更改的空格宽度。


1
能否详细解释一下这里的"> 20"是什么意思? - Alexander Santos
@AlexanderSantos 只是 f 字符串格式化文本的正确对齐方式(20 是为右对齐保留的空间宽度,> 用于右对齐 / < 用于左对齐)。分享两篇解释这个概念非常好的文章:
  1. https://www.geeksforgeeks.org/string-alignment-in-python-f-string/
  2. https://stackabuse.com/formatting-strings-with-python/
- codebae

9
我认为这个就是你要找的东西。
这是一个简单的模块,它仅计算表格条目所需的最大宽度,然后使用rjustljust来美化打印数据。
如果你想让左标题右对齐,只需更改此调用:
 print >> out, row[0].ljust(col_paddings[0] + 1),

从第53行开始:

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

链接似乎已经失效了。你有更新的链接吗? - jvriesem
1
@jvriesem:互联网档案馆有这个页面: 在Python中漂亮地打印表格 - Diomedea

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

会打印出来

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

6
以下函数将使用Python 3(也可能是Python 2)创建所请求的表格(带或不带numpy)。我选择设置每个列的宽度以匹配最长团队名称的宽度。如果您想要对每个列使用团队名称的长度进行修改,可以进行修改,但这会更加复杂。
注意:在Python 2中直接等效的是,您可以使用itertools中的izip替换zip
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

6

对于简单的情况,您可以直接使用现代字符串格式化(简化版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/zh-cn/3/tutorial/inputoutput.html#formatted-string-literals


4
我发现这个只是在寻找一种简单的输出列的方法。如果你只需要简单的列,那么可以使用以下代码:
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的答案已经满足了这一点,并且更加强大,因为它可以处理更多种长度的标签。


1
这个与编程有关的内容已经在 Meta 上讨论过了:https://meta.stackoverflow.com/questions/381571/answer-that-doesnt-answer-the-question - Félix Adriyel Gagnon-Grenier

3
我会尝试循环遍历列表,并使用CSV格式化程序来表示您想要的数据。
您可以指定制表符、逗号或任何其他字符作为分隔符。
否则,只需循环遍历列表并在每个元素后打印"\t"即可。 http://docs.python.org/library/csv.html

这是我的初步尝试,可能可以完成,但似乎需要花费很多精力才能完美地排版。 - hjweide

3
我有一个更好的方法,可以节省很多空间。
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

2
要使用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)

1
一个最小的、不依赖其他库的Python实现,可以与任何现有的print(a, "\t", b)语句兼容,并且左对齐输出。
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('\t')
        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__()

这将使您能够轻松转换大部分工作正常的基于\t的打印输出。
print('\t', '\t'.join(teams_list))
for i in range(len(data)):
    print(teams_list[i], '\t', '\t'.join(str(x) for x in data[i]))

使用:

a = AlignedPrinter()
a.print('\t', '\t'.join(teams_list))
for i in range(len(data)):
    a.print(teams_list[i], '\t', '\t'.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        

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接