3

I have the following data frame:

pd.DataFrame.from_dict({
    'x0': {
        199: 162.2, 441: 324.5, 903: 209.0, 1272: 241.4, 1431: 142.4, 1510: 314.7, 1657: 274.1,
        1777: 217.7, 1811: 261.8, 2022: 143.0, 2164: 341.6, 2167: 364.7, 2461: 348.2, 2606: 256.7,
        2895: 353.2, 114: 249.8, 240: 181.1, 278: 191.6, 372: 249.2, 460: 87.8
    },
    'y0': {
        199: 246.8, 441: 55.4, 903: 236.0, 1272: 233.6, 1431: 230.6, 1510: 249.4, 1657: 67.7,
        1777: 239.3, 1811: 193.7, 2022: 224.0, 2164: 101.6, 2167: 50.3, 2461: 191.9, 2606: 242.3,
        2895: 200.4, 114: 51.5, 240: 104.9, 278: 132.5, 372: 167.0, 460: 207.2
    },
    'x1': {
        199: 201.8, 441: 363.6, 903: 258.1, 1272: 257.0, 1431: 122.4, 1510: 331.0, 1657: 358.7,
        1777: 265.0, 1811: 365.9, 2022: 176.8, 2164: 383.9, 2167: 351.1, 2461: 364.0, 2606: 300.0,
        2895: 352.4, 114: 278.1, 240: 233.3, 278: 171.6, 372: 219.5, 460: 156.8
    },
    'y1': {
        199: 240.2, 441: 114.6, 903: 236.0, 1272: 275.3, 1431: 286.6, 1510: 237.4, 1657: 178.2,
        1777: 244.4, 1811: 100.6, 2022: 273.7, 2164: 154.5, 2167: 184.2, 2461: 127.5, 2606: 244.1,
        2895: 115.1, 114: 85.0, 240: 117.4, 278: 84.1, 372: 159.2, 460: 199.5
    }
})
         x0     y0     x1     y1
199   162.2  246.8  201.8  240.2
441   324.5   55.4  363.6  114.6
903   209.0  236.0  258.1  236.0
1272  241.4  233.6  257.0  275.3
1431  142.4  230.6  122.4  286.6
1510  314.7  249.4  331.0  237.4
              ...

where subsequent columns define starting and ending coordinates of a segment. I need to calculate the point of intersection of this segment and the line, e.g. x = 100 and y = 60. I would like to store the obtained points in columns x1 and y1, so that the values would be replaced if there is an intersection, otherwise original x1 and y1 values would be preserved. I found that the solution to defining intersection point under this link, but I don't know how to vectorise it and make it work with Pandas. Or maybe working directly on columns would be easier? Any ideas?

villoro
  • 1,469
  • 1
  • 11
  • 14
Xaume
  • 293
  • 2
  • 16
  • 1
    This is quite a broad request. There are multiple ways to do what you want. I personally would approach it by using GeoPandas. You could make a GeoSeries of `LineString`s and then use [`intersection`](https://geopandas.org/reference.html?highlight=intersects#geopandas.GeoSeries.intersection) method to get the resulting points. – Georgy Feb 19 '20 at 10:38
  • 1
    it's not clear which line you want to intersect segments with. – Walter Tross Feb 21 '20 at 13:16
  • The line should be used as a parameter, but I mentioned lines `x=100` or `y=60` as an example above (so, a vertical or horizontal line in the standard coordinate system) – Xaume Feb 21 '20 at 13:26

1 Answers1

2

You can easily achieve/vectorize this problem if you munge your data into slope-intercept format:

slopes = (df['y1'] - df['y0']) / (df['x1'] - df['x0'])
y_intercepts = df['y0'] - (slopes * df['x0'])

Then your intercept problem can be solved for any line with:

def get_vertical_intercept(x):
    return slopes * x + y_intercepts

def get_horizontal_intercept(y):
    return (y - y_intercepts) / slopes

As for replacing the daframe values:

intercepts = get_horizontal_intercept(256)
intercepts[np.isinf] = df['x1']
df['x1'] = intercepts.round(1)

As you can imagine, the other columns can be filled similarly...

>>> df

        x0      y0      x1      y1
199     162.2   246.8   107.0   240.2
441     324.5   55.4    457.0   114.6
903     209.0   236.0   258.1   236.0
1272    241.4   233.6   249.8   275.3
1431    142.4   230.6   133.3   286.6
Brian
  • 1,572
  • 9
  • 18
  • This worked like a charm, with one minor comment: as we're getting a horizontal intercept in your example, we should change your code to `intercepts[np.isinf] = df['x1']; df['x1'] = intercepts` – Xaume Feb 25 '20 at 15:38