I have this combined dataset with building heights divided up over several columns ''Height'' ''Building_h'' and ''Building_L. My end goal is to combine them all in one new column. There are however, several problems:

  1. All columns are strings. I am aware of the to_real() function, but it doesn't work as some of the values have 'm' behind it to indicate that they are in meters. How can I change them?

  2. I already used regexp_replace( "height" , 'm.*', ' ') in the field calculator to get rid of the 'm' behind meters and got those into a new field called 'without M', but now only the cases that had m are in this field. They are also still in the field they were originally in, so I still cannot apply the to_real().

  3. I want to use with ''WithoutM'' field to add all the other values to as well.

How do I do this?

  1. Then there is ''Building_l'' which has the number of levels per building. And so, this is a different way of expressing building height than ''height'' and ''building_h'' do. If I say, for example that an average building level is 3 meters; is there a way I can multiply the value for ''building_l'' by 3 and also put this into the ''withoutM'' field?

  2. Last problem is related to the fact that several buildings have a value in more than one column. For example in ''height'' and ''building_l'', how should I handle this?

1 Answer 1


You can use field calculator.

  • Open field calculator.
  • Select update existing field, select your target field ("withoutM").
  • Go to Function editor, select new file and name your new function.
  • On the right side type in this code:
from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')

def my_copy(value1, value2, feature, parent):
  value2 = value2.replace("m", "")
  num_value2 = float(value2)
  if num_value1 != NULL:
      return float(num_value2)

For field with number of levels change else statement to:

      return float(num_value2) * 3
  • Click load and go back on Expresion tab.
  • Type in: my_copy("your_destination_field", "your_source_field") In your case you would replace "your_destination_field" with "withoutM".

This code will check if your destination field is empty, in that case it will copy value from source field.

  • Run this for each of your source fields except where you have number of levels. For that you just change last line of code to :

    return value2 * 3

..for 3 m high floors..

Maybe not the smoothest solution but I think it should work.

  • You can also deal with "m" situation with this code by adding this line above if statement: value2 = value2.replace("m", "").
    – Mat
    Mar 28, 2018 at 19:29
  • Thanks for your help! I have tried your approach and I think it works in theory. There is just a couple of problems: Firstly; when doing the approach for ''building_l'' a 'NULL' Value is returned. I think this is because the attribute of building level is still a string? How do I change this? The second problem comes with overwriting; when the approach works for values from ''height'' (still strings though) that have meters behind them, when will get changed back into 'NULL' when running my_copy("withoutM", "height"). Looking forward to hearing more!
    – Demi Vonk
    Mar 29, 2018 at 6:43
  • I changed code in the answer, hope it works now.
    – Mat
    Mar 29, 2018 at 7:19
  • Ah I see. I got rid of the m's now in the ''height field'', but still they are strings, and they don't want to change into integers with to_real(''height''). I also don't get an error message though. As for the steps you outlined, I don't get values in ''withoutM'' yet... I'm not sure were the bug is; can you maybe explain what ''feature'' and ''parents'' do in: def my_copy(value1, value2, feature, parent)? Maybe I can make sense of it then ;-)
    – Demi Vonk
    Mar 29, 2018 at 8:55
  • Lets try simpler way. Choose update "without M" field (that field is real numbers, right?) In expressions tab: If("without M" is NULL,"height", pass) So, if field without M is empty, fill it with value from "height" else do nothing. After you ran this: If("without M" is NULL,"building_h", pass) and finally: If("without M" is NULL,"Building_l" * 3, pass)
    – Mat
    Mar 29, 2018 at 18:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.