diff options
Diffstat (limited to 'frontend/src/app/_elements/column-table')
3 files changed, 93 insertions, 66 deletions
diff --git a/frontend/src/app/_elements/column-table/column-table.component.css b/frontend/src/app/_elements/column-table/column-table.component.css index c3f5e4e8..aee2314e 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.css +++ b/frontend/src/app/_elements/column-table/column-table.component.css @@ -87,7 +87,7 @@ table ::ng-deep .mat-form-field-wrapper { } .no-pad { - padding: 1px; + padding: 2px; margin: 0; } diff --git a/frontend/src/app/_elements/column-table/column-table.component.html b/frontend/src/app/_elements/column-table/column-table.component.html index fac82bc2..53372574 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.html +++ b/frontend/src/app/_elements/column-table/column-table.component.html @@ -102,7 +102,7 @@ <td *ngFor="let colInfo of dataset.columnInfo; let i = index" class="pad-fix" [ngClass]="{'text-disabled' : !columnsChecked[i]}"> <p class="verticalAlign text-left" style="font-size:13px;" *ngIf="!colInfo.isNumber">Kategorijski</p> <mat-form-field *ngIf="colInfo.isNumber"> - <mat-select matNativeControl [(value)]="colInfo.columnType" [disabled]="!columnsChecked[i]"> + <mat-select matNativeControl [(value)]="colInfo.columnType" [disabled]="!columnsChecked[i]" (selectionChange)="columnTableChangeDetected()"> <mat-option [value]="ColumnType.categorical">Kategorijski</mat-option> <mat-option [value]="ColumnType.numerical">Numerički</mat-option> </mat-select> @@ -118,21 +118,19 @@ </tr> <tr> <th class="border-bottom">Statistika</th> - <td *ngFor="let colInfo of dataset.columnInfo; let i = index" [ngClass]="{'text-disabled' : !columnsChecked[i]}"> + <td *ngFor="let colInfo of dataset.columnInfo; let i = index" [ngClass]="{'text-disabled' : !columnsChecked[i]}" class="text-left"> <span *ngIf="colInfo.columnType == ColumnType.numerical"> - Mean: {{colInfo.mean}}<br> - Median: {{colInfo.median}}<br> - Min: {{colInfo.min}}<br> - Max: {{colInfo.max}}<br> - <!-- TODO na ML-u: Q1 i Q3 u statistici - Q1: {{colInfo.q1}}<br> - Q3: {{colInfo.q3}}<br> - --> - </span> - <div class="text-overflow" *ngIf="colInfo.columnType == ColumnType.categorical"> + Mean: {{colInfo.mean}}<br> + Median: {{colInfo.median}}<br> + Min: {{colInfo.min}}<br> + Max: {{colInfo.max}}<br> + Q1: {{colInfo.q1}}<br> + Q3: {{colInfo.q3}}<br> + </span> + <div class="text-overflow" *ngIf="colInfo.columnType == ColumnType.categorical && colInfo.uniqueValuesPercent"> <span *ngFor="let uniqueValue of colInfo.uniqueValues | slice:0:6; let i = index"> - {{uniqueValue}}<br><!-- TODO na ML-u: broj ponavljanja unique values-a u zagradi nek pise --> - </span> + ({{colInfo.uniqueValuesPercent[i].toFixed(4)}}%) {{uniqueValue}}<br> + </span> </div> </td> </tr> @@ -143,7 +141,7 @@ </th> <td *ngFor="let colInfo of dataset.columnInfo; let i = index" class="pad-fix" [ngClass]="{'text-disabled' : !columnsChecked[i]}"> <mat-form-field> - <mat-select matNativeControl [(value)]="experiment.encodings[i].encoding" [disabled]="!columnsChecked[i]"> + <mat-select matNativeControl [(value)]="experiment.encodings[i].encoding" [disabled]="!columnsChecked[i]" (selectionChange)="columnTableChangeDetected()"> <mat-option *ngFor="let option of Object.keys(Encoding); let optionName of Object.values(Encoding)" [value]="option"> {{ optionName }} </mat-option> @@ -158,75 +156,69 @@ </th> <td *ngFor="let colInfo of dataset.columnInfo; let i = index" [ngClass]="{'text-disabled' : !columnsChecked[i]}"> - <button class="w-100" mat-raised-button [ngClass]="{ 'menu-disabled' : !columnsChecked[i]}" [matMenuTriggerFor]="menu" id="main_{{colInfo.columnName}}" #nullValMenu> - <div class="cell-align"> - {{nullValOption[i]}} - <mat-icon>arrow_drop_down</mat-icon> - </div> - </button> - <mat-menu #menu="matMenu"> - <!--<button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteColumns, i)" value={{colInfo.columnName}}>Obriši kolonu</button>--> - <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteRows, i)" value={{colInfo.columnName}}>Obriši redove</button> - <button mat-menu-item [matMenuTriggerFor]="fillWith">Popuni sa</button> - </mat-menu> - - <mat-menu #fillWith="matMenu"> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.mean}}>Mean ({{colInfo.mean}})</button> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.median}}>Median ({{colInfo.median}})</button> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.max}}>Max ({{colInfo.max}})</button> - <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.min}}>Min ({{colInfo.min}})</button> + <div *ngIf="colInfo.numNulls > 0"> + <button class="w-100" mat-raised-button [ngClass]="{ 'menu-disabled' : !columnsChecked[i]}" [matMenuTriggerFor]="menu" id="main_{{colInfo.columnName}}" #nullValMenu> + <div class="cell-align"> + {{nullValOption[i]}} + <mat-icon>arrow_drop_down</mat-icon> + </div> + </button> + <mat-menu #menu="matMenu"> + <!--<button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteColumns, i)" value={{colInfo.columnName}}>Obriši kolonu</button>--> + <button mat-menu-item (click)="MissValsDeleteClicked($event, NullValueOptions.DeleteRows, i)" value={{colInfo.columnName}}>Obriši redove ({{colInfo.numNulls}})</button> + <button mat-menu-item [matMenuTriggerFor]="fillWith">Popuni sa</button> + </mat-menu> - <button *ngIf="!colInfo.isNumber" mat-menu-item [matMenuTriggerFor]="uniques">Najčešće vrednosti</button> + <mat-menu #fillWith="matMenu"> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.mean}}>Mean ({{colInfo.mean}})</button> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.median}}>Median ({{colInfo.median}})</button> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.max}}>Max ({{colInfo.max}})</button> + <button *ngIf="colInfo.isNumber" mat-menu-item (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{colInfo.min}}>Min ({{colInfo.min}})</button> - <button mat-menu-item [matMenuTriggerFor]="replaceWith">Unesi vrednost...</button> - </mat-menu> + <button *ngIf="!colInfo.isNumber" mat-menu-item [matMenuTriggerFor]="uniques">Najčešće vrednosti</button> - <mat-menu #uniques="matMenu"> - <button mat-menu-item *ngFor="let uniqueValue of colInfo.uniqueValues" (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{uniqueValue}}>{{uniqueValue}}</button> - </mat-menu> + <button mat-menu-item [matMenuTriggerFor]="replaceWith">Unesi vrednost...</button> + </mat-menu> - <mat-menu #replaceWith="matMenu"> - <input type="text" id={{colInfo.columnName}} mat-menu-item placeholder="Unesi vrednost..." [value]> - <button [disabled]="getValue(colInfo.columnName) == ''" mat-menu-item value={{getValue(colInfo.columnName)}} (click)="MissValsReplaceClicked($event, colInfo.columnName, i)">Potvrdi unos</button> - </mat-menu> + <mat-menu #uniques="matMenu"> + <button mat-menu-item *ngFor="let uniqueValue of colInfo.uniqueValues" (click)="MissValsReplaceClicked($event, colInfo.columnName, i)" value={{uniqueValue}}>{{uniqueValue}}</button> + </mat-menu> + <mat-menu #replaceWith="matMenu"> + <input type="text" id={{colInfo.columnName}} mat-menu-item placeholder="Unesi vrednost..." [value]> + <button [disabled]="getValue(colInfo.columnName) == ''" mat-menu-item value={{getValue(colInfo.columnName)}} (click)="MissValsReplaceClicked($event, colInfo.columnName, i)">Potvrdi unos</button> + </mat-menu> + </div> + <div *ngIf="colInfo.numNulls == 0" class="text-left"> + Nema nedostajućih vrednosti. + </div> </td> </tr> - <!--<tr class="row-height" *ngFor="let row of tableData; let i = index"> - <th *ngIf="i == 0" [attr.rowspan]="tableData!.length">Vrednosti</th> - - - <td class="text-center" *ngFor="let col of row; let j = index"> - <div class="text-overflow"> - {{col}} - </div> - </td> - </tr>--> </tbody> </table> </div> </div> </div> -<div class="container-fluid text-offwhite belowColumn mt-3"> +<div *ngIf="dataset && experiment" class="container-fluid text-offwhite belowColumn mt-3"> <div class="ns-row"> <div class="break-2"></div> <div class="ns-col rounded"> <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> <mat-label>Tip problema</mat-label> - <mat-select value="ToDo1"> - <mat-option value="ToDo1">Regresioni</mat-option> - <mat-option value="ToDo2">Binarni-Klasifikacioni</mat-option> - <mat-option value="ToDo3">Multi-Klasifikacioni</mat-option> + <mat-select [(value)]="experiment.type"> + <mat-option [value]="ProblemType.Regression">Regresioni</mat-option> + <mat-option [value]="ProblemType.BinaryClassification">Binarni-klasifikacioni</mat-option> + <mat-option [value]="ProblemType.MultiClassification">Multi-klasifikacioni</mat-option> </mat-select> </mat-form-field> </div> <div class="ns-col rounded"> <mat-form-field appearance="fill" class="align-items-center justify-content-center pt-3 w-100"> <mat-label>Izlazna kolona</mat-label> - <mat-select> - <mat-option *ngFor="let item of dataset?.columnInfo" [value]="item.columnName">{{item.columnName}}</mat-option> + <mat-select [(value)]="experiment.outputColumn" (selectionChange)="changeOutputColumn()"> + <mat-option *ngFor="let inputColumn of experiment.inputColumns" [value]="inputColumn">{{inputColumn}}</mat-option> </mat-select> </mat-form-field> </div> diff --git a/frontend/src/app/_elements/column-table/column-table.component.ts b/frontend/src/app/_elements/column-table/column-table.component.ts index 1946c1f1..01e4e564 100644 --- a/frontend/src/app/_elements/column-table/column-table.component.ts +++ b/frontend/src/app/_elements/column-table/column-table.component.ts @@ -7,6 +7,7 @@ import { MatDialog } from '@angular/material/dialog'; import { MissingvaluesDialogComponent } from 'src/app/_modals/missingvalues-dialog/missingvalues-dialog.component'; import { MatCheckboxChange } from '@angular/material/checkbox'; import { CsvParseService } from 'src/app/_services/csv-parse.service'; +import { ProblemType } from 'src/app/_data/Model'; @Component({ selector: 'app-column-table', @@ -19,10 +20,13 @@ export class ColumnTableComponent implements AfterViewInit { @Input() experiment?: Experiment; @ViewChildren("nullValMenu") nullValMenus!: ElementRef[]; @Output() okPressed: EventEmitter<string> = new EventEmitter(); + @Output() columnTableChanged = new EventEmitter(); + Object = Object; Encoding = Encoding; NullValueOptions = NullValueOptions; ColumnType = ColumnType; + ProblemType = ProblemType; tableData?: any[][]; nullValOption: string[] = []; @@ -35,7 +39,7 @@ export class ColumnTableComponent implements AfterViewInit { ngAfterViewInit(): void { this.datasetService.getMyDatasets().subscribe((datasets) => { - this.dataset = datasets[1]; + this.dataset = datasets[2]; this.setColumnTypeInitial(); this.experiment = new Experiment(); @@ -46,8 +50,9 @@ export class ColumnTableComponent implements AfterViewInit { for (let i = 0; i < this.dataset?.columnInfo.length; i++) { this.experiment?.inputColumns.push(this.dataset.columnInfo[i].columnName); } + this.experiment.outputColumn = this.experiment.inputColumns[0]; this.resetColumnEncodings(Encoding.Label); - this.setDeleteColumnsForMissingValTreatment(); + this.setDeleteRowsForMissingValTreatment(); this.nullValOption = [].constructor(this.dataset.columnInfo.length).fill('Obriši redove'); @@ -67,7 +72,7 @@ export class ColumnTableComponent implements AfterViewInit { } } - setDeleteColumnsForMissingValTreatment() { + setDeleteRowsForMissingValTreatment() { if (this.experiment != undefined) { this.experiment.nullValues = NullValueOptions.DeleteRows; this.experiment.nullValuesReplacers = []; @@ -81,8 +86,13 @@ export class ColumnTableComponent implements AfterViewInit { } } + columnTableChangeDetected() { + this.columnTableChanged.emit(); + } + changeInputColumns(targetMatCheckbox: MatCheckboxChange, columnName: string) { if (this.experiment != undefined) { + if (targetMatCheckbox.checked) { if (this.experiment.inputColumns.filter(x => x == columnName)[0] == undefined) { this.experiment.inputColumns.push(columnName); @@ -94,7 +104,26 @@ export class ColumnTableComponent implements AfterViewInit { //TODO: da se zatamni kolona koja je unchecked //this.experiment.encodings = this.experiment.encodings.filter(x => x.columnName != columnName); samo na kraju iz enkodinga skloni necekirane this.experiment.nullValuesReplacers = this.experiment.nullValuesReplacers.filter(x => x.column != columnName); + if (columnName == this.experiment.outputColumn) + this.experiment.outputColumn = this.experiment.inputColumns[0]; } + this.columnTableChangeDetected(); + } + } + + changeOutputColumn() { + if (this.experiment != undefined && this.dataset != undefined) { + let column = this.dataset.columnInfo.filter(x => x.columnName == this.experiment!.outputColumn)[0]; + if (column.columnType == ColumnType.numerical) { + this.experiment.type = ProblemType.Regression; + } + else { + if (column.uniqueValues!.length == 2) + this.experiment.type = ProblemType.BinaryClassification; + else + this.experiment.type = ProblemType.MultiClassification; + } + this.columnTableChangeDetected(); } } @@ -105,6 +134,7 @@ export class ColumnTableComponent implements AfterViewInit { this.experiment.encodings.push(new ColumnEncoding(this.dataset?.columnInfo[i].columnName, encodingType)); //console.log(this.experiment.encodings); } + this.columnTableChangeDetected(); } } openEncodingDialog() { @@ -141,9 +171,11 @@ export class ColumnTableComponent implements AfterViewInit { option: NullValueOptions.DeleteRows, value: "" }); - this.nullValOption[i] = "Obriši redove"; + let numOfRowsToDelete = (this.dataset.columnInfo.filter(x => x.columnName == this.experiment!.inputColumns[i])[0]).numNulls; + this.nullValOption[i] = "Obriši redove (" + numOfRowsToDelete + ")"; } } + this.columnTableChangeDetected(); } } openMissingValuesDialog() { @@ -159,7 +191,7 @@ export class ColumnTableComponent implements AfterViewInit { MissValsDeleteClicked(event: Event, replacementType: NullValueOptions, index: number) { - if (this.experiment != undefined) { + if (this.experiment != undefined && this.dataset != undefined) { let columnName = (<HTMLInputElement>event.currentTarget).value; let arrayElement = this.experiment.nullValuesReplacers.filter(x => x.column == columnName)[0]; @@ -175,7 +207,9 @@ export class ColumnTableComponent implements AfterViewInit { arrayElement.value = ""; } - this.nullValOption[index] = (replacementType == NullValueOptions.DeleteColumns) ? "Obriši kolonu" : "Obriši redove"; + let numOfRowsToDelete = (this.dataset.columnInfo.filter(x => x.columnName == this.experiment!.inputColumns[index])[0]).numNulls; + this.nullValOption[index] = (replacementType == NullValueOptions.DeleteColumns) ? "Obriši kolonu" : "Obriši redove (" + numOfRowsToDelete + ")"; + this.columnTableChangeDetected(); } } @@ -197,6 +231,7 @@ export class ColumnTableComponent implements AfterViewInit { } this.nullValOption[index] = "Popuni sa: " + fillValue; + this.columnTableChangeDetected(); } } getValue(columnName: string): string { |