【问题标题】:How do I output lists as a table in Jupyter notebook?如何在 Jupyter 笔记本中将列表输出为表格?
【发布时间】:2016-05-11 15:48:33
【问题描述】:

我知道我以前在某个地方看到过一些例子,但我一生都在谷歌搜索时找不到它。

我有一些数据行:

data = [[1,2,3],
        [4,5,6],
        [7,8,9],
        ]

我想在表格中输出这些数据,例如

+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+
| 7 | 8 | 9 |
+---+---+---+

显然我可以使用像 prettytable 这样的库或下载 pandas 或其他东西,但我对此非常不感兴趣。

我只想将我的行作为表格输出到我的 Jupyter 笔记本单元格中。我该怎么做?

【问题讨论】:

  • 您只想使用print 函数吗?数字的宽度是否固定(1位,3位?
  • 这里我写了pythonic抽象。轻松编写代码。 :) jupyter_table_class.py
  • 我很好奇你不想下载 prettytable 或 pandas 的理由是什么......
  • 2016 年是一辈子的事了。可能当时下载 pandas 的速度非常慢。

标签: python jupyter-notebook


【解决方案1】:

我刚刚发现tabulate 有一个 HTML 选项,而且使用起来相当简单。

更新:从 Jupyter v6 及更高版本开始,返回的 table 应该只通过输出单元呈现:

import tabulate
data = [["Sun",696000,1989100000],
         ["Earth",6371,5973.6],
         ["Moon",1737,73.5],
         ["Mars",3390,641.85]]
table = tabulate.tabulate(data, tablefmt='html')
table

至于 Jupyter v5 或更早版本,您可能需要更加明确,类似于 Werner 的回答:

from IPython.display import HTML, display
display(HTML(table))

仍在寻找一些易于使用的东西来创建更复杂的表格布局,例如使用 Latex 语法和格式来合并单元格并在笔记本中进行变量替换:
Allow references to Python variables in Markdown cells #2958

【讨论】:

  • 对齐字符串对我不起作用!它不会将字符串向左对齐!
  • @MojtabaKhodadadi 没有仔细检查,但看起来您可以为 srtings 与数字 here 设置默认列参数。
  • 现在即使只是 tabulate.tabulate(table, tablefmt='html') 似乎也可以工作(尝试过 Jupyter 6.0.3、JupyterLab 2.0.1)。不错!
【解决方案2】:

您可以添加自己的格式化程序。 递归 是可选的,但非常好。

JupyterLite试试这个:

from html import escape

fmtr = get_ipython().display_formatter.formatters['text/html']

def getfmtr(obj, func=None):
    if fmtr.for_type(type(obj)):
        return fmtr.for_type(type(obj))(obj)
    else:
        return escape(obj.__str__()).replace("\n", "<br>")

def strfmtr(obj):
    return escape(obj.__str__()).replace("\n", "<br>")

fmtr.for_type(str, strfmtr)

def listfmtr(self):
    _repr_ = []
    _repr_.append("<table>")
    for item in self:
        _repr_.append("<tr>")
        _repr_.append("<td>")
        _repr_.append(getfmtr(item))
        _repr_.append("<td>")
        _repr_.append("</tr>")
    _repr_.append("</table>")
    return str().join(_repr_)

fmtr.for_type(list, listfmtr)

def dictfmtr(self):
    _repr_ = []
    _repr_.append("<table>")
    for key in self:
        _repr_.append("<th>")
        _repr_.append(getfmtr(key))
        _repr_.append("<th>")
    _repr_.append("<tr>")
    for key, value in self.items():
        _repr_.append("<td>")
        _repr_.append(getfmtr(value))
        _repr_.append("<td>")
    _repr_.append("</tr>")
    _repr_.append("</table>")
    return str().join(_repr_)

fmtr.for_type(dict, dictfmtr)

[
    "Jupyter is really cool!",
    [1, 2],
    [
        {"Name": "Adams", "Age": 32},
        {"Name": "Baker", "Age": 32}
    ]
]

【讨论】:

    【解决方案3】:

    如果你不介意使用一点 html,这样的东西应该可以工作。

    from IPython.display import HTML, display
    
    def display_table(data):
        html = "<table>"
        for row in data:
            html += "<tr>"
            for field in row:
                html += "<td><h4>%s</h4></td>"%(field)
            html += "</tr>"
        html += "</table>"
        display(HTML(html))
    

    然后像这样使用它

    data = [[1,2,3],[4,5,6],[7,8,9]]
    display_table(data)
    

    【讨论】:

      【解决方案4】:

      我最近使用prettytable 来渲染一个漂亮的 ASCII 表。它类似于 postgres CLI 输出。

      import pandas as pd
      from prettytable import PrettyTable
      
      data = [[1,2,3],[4,5,6],[7,8,9]]
      df = pd.DataFrame(data, columns=['one', 'two', 'three'])
      
      def generate_ascii_table(df):
          x = PrettyTable()
          x.field_names = df.columns.tolist()
          for row in df.values:
              x.add_row(row)
          print(x)
          return x
      
      generate_ascii_table(df)
      

      输出:

      +-----+-----+-------+
      | one | two | three |
      +-----+-----+-------+
      |  1  |  2  |   3   |
      |  4  |  5  |   6   |
      |  7  |  8  |   9   |
      +-----+-----+-------+
      

      【讨论】:

        【解决方案5】:

        我终于重新找到了我一直在寻找的jupyter/IPython documentation

        我需要这个:

        from IPython.display import HTML, display
        
        data = [[1,2,3],
                [4,5,6],
                [7,8,9],
                ]
        
        display(HTML(
           '<table><tr>{}</tr></table>'.format(
               '</tr><tr>'.join(
                   '<td>{}</td>'.format('</td><td>'.join(str(_) for _ in row)) for row in data)
               )
        ))
        

        (我可能稍微搞砸了理解,但 display(HTML('some html here')) 是我们需要的)

        【讨论】:

          【解决方案6】:

          有一个不错的技巧:用 pandas DataFrame 包装数据。

          import pandas as pd
          data = [[1, 2], [3, 4]]
          pd.DataFrame(data, columns=["Foo", "Bar"])
          

          它显示如下数据:

            | Foo | Bar |
          0 | 1   | 2   |
          1 | 3   | 4   |
          

          【讨论】:

          • 作为一个除了数据科学以外都绝对喜欢 python 的人,看到九行、四重导入、三重函数调用的答案在最佳答案字面上是“a熊猫数据框。”我的启发是:“如果它很长——它可能是错误的!”
          • 您甚至可以使用to_html() 将DataFrame 显示为HTML,请参阅stackoverflow.com/a/29665452/2866660
          • 谢谢!是的,接受的答案一定要改成这个。
          • 如果你已经有了 Pandas,那肯定很简单,但如果你没有,用它来打印表格有点“大锤破解”
          【解决方案7】:

          我想输出一个表格,其中每列的宽度尽可能小, 其中列用空格填充(但可以更改),行由换行符分隔(但可以更改)并且每个项目都使用str 格式化(但是...)。


          def ftable(tbl, pad='  ', sep='\n', normalize=str):
          
              # normalize the content to the most useful data type
              strtbl = [[normalize(it) for it in row] for row in tbl] 
          
              # next, for each column we compute the maximum width needed
              w = [0 for _ in tbl[0]]
              for row in strtbl:
                  for ncol, it in enumerate(row):
                      w[ncol] = max(w[ncol], len(it))
          
              # a string is built iterating on the rows and the items of `strtbl`:
              #   items are  prepended white space to an uniform column width
              #   formatted items are `join`ed using `pad` (by default "  ")
              #   eventually we join the rows using newlines and return
              return sep.join(pad.join(' '*(wid-len(it))+it for wid, it in zip(w, row))
                                                                for row in strtbl)
          

          函数签名ftable(tbl, pad=' ', sep='\n', normalize=str) 及其默认参数旨在 提供最大的灵活性。

          你可以自定义

          • pad叮,
          • sep分隔符,(例如,pad='&amp;', sep='\\\\\n' 拥有 LaTeX 表格的大部分内容)
          • 用于将输入规范化为公共字符串的函数 格式 --- 默认情况下,为了最大的通用性,它是 str 但如果 你知道你所有的数据都是浮点数lambda item: "%.4f"%item 可能是一个合理的选择,等等。

          表面测试:

          我需要一些测试数据,可能涉及不同宽度的列 所以算法需要更复杂一点(但只是一点点;)

          In [1]: from random import randrange
          
          In [2]: table = [[randrange(10**randrange(10)) for i in range(5)] for j in range(3)]
          
          In [3]: table
          Out[3]: 
          [[974413992, 510, 0, 3114, 1],
           [863242961, 0, 94924, 782, 34],
           [1060993, 62, 26076, 75832, 833174]]
          
          In [4]: print(ftable(table))
          974413992  510      0   3114       1
          863242961    0  94924    782      34
            1060993   62  26076  75832  833174
          
          In [5]: print(ftable(table, pad='|'))
          974413992|510|    0| 3114|     1
          863242961|  0|94924|  782|    34
            1060993| 62|26076|75832|833174
          

          【讨论】:

            【解决方案8】:

            我以前也有同样的问题。我找不到任何可以帮助我的东西,所以我最终在下面创建了 PrintTable--code 课程。还有一个输出。用法很简单:

            ptobj = PrintTable(yourdata, column_captions, column_widths, text_aligns)
            ptobj.print()
            

            或一行:

            PrintTable(yourdata, column_captions, column_widths, text_aligns).print()
            

            输出:

            -------------------------------------------------------------------------------------------------------------
              Name                                     | Column 1   | Column 2   | Column 3   | Column 4   | Column 5    
            -------------------------------------------------------------------------------------------------------------
              Very long name 0                         |          0 |          0 |          0 |          0 |          0  
              Very long name 1                         |          1 |          2 |          3 |          4 |          5  
              Very long name 2                         |          2 |          4 |          6 |          8 |         10  
              Very long name 3                         |          3 |          6 |          9 |         12 |         15  
              Very long name 4                         |          4 |          8 |         12 |         16 |         20  
              Very long name 5                         |          5 |         10 |         15 |         20 |         25  
              Very long name 6                         |          6 |         12 |         18 |         24 |         30  
              Very long name 7                         |          7 |         14 |         21 |         28 |         35  
              Very long name 8                         |          8 |         16 |         24 |         32 |         40  
              Very long name 9                         |          9 |         18 |         27 |         36 |         45  
              Very long name 10                        |         10 |         20 |         30 |         40 |         50  
              Very long name 11                        |         11 |         22 |         33 |         44 |         55  
              Very long name 12                        |         12 |         24 |         36 |         48 |         60  
              Very long name 13                        |         13 |         26 |         39 |         52 |         65  
              Very long name 14                        |         14 |         28 |         42 |         56 |         70  
              Very long name 15                        |         15 |         30 |         45 |         60 |         75  
              Very long name 16                        |         16 |         32 |         48 |         64 |         80  
              Very long name 17                        |         17 |         34 |         51 |         68 |         85  
              Very long name 18                        |         18 |         36 |         54 |         72 |         90  
              Very long name 19                        |         19 |         38 |         57 |         76 |         95  
            -------------------------------------------------------------------------------------------------------------
            

            PrintTable的代码

            # -*- coding: utf-8 -*-
            
            # Class
            class PrintTable:
                def __init__(self, values, captions, widths, aligns):
                if not all([len(values[0]) == len(x) for x in [captions, widths, aligns]]):
                    raise Exception()
                self._tablewidth = sum(widths) + 3*(len(captions)-1) + 4
                self._values = values
                self._captions = captions
                self._widths = widths
                self._aligns = aligns
            
                def print(self):
                self._printTable()
            
                def _printTable(self):
                formattext_head = ""
                formattext_cell = ""
                for i,v in enumerate(self._widths):
                    formattext_head += "{" + str(i) + ":<" + str(v) + "} | "
                    formattext_cell += "{" + str(i) + ":" + self._aligns[i] + str(v) + "} | "
                formattext_head = formattext_head[:-3]
                formattext_head = "  " + formattext_head.strip() + "  "
                formattext_cell = formattext_cell[:-3]
                formattext_cell = "  " + formattext_cell.strip() + "  "
            
                print("-"*self._tablewidth)
                print(formattext_head.format(*self._captions))
                print("-"*self._tablewidth)
                for w in self._values:
                    print(formattext_cell.format(*w))
                print("-"*self._tablewidth)
            

            示范

            # Demonstration
            
            headername = ["Column {}".format(x) for x in range(6)]
            headername[0] = "Name"
            data = [["Very long name {}".format(x), x, x*2, x*3, x*4, x*5] for x in range(20)] 
            
            PrintTable(data, \
                   headername, \
                   [70, 10, 10, 10, 10, 10], \
                   ["<",">",">",">",">",">"]).print()
            

            【讨论】:

              【解决方案9】:

              一组通用函数,用于将任何 Python 数据结构(嵌套在一起的字典和列表)呈现为 HTML。

              from IPython.display import HTML, display
              
              def _render_list_html(l):
                  o = []
                  for e in l:
                      o.append('<li>%s</li>' % _render_as_html(e))
                  return '<ol>%s</ol>' % ''.join(o)
              
              def _render_dict_html(d):
                  o = []
                  for k, v in d.items():
                      o.append('<tr><td>%s</td><td>%s</td></tr>' % (str(k), _render_as_html(v)))
                  return '<table>%s</table>' % ''.join(o)
              
              def _render_as_html(e):
                  o = []
                  if isinstance(e, list):
                      o.append(_render_list_html(e))
                  elif isinstance(e, dict):
                      o.append(_render_dict_html(e))
                  else:
                      o.append(str(e))
                  return '<html><body>%s</body></html>' % ''.join(o)
              
              def render_as_html(e):
                  display(HTML(_render_as_html(e)))
              

              【讨论】:

                【解决方案10】:

                tabletext 很合适

                import tabletext
                
                data = [[1,2,30],
                        [4,23125,6],
                        [7,8,999],
                        ]
                
                print tabletext.to_text(data)
                

                结果:

                ┌───┬───────┬─────┐
                │ 1 │     2 │  30 │
                ├───┼───────┼─────┤
                │ 4 │ 23125 │   6 │
                ├───┼───────┼─────┤
                │ 7 │     8 │ 999 │
                └───┴───────┴─────┘
                

                【讨论】:

                • 这是 Python 2,请注意
                【解决方案11】:

                好的,所以这比我难一点:

                def print_matrix(list_of_list):
                    number_width = len(str(max([max(i) for i in list_of_list])))
                    cols = max(map(len, list_of_list))
                    output = '+'+('-'*(number_width+2)+'+')*cols + '\n'
                    for row in list_of_list:
                        for column in row:
                            output += '|' + ' {:^{width}d} '.format(column, width = number_width)
                        output+='|\n+'+('-'*(number_width+2)+'+')*cols + '\n'
                    return output
                

                这应该适用于可变数量的行、列和位数(对于数字)

                data = [[1,2,30],
                        [4,23125,6],
                        [7,8,999],
                        ]
                print print_matrix(data)
                >>>>+-------+-------+-------+
                    |   1   |   2   |  30   |
                    +-------+-------+-------+
                    |   4   | 23125 |   6   |
                    +-------+-------+-------+
                    |   7   |   8   |  999  |
                    +-------+-------+-------+
                

                【讨论】:

                  【解决方案12】:

                  您可以尝试使用以下功能

                  def tableIt(data):
                      for lin in data:
                          print("+---"*len(lin)+"+")
                          for inlin in lin:
                              print("|",str(inlin),"", end="")
                          print("|")
                      print("+---"*len(lin)+"+")
                  
                  data = [[1,2,3,2,3],[1,2,3,2,3],[1,2,3,2,3],[1,2,3,2,3]]
                  
                  tableIt(data)
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-01-22
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-10-26
                    • 1970-01-01
                    • 2019-04-28
                    • 1970-01-01
                    相关资源
                    最近更新 更多