Skip to content

Commit

Permalink
Adding a dialog to choose the column that is used as join when mergin…
Browse files Browse the repository at this point in the history
…g tables. (#23)

* GUI question to choose the column on which the table join will be based

* Adding little improvements

* Fix broken CI pipeline
  • Loading branch information
gacou54 authored Jul 26, 2021
1 parent b07c260 commit 129d7a2
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 18 deletions.
24 changes: 20 additions & 4 deletions othello/gis/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import functools
from typing import Dict, List

import pandas
from geopandas import GeoDataFrame

from othello.gis import io
Expand All @@ -19,7 +20,17 @@ def make_dataframe_with_common_columns(dfs: List[GeoDataFrame], common_columns:
return df


def add_weighted_columns_to_dataframe(df: GeoDataFrame, criteria_information: List[Dict]) -> GeoDataFrame:
def add_weighted_columns_to_dataframe(df: GeoDataFrame, criteria_information: List[Dict], join_on: str) -> GeoDataFrame:
"""Add the weighted criteria to the 'df' dataframe by joining data on the join_on column name.
Args:
df: Base GeoDataFrame
criteria_information: Criteria data that allows to retrieve the exact column from a table from a layer from aGDB file
join_on: Column name on which the table join will be based
Returns:
GeoDataFrame with the added criteria and the final score
"""
weighted_columns = []

for criterion_information in criteria_information:
Expand All @@ -29,11 +40,16 @@ def add_weighted_columns_to_dataframe(df: GeoDataFrame, criteria_information: Li
weight = criterion_information['weight']
criterion_name = criterion_information['criterion_name']

criterion_geoseries = io.read(filepath, layer=layer)[field]
df[criterion_name + '_np'] = criterion_geoseries
df[criterion_name + '_p'] = weight * criterion_geoseries
criterion_df = io.read(filepath, layer=layer)[[join_on, field]]
criterion_df.columns = [join_on, criterion_name + '_np']
criterion_df[criterion_name + '_p'] = weight * criterion_df[criterion_name + '_np']

df = pandas.merge(left=df, right=criterion_df, on=join_on)
weighted_columns.append(criterion_name + '_p')

# df[criterion_name + '_np'] = criterion_df
# df[criterion_name + '_p'] = weight * criterion_df

# Final score in a new series
df['FinalScore'] = [0 for _ in range(len(df))]
for column in weighted_columns:
Expand Down
25 changes: 19 additions & 6 deletions othello/ui/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import geopandas
from PySide2 import QtCore, QtWidgets
from PySide2.QtWidgets import QMessageBox
from PySide2.QtWidgets import QInputDialog, QMessageBox

from othello import gis
from othello.ui import errors
Expand Down Expand Up @@ -35,7 +35,7 @@ def __init__(self, parent):
self.table.setGeometry(QtCore.QRect(20, 80, 731, 400))
self.table.setRowCount(0)
self.table.setColumnCount(5)
self.table.setHorizontalHeaderLabels(['Criterion', 'Layer', 'Field', 'Weight [0-1]', 'criterion name'])
self.table.setHorizontalHeaderLabels(['Criterion', 'Layer', 'Field', 'Weight [0-1]', 'Criterion name'])

header = self.table.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
Expand Down Expand Up @@ -71,10 +71,23 @@ def aggregate(self, to_new_file: bool, force_normalized_weights: bool = True):
self.assert_weights_are_normalized()

common_columns = gis.util.find_common_columns(self.dfs)

# Choose the column on which the table join will be based
join_on_column, has_not_failed = QInputDialog.getItem(
self,
'Question',
'Choose the column on which the table join will be based.',
common_columns,
0,
False
)
if not (has_not_failed and join_on_column):
return

df = gis.util.make_dataframe_with_common_columns(self.dfs, common_columns)

if to_new_file:
filepath = QtWidgets.QFileDialog.getSaveFileName(self)[0]
filepath = QtWidgets.QFileDialog.getSaveFileName(self, 'Save to file', '', 'GDB (*.gdb)')[0]
else:
filepath = QtWidgets.QFileDialog.getExistingDirectory(self)

Expand All @@ -85,7 +98,7 @@ def aggregate(self, to_new_file: bool, force_normalized_weights: bool = True):
popup.show()
return

df = self.add_weighted_columns(df)
df = self.add_weighted_columns(df, join_on_column)
gis.io.write(df, filepath, layer=f'FinalLayer-{datetime.now().strftime("%Y-%m-%d-%H:%M:%S")}')

popup = Popup(f'The file "{filepath}" have been written.', self)
Expand Down Expand Up @@ -154,7 +167,7 @@ def assert_no_duplicates_in_criterion_names(self):

criterion_names.add(criterion_name)

def add_weighted_columns(self, df: geopandas.GeoDataFrame) -> geopandas.GeoDataFrame:
def add_weighted_columns(self, df: geopandas.GeoDataFrame, join_on: str) -> geopandas.GeoDataFrame:
criteria_information = []

for row_index in range(self.table.rowCount()):
Expand All @@ -166,7 +179,7 @@ def add_weighted_columns(self, df: geopandas.GeoDataFrame) -> geopandas.GeoDataF
'criterion_name': self.table.item(row_index, 4).text(),
})

df = gis.util.add_weighted_columns_to_dataframe(df, criteria_information)
df = gis.util.add_weighted_columns_to_dataframe(df, criteria_information, join_on=join_on)

return df

Expand Down
10 changes: 5 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ click-plugins==1.1.1
cligj==0.7.1
colorama==0.4.4
cx-Freeze==6.5.3
Fiona @ https://download.lfd.uci.edu/pythonlibs/r4tycu3t/Fiona-1.8.20-cp38-cp38-win_amd64.whl
Fiona @ https://download.lfd.uci.edu/pythonlibs/y2rycu7g/Fiona-1.8.20-cp38-cp38-win_amd64.whl
future==0.18.2
GDAL @ https://download.lfd.uci.edu/pythonlibs/r4tycu3t/GDAL-3.3.1-cp38-cp38-win_amd64.whl
GDAL @ https://download.lfd.uci.edu/pythonlibs/y2rycu7g/GDAL-3.3.1-cp38-cp38-win_amd64.whl
geopandas==0.9.0
importlib-metadata==3.7.3
iniconfig==1.1.1
Expand All @@ -21,14 +21,14 @@ pefile==2019.4.18
pluggy==0.13.1
py==1.10.0
pyparsing==2.4.7
pyproj @ https://download.lfd.uci.edu/pythonlibs/r4tycu3t/pyproj-3.0.1-cp38-cp38-win_amd64.whl
pyproj==3.0.1
PySide2==5.15.2
pytest==6.2.2
python-dateutil==2.8.1
pytz==2021.1
pywin32-ctypes==0.2.0
Rtree @ https://download.lfd.uci.edu/pythonlibs/r4tycu3t/Rtree-0.9.7-cp38-cp38-win_amd64.whl
Shapely @ https://download.lfd.uci.edu/pythonlibs/r4tycu3t/Shapely-1.7.1-cp38-cp38-win_amd64.whl
Rtree==0.9.7
Shapely==1.7.1
shiboken2==5.15.2
six==1.15.0
toml==0.10.2
Expand Down
7 changes: 4 additions & 3 deletions tests/gis/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def test_make_dataframe_with_common_columns(self, dfs, common_columns, expected_

assert list(result.columns) == expected_columns

@pytest.mark.parametrize('df, criteria_info, expected_first_criterion_score, expected_second_criterion_score, expected_first_final_score', [(
@pytest.mark.parametrize('df, criteria_info, join_on_column, expected_first_criterion_score, expected_second_criterion_score, expected_first_final_score', [(
geopandas.read_file(GDB_FILEPATH, driver='FileGDB', layer='ArretsTEST_ON'),
[{
'filepath': GDB_FILEPATH,
Expand All @@ -63,12 +63,13 @@ def test_make_dataframe_with_common_columns(self, dfs, common_columns, expected_
'weight': .5,
'criterion_name': 'another-criterion',
}],
'ID',
(8, 8 * .5),
(-46.67, -46.67 * .5),
8 * .5 - 46.67 * .5,
)])
def test_add_weighted_columns_to_dataframe(self, df, criteria_info, expected_first_criterion_score, expected_second_criterion_score, expected_first_final_score):
result = gis.util.add_weighted_columns_to_dataframe(df, criteria_info)
def test_add_weighted_columns_to_dataframe(self, df, criteria_info, join_on_column, expected_first_criterion_score, expected_second_criterion_score, expected_first_final_score):
result = gis.util.add_weighted_columns_to_dataframe(df, criteria_info, join_on_column)

assert 'FinalScore' in result.columns
assert result['a-criterion_np'][0] == expected_first_criterion_score[0]
Expand Down

0 comments on commit 129d7a2

Please sign in to comment.