【问题标题】:Export Pandas DataFrame into a PDF file using Python使用 Python 将 Pandas DataFrame 导出为 PDF 文件
【发布时间】:2021-11-05 15:17:18
【问题描述】:

在 Pandas 中为数据框生成 PDF 的有效方法是什么?

【问题讨论】:

    标签: python pdf pandas reportlab pypdf


    【解决方案1】:

    第一个带有matplotlib 的绘图表然后生成pdf

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_pdf import PdfPages
    
    df = pd.DataFrame(np.random.random((10,3)), columns = ("col 1", "col 2", "col 3"))
    
    #https://stackoverflow.com/questions/32137396/how-do-i-plot-only-a-table-in-matplotlib
    fig, ax =plt.subplots(figsize=(12,4))
    ax.axis('tight')
    ax.axis('off')
    the_table = ax.table(cellText=df.values,colLabels=df.columns,loc='center')
    
    #https://stackoverflow.com/questions/4042192/reduce-left-and-right-margins-in-matplotlib-plot
    pp = PdfPages("foo.pdf")
    pp.savefig(fig, bbox_inches='tight')
    pp.close()
    

    参考:

    How do I plot only a table in Matplotlib?

    Reduce left and right margins in matplotlib plot

    【讨论】:

    • 与 LaTeX 或 troff 相比,这些通过 matplotlib 生成的表格看起来不太好。
    • @Merlin,df.to_latex 可以输出 pdf 文件吗?流程/要求是什么?
    【解决方案2】:

    这是我使用 sqlite3、pandas 和 pdfkit 从 sqlite 数据库中执行此操作的方法

    import pandas as pd
    import pdfkit as pdf
    import sqlite3
    
    con=sqlite3.connect("baza.db")
    
    df=pd.read_sql_query("select * from dobit", con)
    df.to_html('/home/linux/izvestaj.html')
    nazivFajla='/home/linux/pdfPrintOut.pdf'
    pdf.from_file('/home/linux/izvestaj.html', nazivFajla)
    

    【讨论】:

    • pdfkit 不适用于 windows64
    • 效果很好!在 Mac 上安装 Pdfkit:pip install pdfkit && brew install Caskroom/cask/wkhtmltopdf
    【解决方案3】:

    一种方法是使用降价。您可以使用df.to_html()。这会将数据框转换为 html 表。从那里您可以将生成的 html 放入降价文件 (.md)(请参阅 http://daringfireball.net/projects/markdown/basics)。从那里,有一些实用程序可以将 markdown 转换为 pdf (https://www.npmjs.com/package/markdown-pdf)。

    此方法的一个多合一工具是使用 Atom 文本编辑器 (https://atom.io/)。在那里您可以使用扩展程序,搜索“markdown to pdf”,这将为您进行转换。

    注意:最近使用to_html() 时,出于某种原因,我不得不删除多余的“\n”字符。我选择使用Atom -> Find -> '\n' -> Replace ""。

    总的来说,这应该可以解决问题!

    【讨论】:

    • 我认为将中间步骤转换为 HTML,然后 Markdown(甚至没有标准规范),然后转换为 pdf 的解决方案不是一个好方法。
    • 您现在可以使用.to_markdown() 来完全避免使用 HTML。
    【解决方案4】:

    这是一个带有中间 pdf 文件的解决方案。

    这个表格用一些最小的 css 打印得很漂亮。

    pdf 转换是用 weasyprint 完成的。你需要pip install weasyprint。

    # Create a pandas dataframe with demo data:
    import pandas as pd
    demodata_csv = 'https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv'
    df = pd.read_csv(demodata_csv)
    
    # Pretty print the dataframe as an html table to a file
    intermediate_html = '/tmp/intermediate.html'
    to_html_pretty(df,intermediate_html,'Iris Data')
    # if you do not want pretty printing, just use pandas:
    # df.to_html(intermediate_html)
    
    # Convert the html file to a pdf file using weasyprint
    import weasyprint
    out_pdf= '/tmp/demo.pdf'
    weasyprint.HTML(intermediate_html).write_pdf(out_pdf)
    
    # This is the table pretty printer used above:
    
    def to_html_pretty(df, filename='/tmp/out.html', title=''):
        '''
        Write an entire dataframe to an HTML file
        with nice formatting.
        Thanks to @stackoverflowuser2010 for the
        pretty printer see https://stackoverflow.com/a/47723330/362951
        '''
        ht = ''
        if title != '':
            ht += '<h2> %s </h2>\n' % title
        ht += df.to_html(classes='wide', escape=False)
    
        with open(filename, 'w') as f:
             f.write(HTML_TEMPLATE1 + ht + HTML_TEMPLATE2)
    
    HTML_TEMPLATE1 = '''
    <html>
    <head>
    <style>
      h2 {
        text-align: center;
        font-family: Helvetica, Arial, sans-serif;
      }
      table { 
        margin-left: auto;
        margin-right: auto;
      }
      table, th, td {
        border: 1px solid black;
        border-collapse: collapse;
      }
      th, td {
        padding: 5px;
        text-align: center;
        font-family: Helvetica, Arial, sans-serif;
        font-size: 90%;
      }
      table tbody tr:hover {
        background-color: #dddddd;
      }
      .wide {
        width: 90%; 
      }
    </style>
    </head>
    <body>
    '''
    
    HTML_TEMPLATE2 = '''
    </body>
    </html>
    '''
    

    感谢@stackoverflowuser2010 提供漂亮的打印机,请参阅stackoverflowuser2010 的回答https://stackoverflow.com/a/47723330/362951

    我没有使用 pdfkit,因为我在无头机器上遇到了一些问题。但是 weasyprint 很棒。

    【讨论】:

    • 你知道如何强制分页吗?假设我有一个 pandas 数据框的几个表切片,我希望每个表都从一个新页面开始。这可能吗?我应该在什么时候编辑 html 代码?
    • 谢谢!如何使其以横向/不同的页面大小打印?
    【解决方案5】:

    参考这两个我觉得有用的例子:

    简单的 CSS 代码保存在与 ipynb 相同的文件夹中:

    /* includes alternating gray and white with on-hover color */
    
    .mystyle {
        font-size: 11pt; 
        font-family: Arial;
        border-collapse: collapse; 
        border: 1px solid silver;
    
    }
    
    .mystyle td, th {
        padding: 5px;
    }
    
    .mystyle tr:nth-child(even) {
        background: #E0E0E0;
    }
    
    .mystyle tr:hover {
        background: silver;
        cursor: pointer;
    }
    

    python代码:

    pdf_filepath = os.path.join(folder,file_pdf)
    demo_df = pd.DataFrame(np.random.random((10,3)), columns = ("col 1", "col 2", "col 3"))
    
    table=demo_df.to_html(classes='mystyle')
    
    html_string = f'''
    <html>
      <head><title>HTML Pandas Dataframe with CSS</title></head>
      <link rel="stylesheet" type="text/css" href="df_style.css"/>
      <body>
        {table}
      </body>
    </html>
    '''
    
    HTML(string=html_string).write_pdf(pdf_filepath, stylesheets=["df_style.css"])
    

    【讨论】:

    • 最后一行的 HTML 是什么?
    • HTML 在 python 代码中生成为字符串。我不是 100% 确定你的问题是什么意思?
    • HTML 是从 python 的 'weasyprint' 模块导入的 - pypi.org/project/weasyprint
    • 另外请注意,如果您的系统没有足够新的libpango 版本,您可以固定weasyprint==52.5,它不依赖于libpango&gt;=1.44.0
    猜你喜欢
    • 1970-01-01
    • 2012-12-31
    • 2018-03-11
    • 2014-12-26
    • 1970-01-01
    • 1970-01-01
    • 2019-01-29
    相关资源
    最近更新 更多