Разбить пандасный фрейм данных с помощью уникального;Отображать как отдельные таблицы в Jinja2 - PullRequest
0 голосов
/ 24 сентября 2019

Я работаю над проектом, в котором я загружаю файл .csv в фрейм данных pandas и создаю отчет .PDF, используя Python 3.6 + pandas + jinja2 + weasyprint.

csv -> pandas ->jinja2 -> weasyprint

Вот мой вызов: Один из фреймов данных pandas содержит информацию, которую я хочу разделить на уникальные записи в одном из его столбцов, а затем отобразить отдельные таблицы в jinja2 для каждогоиз этих расколов.

Пример фрейма данных:

         Clothing  Color   Size
    0    Shirt     Blue    M
    1    Shirt     Blue    L
    2    Shirt     Black   L
    3    Pants     Black   L
    4    Pants     Blue    XL
    5    Jacket    Blue    L
    6    Jacket    Brown   L

Я могу успешно отправить этот единственный фрейм данных Pandas в jinja2 в целом, назначив df.to_html () jinja2 template_vars.

template_vars = {"title" : "My Title",
                 "df": df.to_html()
                 }                    

, а затем в файле template.html, вызывая его, указав:

<div class="table_standard campaign_kpis_table">
 {{ campaign_kpis }}
</div> 

Теперь я хочу иметь возможность взять фрейм данных Pandas и разделить его на несколько фреймов данных на основе уникальногопредметы в одном столбце.В этом примере «Цвет».

Я могу сделать это, используя:

df_splits = (df['Color'].unique())

Затем, зная все уникальные записи, я могу перебрать их и получить отдельный "фрейм" для фрейма данных,Скажите, пожалуйста, есть ли здесь слово лучше, чем «разделить», и я отредактирую.:)

Так что я могу легко распечатать эти отдельные сплиты в терминале, выполнив что-то вроде:

for df_split in df_splits:
    df_split = df.loc[df['Color']==df_split]
    print (df_split)

Но как отослать их в jinja2 для отображения в виде отдельных таблиц?

Для моих целей в исходном фрейме данных может быть от 1 до 10 уникальных цветов.Количество уникальных записей всегда будет меняться, в зависимости от того, что на складе.Насколько я понимаю, это создаст от 1 до 10 отдельных разбиений фрейма данных.

Что я пишу, чтобы jinja2 создавал таблицы для каждого из этих разбиений данных?

Пожалуйста, дайте мне знать, если вам нужно больше кода, или я не смог адекватно объяснить мою ситуацию.

Полный код раздела "-> jinja2 -> weasyprint" основан на https://pbpython.com/pdf-reports.html.

В настоящее время он выглядит следующим образом:

from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('.'))

template = env.get_template("templates/template.html")

template_vars = {"df": df.to_html(),
             }

html_out = template.render(template_vars)

with open("/path/to/report.html", "w") as fh:
fh.write(html_out)

from weasyprint import HTML
HTML(string=html_out).write_pdf("/path/to/report.pdf", stylesheets=["templates/style.css"])

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Вместо уникального () вы ищете панд groupby (). Вот документация .
Вот шаги:

Вы можете создать групповой объект, используя gb = df.groupby('Color') Вы можете думать об объекте, который выглядит следующим образом:


[('Black',   <black_dataframe>)
('Blue',   <blue_dataframe>)
('Brown',   <brown_dataframe>)]

ограждающая структура на самом деле не является списком, а действует как единое целое.это итеративно.


создайте шаблон с именем mytemplate.html в той же папке, что и код для его запуска (на данный момент).

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>{{title}}</title>
</head>
<body>
   {% for results in data.values() %}
        {{ results | safe}}
    {% endfor %}
</body>
</html>

Вы отправите его с помощью:

from jinja2 import Environment, FileSystemLoader 
import webbrowser as wb 
from pathlib import Path
import io
import pandas as pd
df = pd.read_csv(io.StringIO('Shirt,Blue,M\nShirt,Blue,L\nShirt,Black,L\nPants,Black,L\nPants,Blue,XL\nJacket,Blue,L\nJacket,Brown,L\n'), names=['Clothing', 'Color', 'Size'])
gb = df.groupby('Color')
env = Environment(loader=FileSystemLoader('.'))
template = env.get_template("mytemplate.html") 
data = {x:y.to_html() for x,y in gb} 
template_vars = {'title': "Tables, Tables everywhere", 'data' : data} 
html_out = template.render(template_vars)  
Path('myoutfile.html').write_text(html_out) 
wb.open(f"""file://{Path('.').absolute()}/myoutfile.html""")  
0 голосов
/ 24 сентября 2019

Передача данных и df_splits непосредственно в jinja2, а затем используйте цикл for в jinja2

import pandas as pd
from jinja2 import Environment

df = pd.DataFrame([('Shirt','Blue','M'), ('Shirt','Blue','L'), ('Shirt','Black','L'), ('Pants','Black','L'), ('Pants','Blue','XL'), ('Jacket','Blue','L'), ('Jacket','Brown','L')], columns=['Clothing', 'Color', 'Size'])

env = Environment()
tmpl = env.from_string( '''
{% for df_split in df_splits %}
<div>
{{df.loc[df['Color'] == df_split].to_html()}}
</div>
{% endfor %}''')

print(tmpl.render(df=df,df_splits = df['Color'].unique()))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...