Skip to content

Commit ea2e537

Browse files
committedSep 7, 2017
Make value field in 'Stats by category' optional
If not set, only the feature counts for each category will be calculated
1 parent 30c663e commit ea2e537

File tree

1 file changed

+52
-24
lines changed

1 file changed

+52
-24
lines changed
 

‎python/plugins/processing/algs/qgis/StatisticsByCategories.py

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ def initAlgorithm(self, config=None):
6464
self.tr('Input vector layer'),
6565
types=[QgsProcessing.TypeVector]))
6666
self.addParameter(QgsProcessingParameterField(self.VALUES_FIELD_NAME,
67-
self.tr('Field to calculate statistics on'),
68-
parentLayerParameterName=self.INPUT))
67+
self.tr(
68+
'Field to calculate statistics on (if empty, only count is calculated)'),
69+
parentLayerParameterName=self.INPUT, optional=True))
6970
self.addParameter(QgsProcessingParameterField(self.CATEGORIES_FIELD_NAME,
7071
self.tr('Field(s) with categories'),
7172
parentLayerParameterName=self.INPUT,
@@ -85,7 +86,10 @@ def processAlgorithm(self, parameters, context, feedback):
8586
category_field_names = self.parameterAsFields(parameters, self.CATEGORIES_FIELD_NAME, context)
8687

8788
value_field_index = source.fields().lookupField(value_field_name)
88-
value_field = source.fields().at(value_field_index)
89+
if value_field_index >= 0:
90+
value_field = source.fields().at(value_field_index)
91+
else:
92+
value_field = None
8993
category_field_indexes = [source.fields().lookupField(n) for n in category_field_names]
9094

9195
# generate output fields
@@ -101,7 +105,10 @@ def addField(name):
101105
field.setName(name)
102106
fields.append(field)
103107

104-
if value_field.isNumeric():
108+
if value_field is None:
109+
field_type = 'none'
110+
fields.append(QgsField('count', QVariant.Int))
111+
elif value_field.isNumeric():
105112
field_type = 'numeric'
106113
fields.append(QgsField('count', QVariant.Int))
107114
fields.append(QgsField('unique', QVariant.Int))
@@ -140,42 +147,50 @@ def addField(name):
140147
fields.append(QgsField('mean_length', QVariant.Double))
141148

142149
request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
143-
attrs = [value_field_index]
150+
if value_field is not None:
151+
attrs = [value_field_index]
152+
else:
153+
attrs = []
144154
attrs.extend(category_field_indexes)
145155
request.setSubsetOfAttributes(attrs)
146156
features = source.getFeatures(request)
147157
total = 50.0 / source.featureCount() if source.featureCount() else 0
148-
values = defaultdict(list)
158+
if field_type == 'none':
159+
values = defaultdict(lambda: 0)
160+
else:
161+
values = defaultdict(list)
149162
for current, feat in enumerate(features):
150163
if feedback.isCanceled():
151164
break
152165

153166
feedback.setProgress(int(current * total))
154167
attrs = feat.attributes()
155-
if True:
156-
if field_type == 'numeric':
157-
if attrs[value_field_index] == NULL:
158-
continue
159-
else:
160-
value = float(attrs[value_field_index])
161-
elif field_type == 'string':
162-
if attrs[value_field_index] == NULL:
163-
value=''
164-
else:
165-
value = str(attrs[value_field_index])
166-
elif attrs[value_field_index] == NULL:
167-
value = NULL
168+
cat = tuple([attrs[c] for c in category_field_indexes])
169+
if field_type == 'none':
170+
values[cat] += 1
171+
continue
172+
if field_type == 'numeric':
173+
if attrs[value_field_index] == NULL:
174+
continue
168175
else:
169-
value = attrs[value_field_index]
170-
cat = tuple([attrs[c] for c in category_field_indexes])
171-
values[cat].append(value)
176+
value = float(attrs[value_field_index])
177+
elif field_type == 'string':
178+
if attrs[value_field_index] == NULL:
179+
value = ''
180+
else:
181+
value = str(attrs[value_field_index])
182+
elif attrs[value_field_index] == NULL:
183+
value = NULL
172184
else:
173-
pass
185+
value = attrs[value_field_index]
186+
values[cat].append(value)
174187

175188
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
176189
fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
177190

178-
if field_type == 'numeric':
191+
if field_type == 'none':
192+
self.saveCounts(values, sink, feedback)
193+
elif field_type == 'numeric':
179194
self.calcNumericStats(values, sink, feedback)
180195
elif field_type == 'datetime':
181196
self.calcDateTimeStats(values, sink, feedback)
@@ -184,6 +199,19 @@ def addField(name):
184199

185200
return {self.OUTPUT: dest_id}
186201

202+
def saveCounts(self, values, sink, feedback):
203+
total = 50.0 / len(values) if values else 0
204+
current = 0
205+
for cat, v in values.items():
206+
if feedback.isCanceled():
207+
break
208+
209+
feedback.setProgress(int(current * total) + 50)
210+
f = QgsFeature()
211+
f.setAttributes(list(cat) + [v])
212+
sink.addFeature(f, QgsFeatureSink.FastInsert)
213+
current += 1
214+
187215
def calcNumericStats(self, values, sink, feedback):
188216
stat = QgsStatisticalSummary()
189217

0 commit comments

Comments
 (0)
Please sign in to comment.