Pretty Printing a dataframe do pandas

113

Como posso imprimir um dataframe do pandas como uma boa tabela baseada em texto, como a seguir?

+------------+---------+-------------+
| column_one | col_two |   column_3  |
+------------+---------+-------------+
|          0 |  0.0001 | ABCD        |
|          1 |  1e-005 | ABCD        |
|          2 |  1e-006 | long string |
|          3 |  1e-007 | ABCD        |
+------------+---------+-------------+
Ofer
fonte

Respostas:

180

Acabei de encontrar uma ótima ferramenta para essa necessidade, é chamada de tabular .

Ele imprime dados tabulares e trabalha com DataFrame.

from tabulate import tabulate
import pandas as pd

df = pd.DataFrame({'col_two' : [0.0001, 1e-005 , 1e-006, 1e-007],
                   'column_3' : ['ABCD', 'ABCD', 'long string', 'ABCD']})
print(tabulate(df, headers='keys', tablefmt='psql'))

+----+-----------+-------------+
|    |   col_two | column_3    |
|----+-----------+-------------|
|  0 |    0.0001 | ABCD        |
|  1 |    1e-05  | ABCD        |
|  2 |    1e-06  | long string |
|  3 |    1e-07  | ABCD        |
+----+-----------+-------------+

Nota:

Para suprimir índices de linha para todos os tipos de dados, passe showindex="never"ou showindex=False.

Romain
fonte
5
Se você não tem acesso ao que há de mais moderno, pode fazer tabulate([list(row) for row in df.values], headers=list(df.columns))para se livrar do índice
Pedro M Duarte
1
Não funciona muito bem quando você tem hierarquias em índices de linhas e colunas.
Siddharth de
Certifique-se de fazer print(tabulate(df, **kwargs))e não simplesmente tabulate(df, **kwargs); o último mostrará todas as novas linhas \n....
Dror
6
Para suprimir a coluna do índice esquerdo, pode-se desejar também adicionarshowindex=False
Arthur
23

Uma abordagem simples é produzir como html, o que o pandas faz fora da caixa :

df.to_html('temp.html')
ErichBSchulz
fonte
17

pandas> = 1,0

Se você deseja que uma função embutida despeje seus dados em alguma marcação do github, agora você tem uma. Dê uma olhada em to_markdown:

df = pd.DataFrame({"A": [1, 2, 3], "B": [1, 2, 3]}, index=['a', 'a', 'b'])  
print(df.to_markdown()) 

|    |   A |   B |
|:---|----:|----:|
| a  |   1 |   1 |
| a  |   2 |   2 |
| b  |   3 |   3 |

Aqui está o que parece no github:

insira a descrição da imagem aqui

Observe que você ainda precisará ter o tabulatepacote instalado.

cs95
fonte
16

Se você estiver no bloco de notas Jupyter, poderá executar o código a seguir para exibir interativamente o dataframe em uma tabela bem formatada.

Esta resposta se baseia na resposta to_html ('temp.html') acima, mas em vez de criar um arquivo exibe a tabela bem formatada diretamente no bloco de notas:

from IPython.display import display, HTML

display(HTML(df.to_html()))

Crédito para este código devido ao exemplo em: Mostrar DataFrame como tabela no iPython Notebook

Mark Andersen
fonte
15

Você pode usar o prettytable para renderizar a tabela como texto. O truque é converter o data_frame em um arquivo csv na memória e fazer com que ele seja lido de maneira adequada. Aqui está o código:

from StringIO import StringIO
import prettytable    

output = StringIO()
data_frame.to_csv(output)
output.seek(0)
pt = prettytable.from_csv(output)
print pt
Ofer
fonte
Que versão de pandas era essa?
WAF de
4
AFAIK, prettytableé amplamente considerado abandonware. Vergonha também, pois era um belo pacote. :(
dmn
@dmn então não é mais mantido?
muon
prettytablenão teve um lançamento desde 6 de abril de 2013. tabulateé seu predecessor espiritual e tem lançamentos regulares, sendo o mais recente em 24 de janeiro de 2019.
noddy
7

Usei a resposta de Ofer por um tempo e a achei ótima na maioria dos casos. Infelizmente, devido a inconsistências entre o to_csv do pandas e o from_csv do prettytable, tive que usar o prettytable de uma maneira diferente.

Um caso de falha é um dataframe contendo vírgulas:

pd.DataFrame({'A': [1, 2], 'B': ['a,', 'b']})

Prettytable levanta um erro no formulário:

Error: Could not determine delimiter

A função a seguir trata desse caso:

def format_for_print(df):    
    table = PrettyTable([''] + list(df.columns))
    for row in df.itertuples():
        table.add_row(row)
    return str(table)

Se você não se importa com o índice, use:

def format_for_print2(df):    
    table = PrettyTable(list(df.columns))
    for row in df.itertuples():
        table.add_row(row[1:])
    return str(table)
ejrb
fonte
Olá, a format_for_print()função não parece estar imprimindo o índice do Pandas DataFrame. Eu defino o índice usando, df.index.name = 'index'mas isso não imprime a coluna do índice com um nome.
edesz
2

Seguindo a resposta de Mark, se você não estiver usando o Jupyter por algum motivo, por exemplo, se quiser fazer alguns testes rápidos no console, você pode usar o DataFrame.to_stringmétodo, que funciona a partir de - pelo menos - Pandas 0.12 (2014) .

import pandas as pd

matrix = [(1, 23, 45), (789, 1, 23), (45, 678, 90)]
df = pd.DataFrame(matrix, columns=list('abc'))
print(df.to_string())

#  outputs:
#       a    b   c
#  0    1   23  45
#  1  789    1  23
#  2   45  678  90
sigint
fonte
0

Talvez você esteja procurando algo assim:

def tableize(df):
    if not isinstance(df, pd.DataFrame):
        return
    df_columns = df.columns.tolist() 
    max_len_in_lst = lambda lst: len(sorted(lst, reverse=True, key=len)[0])
    align_center = lambda st, sz: "{0}{1}{0}".format(" "*(1+(sz-len(st))//2), st)[:sz] if len(st) < sz else st
    align_right = lambda st, sz: "{0}{1} ".format(" "*(sz-len(st)-1), st) if len(st) < sz else st
    max_col_len = max_len_in_lst(df_columns)
    max_val_len_for_col = dict([(col, max_len_in_lst(df.iloc[:,idx].astype('str'))) for idx, col in enumerate(df_columns)])
    col_sizes = dict([(col, 2 + max(max_val_len_for_col.get(col, 0), max_col_len)) for col in df_columns])
    build_hline = lambda row: '+'.join(['-' * col_sizes[col] for col in row]).join(['+', '+'])
    build_data = lambda row, align: "|".join([align(str(val), col_sizes[df_columns[idx]]) for idx, val in enumerate(row)]).join(['|', '|'])
    hline = build_hline(df_columns)
    out = [hline, build_data(df_columns, align_center), hline]
    for _, row in df.iterrows():
        out.append(build_data(row.tolist(), align_right))
    out.append(hline)
    return "\n".join(out)


df = pd.DataFrame([[1, 2, 3], [11111, 22, 333]], columns=['a', 'b', 'c'])
print tableize(df)
Resultado:
+ ------- + ---- + ----- +
| a | b | c |
+ ------- + ---- + ----- +
| 1 | 2 | 3 |
| 11111 22 333 |
+ ------- + ---- + ----- +
Pafkone
fonte
-5

Eu queria uma impressão em papel de um dataframe, mas também queria adicionar alguns resultados e comentários na mesma página. Eu trabalhei com os itens acima e não consegui o que queria. Acabei usando as instruções file.write (df1.to_csv ()) e file.write (",,, blah ,,,,,, blah") para colocar meus extras na página. Quando abri o arquivo csv, ele foi direto para uma planilha que imprimiu tudo no ritmo e formato certos.

Jon
fonte