|
25 | 25 | #include "qgsvectorlayer.h"
|
26 | 26 | #include "qgsvectordataprovider.h"
|
27 | 27 | #include "qgsattributeeditor.h"
|
| 28 | +#include "qgsstatisticalsummary.h" |
28 | 29 |
|
29 | 30 | #include <limits>
|
30 | 31 | #include <QComboBox>
|
31 | 32 | #include <QSettings>
|
32 | 33 |
|
| 34 | +QList< QgsStatisticalSummary::Statistic > QgsMergeAttributesDialog::mDisplayStats = |
| 35 | + QList< QgsStatisticalSummary::Statistic > () << QgsStatisticalSummary::Count |
| 36 | + << QgsStatisticalSummary::Sum |
| 37 | + << QgsStatisticalSummary::Mean |
| 38 | + << QgsStatisticalSummary::Median |
| 39 | + << QgsStatisticalSummary::StDev |
| 40 | + << QgsStatisticalSummary::StDevSample |
| 41 | + << QgsStatisticalSummary::Min |
| 42 | + << QgsStatisticalSummary::Max |
| 43 | + << QgsStatisticalSummary::Range |
| 44 | + << QgsStatisticalSummary::Minority |
| 45 | + << QgsStatisticalSummary::Majority |
| 46 | + << QgsStatisticalSummary::Variety |
| 47 | + << QgsStatisticalSummary::FirstQuartile |
| 48 | + << QgsStatisticalSummary::ThirdQuartile |
| 49 | + << QgsStatisticalSummary::InterQuartileRange; |
| 50 | + |
33 | 51 | QgsMergeAttributesDialog::QgsMergeAttributesDialog( const QgsFeatureList &features, QgsVectorLayer *vl, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags f )
|
34 | 52 | : QDialog( parent, f )
|
35 | 53 | , mFeatureList( features )
|
@@ -152,16 +170,15 @@ QComboBox *QgsMergeAttributesDialog::createMergeComboBox( QVariant::Type columnT
|
152 | 170 | QgsFeatureList::const_iterator f_it = mFeatureList.constBegin();
|
153 | 171 | for ( ; f_it != mFeatureList.constEnd(); ++f_it )
|
154 | 172 | {
|
155 |
| - newComboBox->addItem( tr( "Feature %1" ).arg( f_it->id() ), QString::number( f_it->id() ) ); |
| 173 | + newComboBox->addItem( tr( "Feature %1" ).arg( f_it->id() ), QString( "f%1" ).arg( f_it->id() ) ); |
156 | 174 | }
|
157 | 175 |
|
158 | 176 | if ( columnType == QVariant::Double || columnType == QVariant::Int )
|
159 | 177 | {
|
160 |
| - newComboBox->addItem( tr( "Minimum" ), "minimum" ); |
161 |
| - newComboBox->addItem( tr( "Maximum" ), "maximum" ); |
162 |
| - newComboBox->addItem( tr( "Median" ), "median" ); |
163 |
| - newComboBox->addItem( tr( "Sum" ), "sum" ); |
164 |
| - newComboBox->addItem( tr( "Mean" ), "mean" ); |
| 178 | + Q_FOREACH ( QgsStatisticalSummary::Statistic stat, mDisplayStats ) |
| 179 | + { |
| 180 | + newComboBox->addItem( QgsStatisticalSummary::displayName( stat ) , stat ); |
| 181 | + } |
165 | 182 | }
|
166 | 183 | else if ( columnType == QVariant::String )
|
167 | 184 | {
|
@@ -250,39 +267,26 @@ void QgsMergeAttributesDialog::refreshMergedValue( int col )
|
250 | 267 | //evaluate behaviour (feature value or min / max / mean )
|
251 | 268 | QString mergeBehaviourString = comboBox->itemData( comboBox->currentIndex() ).toString();
|
252 | 269 | QVariant mergeResult; // result to show in the merge result field
|
253 |
| - if ( mergeBehaviourString == "minimum" ) |
254 |
| - { |
255 |
| - mergeResult = minimumAttribute( col ); |
256 |
| - } |
257 |
| - else if ( mergeBehaviourString == "maximum" ) |
258 |
| - { |
259 |
| - mergeResult = maximumAttribute( col ); |
260 |
| - } |
261 |
| - else if ( mergeBehaviourString == "mean" ) |
262 |
| - { |
263 |
| - mergeResult = meanAttribute( col ); |
264 |
| - } |
265 |
| - else if ( mergeBehaviourString == "median" ) |
266 |
| - { |
267 |
| - mergeResult = medianAttribute( col ); |
268 |
| - } |
269 |
| - else if ( mergeBehaviourString == "sum" ) |
270 |
| - { |
271 |
| - mergeResult = sumAttribute( col ); |
272 |
| - } |
273 |
| - else if ( mergeBehaviourString == "concat" ) |
| 270 | + if ( mergeBehaviourString == "concat" ) |
274 | 271 | {
|
275 | 272 | mergeResult = concatenationAttribute( col );
|
276 | 273 | }
|
277 | 274 | else if ( mergeBehaviourString == "skip" )
|
278 | 275 | {
|
279 | 276 | mergeResult = tr( "Skipped" );
|
280 | 277 | }
|
281 |
| - else //an existing feature value |
| 278 | + else if ( mergeBehaviourString.startsWith( "f" ) ) |
282 | 279 | {
|
283 |
| - int featureId = mergeBehaviourString.toInt(); |
| 280 | + //an existing feature value - TODO should be QgsFeatureId, not int |
| 281 | + int featureId = mergeBehaviourString.mid( 1 ).toInt(); |
284 | 282 | mergeResult = featureAttribute( featureId, col );
|
285 | 283 | }
|
| 284 | + else |
| 285 | + { |
| 286 | + //numerical statistic |
| 287 | + QgsStatisticalSummary::Statistic stat = ( QgsStatisticalSummary::Statistic )( comboBox->itemData( comboBox->currentIndex() ).toInt() ); |
| 288 | + mergeResult = calcStatistic( col, stat ); |
| 289 | + } |
286 | 290 |
|
287 | 291 | //insert string into table widget
|
288 | 292 | QTableWidgetItem* newTotalItem = new QTableWidgetItem();
|
@@ -311,141 +315,30 @@ QVariant QgsMergeAttributesDialog::featureAttribute( int featureId, int col )
|
311 | 315 | }
|
312 | 316 | }
|
313 | 317 |
|
314 |
| -QVariant QgsMergeAttributesDialog::minimumAttribute( int col ) |
315 |
| -{ |
316 |
| - double minimumValue = std::numeric_limits<double>::max(); |
317 |
| - double currentValue; |
318 |
| - bool conversion = false; |
319 |
| - int numberOfConsideredFeatures = 0; |
320 | 318 |
|
321 |
| - for ( int i = 0; i < mFeatureList.size(); ++i ) |
322 |
| - { |
323 |
| - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
324 |
| - if ( conversion ) |
325 |
| - { |
326 |
| - if ( currentValue < minimumValue ) |
327 |
| - { |
328 |
| - minimumValue = currentValue; |
329 |
| - ++numberOfConsideredFeatures; |
330 |
| - } |
331 |
| - } |
332 |
| - } |
333 |
| - |
334 |
| - if ( numberOfConsideredFeatures < 1 ) |
335 |
| - { |
336 |
| - return QVariant( mVectorLayer->fields().at( col ).type() ); |
337 |
| - } |
338 |
| - |
339 |
| - return QVariant( minimumValue ); |
340 |
| -} |
341 |
| - |
342 |
| -QVariant QgsMergeAttributesDialog::maximumAttribute( int col ) |
| 319 | +QVariant QgsMergeAttributesDialog::calcStatistic( int col, QgsStatisticalSummary::Statistic stat ) |
343 | 320 | {
|
344 |
| - double maximumValue = -std::numeric_limits<double>::max(); |
345 |
| - double currentValue; |
346 |
| - bool conversion = false; |
347 |
| - int numberOfConsideredFeatures = 0; |
348 |
| - |
349 |
| - for ( int i = 0; i < mFeatureList.size(); ++i ) |
350 |
| - { |
351 |
| - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
352 |
| - if ( conversion ) |
353 |
| - { |
354 |
| - if ( currentValue > maximumValue ) |
355 |
| - { |
356 |
| - maximumValue = currentValue; |
357 |
| - ++numberOfConsideredFeatures; |
358 |
| - } |
359 |
| - } |
360 |
| - } |
361 |
| - |
362 |
| - if ( numberOfConsideredFeatures < 1 ) |
363 |
| - { |
364 |
| - return QVariant( mVectorLayer->fields().at( col ).type() ); |
365 |
| - } |
366 |
| - |
367 |
| - return QVariant( maximumValue ); |
368 |
| -} |
| 321 | + QgsStatisticalSummary summary( stat ); |
369 | 322 |
|
370 |
| -QVariant QgsMergeAttributesDialog::meanAttribute( int col ) |
371 |
| -{ |
372 |
| - int numberOfConsideredFeatures = 0; |
373 |
| - double currentValue; |
374 |
| - double sum = 0; |
375 | 323 | bool conversion = false;
|
376 |
| - |
| 324 | + QList<double> values; |
377 | 325 | for ( int i = 0; i < mFeatureList.size(); ++i )
|
378 | 326 | {
|
379 |
| - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
| 327 | + double currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
380 | 328 | if ( conversion )
|
381 | 329 | {
|
382 |
| - sum += currentValue; |
383 |
| - ++numberOfConsideredFeatures; |
| 330 | + values << currentValue; |
384 | 331 | }
|
385 | 332 | }
|
386 | 333 |
|
387 |
| - if ( numberOfConsideredFeatures < 1 ) |
| 334 | + if ( values.isEmpty() ) |
388 | 335 | {
|
389 |
| - return QVariant( mVectorLayer->fields().at( col ).type() ); |
| 336 | + return QVariant( mVectorLayer->fields()[col].type() ); |
390 | 337 | }
|
391 | 338 |
|
392 |
| - double mean = sum / numberOfConsideredFeatures; |
393 |
| - return QVariant( mean ); |
394 |
| -} |
395 |
| - |
396 |
| -QVariant QgsMergeAttributesDialog::medianAttribute( int col ) |
397 |
| -{ |
398 |
| - //bring all values into a list and sort |
399 |
| - QList<double> valueList; |
400 |
| - double currentValue; |
401 |
| - bool conversionSuccess; |
402 |
| - |
403 |
| - for ( int i = 0; i < mFeatureList.size(); ++i ) |
404 |
| - { |
405 |
| - currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversionSuccess ); |
406 |
| - if ( !conversionSuccess ) |
407 |
| - { |
408 |
| - continue; |
409 |
| - } |
410 |
| - valueList.push_back( currentValue ); |
411 |
| - } |
412 |
| - qSort( valueList ); |
413 |
| - |
414 |
| - double medianValue; |
415 |
| - int size = valueList.size(); |
416 |
| - |
| 339 | + summary.calculate( values ); |
417 | 340 |
|
418 |
| - if ( size < 1 ) |
419 |
| - { |
420 |
| - return QVariant( mVectorLayer->fields().at( col ).type() ); |
421 |
| - } |
422 |
| - |
423 |
| - bool even = ( size % 2 ) < 1; |
424 |
| - if ( even ) |
425 |
| - { |
426 |
| - medianValue = ( valueList[size / 2 - 1] + valueList[size / 2] ) / 2; |
427 |
| - } |
428 |
| - else //odd |
429 |
| - { |
430 |
| - medianValue = valueList[( size + 1 ) / 2 - 1]; |
431 |
| - } |
432 |
| - return QVariant( medianValue ); |
433 |
| -} |
434 |
| - |
435 |
| -QVariant QgsMergeAttributesDialog::sumAttribute( int col ) |
436 |
| -{ |
437 |
| - double sum = 0.0; |
438 |
| - bool conversion = false; |
439 |
| - |
440 |
| - for ( int i = 0; i < mFeatureList.size(); ++i ) |
441 |
| - { |
442 |
| - double currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion ); |
443 |
| - if ( conversion ) |
444 |
| - { |
445 |
| - sum += currentValue; |
446 |
| - } |
447 |
| - } |
448 |
| - return QVariant( sum ); |
| 341 | + return QVariant::fromValue( summary.statistic( stat ) ); |
449 | 342 | }
|
450 | 343 |
|
451 | 344 | QVariant QgsMergeAttributesDialog::concatenationAttribute( int col )
|
|
0 commit comments