リストを表形式のデータとして印刷する


366

私はPythonに非常に慣れていないため、印刷出力用にデータを適切にフォーマットするのに苦労しています。

2つの見出しに使用される1つのリストと、表のコンテンツになるマトリックスがあります。そのようです:

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
+1、私は昨晩同じことをやろうとしていた。コマンドラインに出力しようとしているだけですか、それともGUIモジュールを使用していますか?
HellaMad

コマンドラインに出力するだけです。ただし、ユニットテストのケースに合格する必要があるため、ここではフォーマットが非常に重要です。
hjweide 2012年



行と列のラベルが同じであるため、ここでの要件はかなり特殊化されていることに注意してください。したがって、この特定のケースでは、アドホックコードはこれがいかに簡単かを示す良い例です。しかし、ここでの他のソリューションは、より一般的なテーブル表示に適している場合があります。
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()およびFormat Specification Mini-Languageに依存しています


3
python2.6を使用している場合は、row_formatにteam_listインデックスを追加することを忘れないでください。row_format= "{0:> 15} {1:> 15} {2:> 15}"
LuisMuñoz14年

1
本文のデータがヘッダーよりも大きい場合は、データの最初の行に基づいて列幅を設定できます。data [0]のtの場合: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

tabulateには、ヘッダーとテーブル形式を指定する多くのオプションがあります。

print(tabulate([['Alice', 24], ['Bob', 19]], headers=['Name', 'Age'], tablefmt='orgtbl'))
| Name   |   Age |
|--------+-------|
| Alice  |    24 |
| Bob    |    19 |

2. PrettyTablehttps : //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. texttablehttps : //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. termtableshttps : //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テーブル形式を読み書きできます。

13
tabulateは、データ中心のCLIツールを構築するための非常に便利なツールであることがわかりました。それとクリック(pip install click)を組み合わせると、本格的なシチューができます。
alexbw 2014年

4
これは素晴らしいです、ありがとう。個人的には、この3つのうちどちらを選びますか?
ジムRaynor

素晴らしい返信!PrettyTableは非常に優れている-他の2つのオプションの完璧なバランス。
edesz 2016年

2
terminaltablesは中国語、おそらく英語以外の言語に
適してい

5
私はメインパッケージとIMO "beautifultable"で遊んだところです-最高の、維持された、良いAPIとdoco、色のサポート。"texttable"-優れた、維持された、優れたAPIですが、色付きで使用するとテーブルが整列しなくなります。"terminaltables"-良い、コード例によるdoco。「PrettyTable」-わかりましたが、古いテーブルの「タイトル」は機能しません。"Tabulate"-良いですが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 2012年

26
出力の書式設定にパンダを使用することは、Overkill(大文字のOを意図)のように見えます。
Niels Bom

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」を2回使用しました。各パーツを分解するには:

'-' (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'])場所で使用することになりました.2f
Ross

25

Python 3.4で動作するようにSven Marnachの回答を更新します。

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

これはあなたが探しているものだと思います。

これは、テーブルエントリに必要な最大幅を計算し、rjustljustを使用してデータをきれいに出力する単純なモジュールです。

左見出しを右揃えにする場合は、次の呼び出しを変更します。

 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 = 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 |
+-----------------------+

色も使えます。

色を使用するには、colorオプションを使用し(デフォルトでは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))

それからあなたは得るでしょう:

ここに画像の説明を入力してください

色の印刷は機能しない場合がありますが、色付きのテキストを印刷する他のライブラリとまったく同じように機能します。私はテストし、すべての単一の色が動作します。デフォルトの34mANSIエスケープシーケンスを使用する場合のように、青もめちゃくちゃになりません(何が問題なのかわからない場合)。とにかく、それはすべてすべての色がシステムのデフォルトではなく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

次の関数は、要求されたテーブル(numpyの有無にかかわらず)をPython 3(おそらくPython 2)で作成します。各列の幅を、最も長いチーム名の幅と一致するように設定することにしました。各列にチーム名の長さを使用する場合は変更できますが、さらに複雑になります。

注:Python 2で直接同等のものを使用するにzipizip、itertools のwith を置き換えることができます。

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 2012年

2

これは、単純な列を出力する方法を探しているだけでした。no-fuss列が必要な場合は、これを使用できます。

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

編集:私はできるだけシンプルにしようとしていたため、チームリストを使用する代わりに手動でいくつかのことを行いました。OPの実際の質問に一般化するには:

#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の回答はすでにそれを満たし、より幅広いラベル長を処理できるため、より堅牢です。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.