16

Here there are two layers with the representation of the streets and the idea is: We want to update the most recent layer (with the red line) with some of the data storaged in the other one (the light blue), but these layers are similar in the Geographic position that can be very close and a little more distant depending on the place in the map and only one attribute matches in cases that a line is the same in the other one(codlog x codlog5).

Qgis layers.

For instance: In the middle of the image, there is a square in both layers, but how do I do in the map to recognize the blue one is the same as the green one and update the recent layer?

How can I do it? Is there any plugin or tool thats helps with it?

  • You want to update red layer with attributes from blue layer or with additional features from blue layer? – dmh126 Jul 15 '15 at 20:39
  • The attributes. Situation: The red layer contains the columns (a, b, c, d) and the blue one the columns (d, e, f). I want to add in the red layer the columns (e, f) from the other layer and its results that matches. – Jhonatan Oliveira Jul 15 '15 at 21:05
  • There is some documentation here for a conflation plugin. Not sure if development has been completed. – Barbarossa Jul 15 '15 at 21:38
  • 1
    have you tried Jump ? – radouxju Jul 16 '15 at 7:41
  • But the column "d" of the blu line and the "d" of the red one are an unique common id? What they contain? – Sergio Jul 16 '15 at 10:22
6
+50

This is a great question, I had to do something similar recently but with a much smaller dataset, so I was able to use a simple intersection with some extra visual quality checking and it was fine.

But here's an idea for this, though I don't have code, and it's kind of a hefty process. Definitely test with a sample from the full dataset first. You can probably some useful code around here. (The indentation got a little weird below.):

  1. take the good geometry set (where you want to have the attributes end up) and create a buffer of it*

  2. iterate through each of the buffer features:

    2a. calculate the general orientation of the feature (max_y - min_y / max_x - min_x or something like that)

    2b. make a select by location query on the other layer using this single feature

    1. you'll have more than one feature that matches the select by location query, so iterate through these selected features and calculate the orientation of each one

    2. get the attributes from whichever feature has an orientation closest to that of the buffer feature.

*I would start with a very small distance (one map unit or something) and then run this process with increasing distances, being careful not to overwrite any attributes that you have already transferred.

**You could actually probably forgo making the buffer features, and just do the select by location query with a buffer distance in it. I'm not very familiar with QGIS, but I'm sure you'd be able to do that.

There is no way that this will work perfectly for all your features, but it's a start, and then it just comes down to developing a good QA/QC strategy for checking and completing the transfer.

EDIT Thinking about this more, here is a basic example that would completely break the system if you were starting with a very small buffer distance and choosing the feature with the best matched orientation as I recommended:

enter image description here

The attributes from the wrong red line would be taken. To avoid this, you may want to create some sort of tolerance, and only take feature's attributes if its orientation (when compared to the orientation of the original blue feature) falls within that tolerance.

EDIT 2 Oops, are these polygons? I guess I just assumed they were lines on a grey background. If they are polygons, I don't really know if this orientation concept is a good one. But you could select all intersecting features, and figure out which has the most overlap (run a Union-type tool, and then use the polygon with the largest area...).

  • That logic is sound. I have used a similar approach in C#/ArcObjects to copy attributes from an inaccurate dataset with attributes to an accurate dataset without attributes... 95% correct. Manual checking/fixing was necessary in tight areas but it was certainly quicker than doing it all manually. – Michael Stimson Jul 17 '15 at 3:46
2

If you want to add some attributes from red layer to blue layer and one attribute is common in both layers, you have to use Add Vector Join.

I've written about that here.

  1. Right click on your red shapefile layer on Layer Panel and choose Properties.
  2. Then go to Joins tab.
  3. Press the + button, it will create new join.
  4. Join layer is your red shapefile layer. Join field is field with the common values in both. Target field is your field you want to join to from blue layer.
  5. After that you will get a new attribute in your shapefiles table.

That's it.

Here you have an example with screenshots.

1

I much prefer the answer from @dmh126 as his method allows your red_line layer to be updated quite easily.

Just to add an alternative, you can use the Join attributes table tool from the Processing Toolbox and select your layers with the common field. Note that this method creates a new shapefile instead of updating an existing one:

Join attributes table

0

If you have some unique ID in both layers which you can use to easily join values to new layer from old one, it is piece of cake. But this doesn't seem like that case.

If not, it is pretty difficult problem. I wonder why comment from user30184 suggesting to use OpenJUMP and plugin http://www.vividsolutions.com/products.asp?catg=spaapp&code=roadmatcher was not posted instead as answer because it sounds completely legit to me in this case.

Otherwise I don't think you can do this without some coding. With QGIS you can use shapely and when combining buffering and intersecting you should be able to do some significant automatic check.

One approach could be to compare some reasonably big buffer of red lines with blue lines and get matching attributes and ratio how much is it matching. In pseudo-code:

for r_line in red_lines:
  r_line_buf = r_line.buffer()
  intersecting_b_lines = []
  for b_line in blue_lines:
    if r_line_buf.intersects(b_line):
      intersect_length = calculateIntersectionLength(r_line_buf,b_line)
      b_line_values = getAttributes(b_line)
      intersecting_b_lines.append((b_line_values,intersect_length))
  b_line_best_fit = findLongestLineWithinIntersected(intersecting_b_lines)
  r_line_length = r_line.length
  b_vs_r_line_ratio = compareLength(r_line_length,b_line_best_fit)
  saveToNewColumns(r_line, b_line_best_fit.Atribute1, b_line_best_fit.Atribute2..., b_vs_r_line_ratio)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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