如何将pandas数据框显示为数据表?

时间:2018-02-05 12:21:39

标签: python jquery pandas flask datatables

我希望将一个表(一个pandas数据帧)显示为DataTable。在下面的简化示例中,我读取了用户提供的两个数字,用于确定表的行号和列号。然后,正确显示该表的元素数,但不会出现该表。

我认为问题是我以错误的方式传递了表格。当我尝试

return jsonify(number_elements=a * b,
                   my_table=df)

我收到错误

  

anaconda2 / lib / python2.7 / json / encoder.py“,第184行,默认情况下       提出TypeError(repr(o)+“不是JSON可序列化的”)

     

TypeError:0 1 2 3 0 51 35 10 84 1 30 60 79 24不是JSON   序列化

如果我使用

return jsonify(number_elements=a * b,
                   my_table=df.to_json())

然后没有错误,但表仍未显示。

我该如何正确地做到这一点?

我的index.html文件如下所示:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"
          rel="stylesheet">
     <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css"
           rel="stylesheet">
  <script type=text/javascript>
    $(function() {
      $('a#calculate').bind('click', function() {
        $.getJSON('/_get_table', {
          a: $('input[name="a"]').val(),
          b: $('input[name="b"]').val()
        }, function(data) {
          $("#elements").text(data.number_elements);
          $("#a_nice_table").DataTable(data.my_table);
        });
        return false;
      });
    });
  </script>
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Create a pretty table</h3>
      </div>

      <div>
        <p>Number of rows</p>
        <input type="text" size="5" name="a" value="2">
        <p>Number of columns</p>
        <input type="text" size="5" name="b" value="4">

        <p><a href="javascript:void();" id="calculate">get a pretty table</a></p>
         <p>Result</p>
        <p>Number of elements:</p>
          <span id="elements">Hallo</span><br>
          <span id="a_nice_table">Here should be a table</span>
      </div>
    </div>
  </body>
</html>

我的文件app.py如下所示:

from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np

# Initialize the Flask application
app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/_get_table')
def get_table():
    a = request.args.get('a', type=int)
    b = request.args.get('b', type=int)

    df = pd.DataFrame(np.random.randint(0, 100, size=(a, b)))

    return jsonify(number_elements=a * b,
                   my_table=df)


if __name__ == '__main__':
    app.run(debug=True)

2 个答案:

答案 0 :(得分:6)

这是我的实施。我做了一些优化,例如将你的js文件移到HTML的末尾:

<强>的index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
  </head>
  <body>
    <div class="container">
      <div class="header">
        <h3 class="text-muted">Create a pretty table</h3>
      </div>

      <div>
        <p>Number of rows</p>
        <input type="text" size="5" name="a" value="2">
        <p>Number of columns</p>
        <input type="text" size="5" name="b" value="4">

        <p><a href="javascript:void();" id="calculate">get a pretty table</a></p>
         <p>Result</p>
        <p>Number of elements:</p>
          <span id="elements">Hallo</span><br>
          <table id="a_nice_table">Here should be a table</table>
      </div>
    </div>
    <script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
    <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
    <script type="text/javascript">
      $(document).ready(function() {
        var table = null;
        $('a#calculate').bind('click', function() {
          $.getJSON('/_get_table', {
            a: $('input[name="a"]').val(),
            b: $('input[name="b"]').val()
          }, function(data) {
            $("#elements").text(data.number_elements);
            if (table !== null) {
              table.destroy();
              table = null;
              $("#a_nice_table").empty();
            }
            table = $("#a_nice_table").DataTable({
              data: data.my_table,
              columns: data.columns
            });
          });
          return false;
        });
      });
    </script>
  </body>
</html>

<强> app.py

from flask import Flask, render_template, request, jsonify
import pandas as pd
import numpy as np
import json

# Initialize the Flask application
app = Flask(__name__)


@app.route('/')
def index():
    return render_template('index.html')


@app.route('/_get_table')
def get_table():
    a = request.args.get('a', type=int)
    b = request.args.get('b', type=int)

    df = pd.DataFrame(np.random.randint(0, 100, size=(a, b)))

    return jsonify(number_elements=a * b,
                   my_table=json.loads(df.to_json(orient="split"))["data"],
                   columns=[{"title": str(col)} for col in json.loads(df.to_json(orient="split"))["columns"]])


if __name__ == '__main__':
    app.run(debug=True)

我修改了什么:

  1. 添加了js文件以呈现DataTable。
  2. 将js文件向下移动到HTML的底部。
  3. 在使用新数据刷新数据时,在js中添加了用于销毁和清除列的检查。
  4. 使用方向to_json的{​​{1}}方法生成DataTables的json数据。
  5. 还必须为要使用的DataTables添加一个split json字符串,该字符串在使用columns
  6. 后动态设置

    以下是如何使用熊猫的to_json来生成表格:

    <强>的index.html

    to_html

    <强> app.py

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
        <link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet">
      </head>
      <body>
        <div class="container">
          <div class="header">
            <h3 class="text-muted">Create a pretty table</h3>
          </div>
    
          <div>
            <p>Number of rows</p>
            <input type="text" size="5" name="a" value="2">
            <p>Number of columns</p>
            <input type="text" size="5" name="b" value="4">
    
            <p><a href="javascript:void();" id="calculate">get a pretty table</a></p>
             <p>Result</p>
            <p>Number of elements:</p>
              <span id="elements">Hallo</span><br>
              <div id="mytablediv">Here should be a table</div>
          </div>
        </div>
        <script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
        <script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js" type="text/javascript"></script>
        <script type="text/javascript">
          $(document).ready(function() {
            var table = null;
            $('a#calculate').bind('click', function() {
              $.getJSON('/_get_table', {
                a: $('input[name="a"]').val(),
                b: $('input[name="b"]').val()
              }, function(data) {
                $("#elements").text(data.number_elements);
                if (table !== null) {
                  table.destroy();
                  table = null;
                  $("#a_nice_table").empty();
                }
                $("#mytablediv").html(data.my_table);
                table = $("#a_nice_table").DataTable();
              });
              return false;
            });
          });
        </script>
      </body>
    </html>
    

    与以前的实施不同:

    1. 在HTML中,我必须添加父div才能保存生成的HTML表。在这种情况下,我称之为from flask import Flask, render_template, request, jsonify import pandas as pd import numpy as np # Initialize the Flask application app = Flask(__name__) @app.route('/') def index(): return render_template('index2.html') @app.route('/_get_table') def get_table(): a = request.args.get('a', type=int) b = request.args.get('b', type=int) df = pd.DataFrame(np.random.randint(0, 100, size=(a, b))) return jsonify(number_elements=a * b, my_table=df.to_html(classes='table table-striped" id = "a_nice_table', index=False, border=0)) if __name__ == '__main__': app.run(debug=True)
    2. 在JS方面的HTML中,我必须在生成数据后基本修改mytablediv的HTML内容。此HTML内容来自mytablediv输出。
    3. 在JS方面的HTML中,我没有必要将更多数据传递到to_html函数,因为这将使用HTML代码处理。
    4. DataTable中,我必须使用hackey方法为pandas生成HTML ID标记。 ID标签让JS知道要修改的元素。我使用了here的解决方案。
    5. app.py中,由于我现在正在生成HTML,因此我还必须明确指定其他表样式选项,例如app.pyborder=0,以模仿以前的实现。

答案 1 :(得分:1)

你不应该先生成html表吗?利用pandas.DataFrame.to_html()函数?实际上,documentation of DataTables显示了一个使用html表的示例。