20

I have a layer in QGIS, and I want to duplicate it through a plugin so I can use the copy of it as I want, without modifying the original.

Of course layer2 = layer1 will not work, because everything that happens to layer2 will also happen to layer1, as it is the same object behind all this.

The only way I found to do it is as such:

QgsVectorFileWriter.writeAsVectorFormat(layer1, r"C:\Users\ABC\AppData\Local\Temp\NewLayer.shp", "utf-8", None, "ESRI Shapefile")
layer2 = QgsVectorLayer("C:\Users\ABC\AppData\Local\Temp\NewLayer.shp", "New vector", "ogr")
#do something with layer2

Is there a simple way to duplicate the layer in memory, without having to write a new file?

MrXsquared
36.2k22 gold badges76 silver badges127 bronze badges
asked Aug 5, 2016 at 12:59

3 Answers 3

24

In QGIS 3 you can make a copy of a layer without saving any reference to the parent layer in this way:

# imports
import processing
from qgis.utils import iface
from qgis.core import QgsProject
# choose a layer
layer = iface.activeLayer()
layer.selectAll()
clone_layer = processing.run("native:saveselectedfeatures", {'INPUT': layer, 'OUTPUT': 'memory:'})['OUTPUT']
layer.removeSelection()
QgsProject.instance().addMapLayer(clone_layer)

The QgsVectorLayer class has a clone() method that allows you to clone the layer in a new layer, the problem is that if you modify the geometry in the cloned layer the original layer will be affected: the reason for this is that the data source is the same for the original layer and the cloned layer.

Taras
35.8k5 gold badges77 silver badges152 bronze badges
answered Aug 24, 2018 at 22:11
0
20

The following code works for me from both the Python Console and plugin. It takes the features from the source input layer and copies the attributes to a memory layer (in this case, a polygon layer but you can change it to LineString or Point depending on layer type):

# imports
from qgis.utils import iface
from qgis.core import QgsVectorLayer, QgsMapLayerRegistry
layer = QgsVectorLayer("path/to/layer", "polygon", "ogr")
feats = [feat for feat in layer.getFeatures()]
mem_layer = QgsVectorLayer("Polygon?crs=epsg:4326", "duplicated_layer", "memory")
mem_layer_data = mem_layer.dataProvider()
attr = layer.dataProvider().fields().toList()
mem_layer_data.addAttributes(attr)
mem_layer.updateFields()
mem_layer_data.addFeatures(feats)
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
Taras
35.8k5 gold badges77 silver badges152 bronze badges
answered Aug 5, 2016 at 13:39
0
8

Since QGIS 3.0, there is another approach available. Use the materialize() method from the QgsFeatureSource class.

Over the entire layer with the allFeatureIds() method:

# imports
from qgis.utils import iface
from qgis.core import QgsFeatureRequest, QgsProject
# choose a layer
layer = iface.activeLayer()
# or with: layer = QgsProject.instance().mapLayersByName('LAYER_NAME')[0]
# create a new layer from all features 
new_layer = layer.materialize(QgsFeatureRequest().setFilterFids(layer.allFeatureIds()))
# add a new layer to the map
QgsProject.instance().addMapLayer(new_layer)

Over the selection of all features with the selectedFeatureIds() method from the QgsVectorLayer class:

# imports
from qgis.utils import iface
from qgis.core import QgsFeatureRequest, QgsProject
# choose a layer
layer = iface.activeLayer()
# or with: # or with: layer = QgsProject.instance().mapLayersByName('LAYER_NAME')[0]
# select all features in the original layer
layer.selectAll()
# create a new layer from selected features
new_layer = layer.materialize(QgsFeatureRequest().setFilterFids(layer.selectedFeatureIds()))
# remove selection in the original layer
layer.removeSelection()
# add a new layer to the map 
QgsProject.instance().addMapLayer(new_layer)

References:

answered Apr 25, 2022 at 6:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.