-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdataframe.py
More file actions
44 lines (33 loc) · 1.57 KB
/
Copy pathdataframe.py
File metadata and controls
44 lines (33 loc) · 1.57 KB
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
"""Line items → pandas DataFrame → CSV.
The one shape that needs a word of explanation: a line-item array is a *bare* list, and
each cell inside each row carries its own confidence. `unwrap()` flattens a row into the
plain dict pandas wants; keeping the confidences means you can filter before you total.
pip install pandas
python examples/dataframe.py invoice.pdf out.csv
"""
import sys
import pandas as pd
from visionapi import VisionAPI, at_least, rows, unwrap, value
path = sys.argv[1] if len(sys.argv) > 1 else "invoice.pdf"
out = sys.argv[2] if len(sys.argv) > 2 else "line-items.csv"
vision = VisionAPI()
res = vision.analyze(file=path, preset="invoice")
result = res["result"]
records = []
for row in rows(result, "line_item"):
flat = unwrap(row)
# Carry the header down onto every line so the CSV stands on its own.
flat["invoice_id"] = value(result, "invoice_id")
flat["invoice_date"] = value(result, "invoice_date")
# A per-cell confidence check: anything but "high" on the money column is worth a look.
flat["amount_is_confident"] = at_least(row.get("amount"), "high")
records.append(flat)
frame = pd.DataFrame.from_records(records)
frame.to_csv(out, index=False)
print(frame.head().to_string())
print(f"\n{len(frame)} line(s) → {out}")
total = value(result, "total_amount") or value(result, "total")
if total is not None and "amount" in frame:
summed = frame["amount"].fillna(0).sum()
print(f"stated total {total} vs summed lines {summed:.2f}" +
(" ✓" if abs(summed - float(total)) < 0.01 else " ← worth a human look"))