In QGIS I have two words e.g. the species name I would like to extract and put in its own column and then extract each of the numbers individually into its own column that represents DBH, height and spread. I have had a look at a few examples here and I cannot get it to work for me.
2 Answers
Working with tree data is right up my alley! I'm sure you could use expressions in the field calculator to do this, but if you would like to use pyqgis, you can add and populate all four fields at once. I chose this method partly because it looks as though there are some inconsistencies in your data (at least one row has commas separating the measurement values).
As a general rule, I always advise to make a backup copy of your layer first, as this script will permanently edit your data.
- Copy and paste the script below into the editor. Note: You will only need to edit the very first line. In my example it is 'Tree_info'. You need to change this to the name of your field which contains the data you want to extract (Corymbia propinqua 38, 26, 7 etc).
Script
field_name = 'Tree_info' # The name of your column which contains the information you wish to extract
lyr = iface.activeLayer()
flds_to_add = [
QgsField('Species', QVariant.String),
QgsField('DBH', QVariant.Int, len=3),
QgsField('Height', QVariant.Int, len=2),
QgsField('Spread', QVariant.Int, len=2)
]
lyr.dataProvider().addAttributes(flds_to_add)
lyr.updateFields()
sp_idx = lyr.fields().lookupField('Species')
dbh_idx = lyr.fields().lookupField('DBH')
ht_idx = lyr.fields().lookupField('Height')
sprd_idx = lyr.fields().lookupField('Spread')
att_map = {}
for f in lyr.getFeatures():
col_data = f[field_name]
data_split = col_data.split(' ')
sp_name = f'{data_split[0].strip(",")} {data_split[1].strip(",")}'
dbh = int(data_split[2].strip(','))
ht = int(data_split[3].strip(','))
sprd = int(data_split[4].strip(','))
att_map[f.id()] = {sp_idx: sp_name, dbh_idx: dbh, ht_idx: ht, sprd_idx: sprd}
lyr.dataProvider().changeAttributeValues(att_map)
- Make sure your layer is selected in the Table of Contents and click Run to execute the script (this icon):
The image below is of the script in my Python console.
You should get the following result (fields added to your layer and populated with the extracted values):
-
1@Simon Muirhead, I just made a small edit to my answer. I re-read your question and realised you want to extract both genus and species together (originally I thought you wanted only species). I have updated the script to do that.– Ben WFeb 13 at 7:04
-
1I just replied without checking the comments! Thank you very much, it is greatly appreciated. I really need to get field work data sorted so we are collecting the data in individual fields. Feb 13 at 7:55
-
@Simon Muirhead, no problem :-) Great. It sounds like you got the result you were after? Do you use a field data collection app? There are a couple that work very well with QGIS. I have used QField a lot and can thoroughly recommend it. There is also Input (which I haven't tried but it is also widely used and looks very good). Using something like that could help a lot with consistency of field data entry.– Ben WFeb 13 at 8:10
-
BTW, if the answer solved your problem would you mind accepting it with the check mark? Cheers.– Ben WFeb 13 at 8:11
-
1Gladly accepted. Definitely works :) I had everyone using collector when I was at Arcadis, but where am now doesn't have ESRI money. I will check out Qfield ASAP! Feb 13 at 8:21
Using the processing tools and expressions:
- algorithm: Refactor fields
- expression:
regexp_replace ("field2", '^(\\D+) (\\d+) (\\d+) (\\d+)', '\\x')
where x takes values 1,2,3,4 in the 4 fields
algorithm
add 4 fields, using the icons on the right of the window, and populate them with the expression above.
output
-
1
-
Thanks for this. I was just wondering what you used to populate the 'Load fields from template layer'? I cans see you are using CSV layer maybe? Feb 13 at 21:34
-