You need to convert your date into datetime object for max()
to work correctly. It appears field calculator doesn't see the value as a datetime object. You may need to adjust the date format to suit your region date settings. See Strptime Behavior in the Python docs.
Using the Python Parser, select Show Codeblock. In the Pre-logic script code:
from datetime import datetime
def dtmax(*args):
f = '%m/%d/%Y %I:%M:%S %p'
dlist= list()
for d in args:
if d:
dlist.append(datetime.strptime(d, f))
return max(dlist)
Expression:
dtmax(!DateField1!, !DateField2!, !DateField3!, !DateField4!)
NULL and None
Fun fact: NULL is not None
With this in mind it's easy to fix the code
@qgsfunction(args=-1, group='Custom')
def mean_col(cols, feature, parent):
vals = [feature[i] for i in cols if feature[i] != NULL]
return sum(vals)/float(len(vals))
Do not write to layers in expressions
Additional advice: never write to layers in expressions. Expressions are often executed in threads and in different contexts and using layer.changeAttributeValue()
and similar functions may result in undefined behavior (read: crash).
Using values instead of attribute names
Another interesting experiment for educational purpose.
Instead of providing column names to the function, you can also provide values.
@qgsfunction(args='auto', group='Custom')
def mean_value(vals, feature, parent):
vals = [val for val in vals if val != NULL]
return sum(vals)/float(len(vals))
And then call it with
mean_value("kk1", "kk2", "kk3", "kk4")
The interesting result is: it will return NULL as soon as at least one column is NULL.
How comes? QGIS assumes the result for an expression function is NULL as soon as at least one parameter is NULL for performance reasons. It's possible to control this behavior, but unfortunately the @qgsfunction
decorator does not support this to date (QGIS 3.2).
To workaround this behavior we can either provide a full-blown QgsExpressionFunction
implementation which is out of scope for this answer.
Or just take a little detour and use an array instead.
@qgsfunction(args='auto', group='Custom')
def mean_value(vals, feature, parent):
vals = [val for val in vals if val != NULL]
return sum(vals)/float(len(vals))
and then call it with
mean_value(array("kk1", "kk2", "kk3", "kk4"))
Best Answer
Open up the layer's Attribute Table > Toggle editing mode. Select the fields you want changed then open the Field Calculator. Check the Only update selected features box at the top.
Assuming you already made a column for the Date, check the Update existing field box and select the required field. Then in the expression box, enter
NULL
.