You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
4.2 KiB
101 lines
4.2 KiB
import geojson
|
|
import numpy as np
|
|
import pandas as pd
|
|
import sqlalchemy
|
|
from django.conf import settings
|
|
from django.contrib.gis.geos import GEOSGeometry
|
|
from geojson import MultiPolygon
|
|
from tqdm import tqdm
|
|
|
|
from service import models
|
|
|
|
|
|
def raschet_real(df, koefs):
|
|
koef_summ = sum(koefs.values())
|
|
df['rate'] = df[list(koefs.keys())].apply(lambda x: sum([x[k] * koefs[k] for k in list(koefs.keys())]), axis=1)
|
|
df['rate'] = df['rate'] / koef_summ
|
|
return df
|
|
|
|
|
|
def raschet(tables, filters, koefs, method):
|
|
conn = sqlalchemy.create_engine(settings.DB_URL, connect_args={'options': '-csearch_path=public'})
|
|
msk_ao = filters.get('msk_ao')
|
|
msk_rayon = filters.get('msk_rayon')
|
|
rate_from = filters.get('rate_from', None)
|
|
rate_to = filters.get('rate_to', None)
|
|
category = filters.get('category', [])
|
|
categories = ','.join([f"'{c}'" for c in category])
|
|
points_df = None
|
|
nets_df = None
|
|
for table in tables:
|
|
if 'point' in table:
|
|
if msk_ao is not None:
|
|
query = f"select * from {table} where msk_ao={msk_ao} and category in ({categories});" if len(
|
|
categories) > 0 else f"select * from {table} where msk_ao={msk_ao};"
|
|
elif msk_rayon is not None:
|
|
query = f"select * from {table} where msk_rayon={msk_rayon} and category in ({categories});" if len(
|
|
categories) > 0 else f"select * from {table} where msk_rayon={msk_rayon};"
|
|
else:
|
|
query = f"select * from {table} where category in ({categories});" if len(
|
|
categories) > 0 else f"select * from {table};"
|
|
points = pd.read_sql(query, conn)
|
|
if method == 'rate':
|
|
points_df = raschet_real(points, koefs)
|
|
if rate_from is not None and rate_to is not None:
|
|
points_df = points_df[(points_df['rate'] >= rate_from) & (points_df['rate'] <= rate_to)]
|
|
else:
|
|
points_df = points[(points['model'] >= rate_from) & (points['model'] <= rate_to)]
|
|
|
|
if 'net' in table:
|
|
if msk_ao is not None:
|
|
query = f"select * from {table} where msk_ao={msk_ao};"
|
|
elif msk_rayon is not None:
|
|
query = f"select * from {table} where msk_rayon={msk_rayon};"
|
|
else:
|
|
query = f"select * from {table};"
|
|
nets = pd.read_sql(query, conn)
|
|
if method == 'rate':
|
|
nets_df = raschet_real(nets, koefs)
|
|
if rate_from is not None and rate_to is not None:
|
|
nets_df = nets_df[(nets_df['rate'] >= rate_from) & (nets_df['rate'] <= rate_to)]
|
|
else:
|
|
nets_df = nets[(nets['model'] >= rate_from) & (nets['model'] <= rate_to)]
|
|
|
|
return points_df, nets_df
|
|
|
|
|
|
# ==============
|
|
|
|
def load_data(filepath: str):
|
|
models.PlacementPoint.objects.all().delete()
|
|
df = pd.read_csv(filepath)
|
|
df = df.replace(np.nan, None)
|
|
df = df.replace('NaT', None)
|
|
for row in tqdm(df.to_dict('records'), desc='Loading data...'):
|
|
data = {k: row[k] for k in row.keys() if k not in ['id', 'okrug', 'rayon', 'age_month']}
|
|
data['location_id'] = row['id']
|
|
data['okrug'] = models.AO.objects.get(name=row['okrug'])
|
|
data['rayon'] = models.Rayon.objects.get(name=row['rayon'])
|
|
models.PlacementPoint.objects.create(**data)
|
|
|
|
|
|
def load_ao_and_rayons(ao_filepath: str,
|
|
rayons_filepath: str):
|
|
models.AO.objects.all().delete()
|
|
models.Rayon.objects.all().delete()
|
|
gj = geojson.load(ao_filepath)
|
|
objs = gj['features']
|
|
for obj in tqdm(objs, desc='Loading AOs...'):
|
|
name = obj['properties']['okrug']
|
|
coords = obj['geometry']['coordinates']
|
|
models.AO.objects.create(**{'name': name, 'polygon': GEOSGeometry(str(MultiPolygon(coords)))})
|
|
gj = geojson.load(rayons_filepath)
|
|
objs = gj['features']
|
|
for obj in tqdm(objs, desc='Loading Rayons...'):
|
|
name = obj['properties']['rayon']
|
|
coords = obj['geometry']['coordinates']
|
|
okr = obj['properties']['okrug']
|
|
ao = models.AO.objects.get(name=okr)
|
|
models.Rayon.objects.create(**{'name': name, 'polygon': GEOSGeometry(str(MultiPolygon(coords))), 'AO': ao})
|
|
print('AO and Rayons loaded')
|