Plot.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #
  2. # Copyright (c) Daniel Sheffield 2023
  3. #
  4. # All rights reserved
  5. #
  6. # THIS SOFTWARE IS PROVIDED AS IS WITHOUT WARRANTY
  7. from app.data.QueryManager import QueryManager, display_mapper
  8. from datetime import date, datetime
  9. import seaborn as sns
  10. import pandas as pd
  11. import matplotlib.pyplot as plt
  12. import os
  13. import sys
  14. from sqlite3 import Cursor
  15. import psycopg
  16. from db_credentials import HOST, PASSWORD
  17. ALL_UNITS = {'g','kg','mL','L','Pieces','Bunches','Bags'}
  18. host = f'host={HOST}'
  19. password = f'password={PASSWORD}'
  20. user = os.getenv('USER')
  21. conn = psycopg.connect(f"{host} dbname=grocery user={user} {password}")
  22. cur: Cursor = conn.cursor()
  23. cur.execute("BEGIN")
  24. query_manager = QueryManager(cur, display_mapper)
  25. fields = dict()
  26. for k in ('group', 'category', 'product', 'unit'):
  27. options = query_manager.unique_suggestions(k, **fields)
  28. names = [ o for o in options ]
  29. matches = '\t'.join(names)
  30. print(f'{k.title()} names: {matches}')
  31. while (len(options) >=1):
  32. v = fields[k] if k in fields else ''
  33. fields[k] = v + input(f"{k.title()}: {v}")
  34. options = query_manager.unique_suggestions(k, **fields)
  35. if k == 'unit':
  36. options = sorted(set(options) | ALL_UNITS)
  37. if fields[k] == '':
  38. choice = ''
  39. break
  40. elif len(options) == 1:
  41. choice = options[0]
  42. break
  43. elif fields[k].lower() in map(lambda x: x.lower(), options):
  44. choice = next(
  45. filter(lambda x: x.lower() == fields[k].lower(), options)
  46. )
  47. break
  48. elif len(options) == 0 and k == 'unit':
  49. choice = fields[k]
  50. break
  51. matches = '\t'.join(options)
  52. print(f'Matches ({k}): {matches}')
  53. if k != 'unit':
  54. fields[k] = (fields[k] and choice) or ''
  55. else:
  56. fields[k] = choice
  57. if fields[k] == '':
  58. print(f'Ignoring {k} {choice} as it does not exist')
  59. else:
  60. print(f'Selected {k}: {fields[k]}')
  61. print()
  62. fields = dict((k,v or None) for k,v in fields.items())
  63. unit = fields['unit'] or 'kg'
  64. if unit not in ALL_UNITS:
  65. print(f'Invalid unit: {unit}')
  66. exit(2)
  67. print(f'Getting data for selection:\n ')
  68. print(f'\n '.join([f'{k.title()}: {v}' for k,v in fields.items()]))
  69. d = pd.DataFrame(query_manager.get_historic_prices_data(unit, **dict((k,v) for k,v in fields.items() if k != 'unit')))
  70. if d.empty:
  71. sys.exit(1)
  72. print(d.info())
  73. print(d)
  74. sns.set_theme()
  75. now = datetime.now().date()
  76. d['ts_month'] = d['ts_raw'].apply(lambda x: date(x.date().year, x.date().month,1))
  77. p = d[d['ts_month'] == date(now.year,now.month,1) ].groupby(['ts_month','group',])['price', 'quantity'].sum()
  78. if not p.empty:
  79. p = p.reset_index().set_index('group')
  80. p['price'] = p['price'].apply(float)
  81. p['quantity'] = p['quantity'].apply(float)
  82. print(p.info())
  83. print(p)
  84. ax = p.plot.pie(y='quantity', figsize=(5, 5))
  85. ax.get_legend().remove()
  86. ax.set_xlabel('')
  87. ax.set_ylabel('')
  88. ax.set_title(f'Quantity ({unit})')
  89. plt.show()
  90. ax = p.plot.pie(y='price', figsize=(5, 5))
  91. ax.get_legend().remove()
  92. ax.set_xlabel('')
  93. ax.set_ylabel('')
  94. ax.set_title(f'Price ($)')
  95. plt.show()
  96. p = d.pivot_table(index=['ts_raw',], columns=['product',], values=['$/unit'], aggfunc='mean')
  97. p.columns = p.columns.droplevel()
  98. print(p.info())
  99. print(p)
  100. ax = sns.lineplot(data=p, markers=True)
  101. ax.set_xlabel('Time')
  102. ax.set_ylabel(f'$ / {unit}')
  103. plt.show()