J'ai créé deux geodataframes et j'essaie de trouver la distance la plus courte entre chaque point d'un geodataframe et n'importe quel point de l'autre geodataframe en fonction de la réponse ici.

Cependant, même si je pense avoir créé une colonne de géométrie, je ne peux pas accéder aux lignes. Je reçois cette erreur:

AttributeError: ("'Series' object has no attribute 'geometry'", u'occurred at index 0')

Nameofgeodataframe.head () renvoie:

   node  x_coord  y_coord   Coordinates1
0     0        0      258  POINT (0 258)
1     1        0      259  POINT (0 259)
2     2        0      260  POINT (0 260)
3     3        0      261  POINT (0 261)
4     4        0      262  POINT (0 262)

Ceci est mon script très inélégant.

f = h5py.File("temp_bin2x_outer_tagged.hdf", "r")
data = f["MDF/images/0/image"]
my_test = data[171, :, :]
val = filter.threshold_otsu(my_test)
binary = np.where(my_test > val, 1, 0)
outskel = skeletonize(binary)
x, y = np.where(outskel>0)
y_coord = y.tolist()
x_coord = x.tolist()
index = list(range(0,(len(x_coord))))
df = pd.DataFrame({"y_coord": y_coord, "x_coord": x_coord, "node": index})
df['Coordinates1'] = list(zip(df.x_coord, df.y_coord))
df['Coordinates1'] = df['Coordinates1'].apply(Point)
outer = geopandas.GeoDataFrame(df, geometry='Coordinates1')

f2 = h5py.File("temp_bin2x_inner_tagged.hdf", "r")
data2 = f2["MDF/images/0/image"]
my_test2 = data2[211, :, :]
val2 = filter.threshold_otsu(my_test2)
binary2 = np.where(my_test2 > val2, 1, 0)
binary2 = np.where(my_test2 > val2, 1, 0)
inskel = skeletonize(binary2)
x2, y2 = np.where(inskel>0)
y_coord2 = y2.tolist()
x_coord2 = x2.tolist()
index2 = list(range(0,(len(x_coord2))))
df2 = pd.DataFrame({"y_coord2": y_coord2, "x_coord2": x_coord2, "node": index2})
df2['Coordinates'] = list(zip(df2.x_coord2, df2.y_coord2))
df2['Coordinates'] = df2['Coordinates'].apply(Point)
inner = geopandas.GeoDataFrame(df2, geometry='Coordinates')

from shapely.ops import nearest_points
pts3 = inner.geometry.unary_union
def near(point, pts=pts3):
     nearest = inner.geometry == nearest_points(point, pts)[1]
     return inner[nearest].node.get_values()[0]
outer['Nearest'] = outer.apply(lambda row: near(row.geometry), axis=1)

Suis-je incompréhensible sur la construction d'un cadre géographique?

Merci beaucoup, toute aide serait formidable!

1
Emily 17 mars 2019 à 05:16

2 réponses

Meilleure réponse

Vous faites un mélange entre le nouveau nom de colonne et la géométrie du nom, c'est la raison de l'erreur: (la traduction du nom n'est pas toujours faite)

 data1 = """
 node  x_coord  y_coord 
0        0      258  
1        0      259  
2        0      260  
3        0      261  
4        0      230  
 """
data2 = """
  node  x_coord  y_coord 
0        0      288  
1        0      249  
2        0      210  
3        0      259  
4        0      232  
"""
df1 = pd.read_csv(pd.compat.StringIO(data1), sep='\s+')
df2 = pd.read_csv(pd.compat.StringIO(data2), sep='\s+')
df1['Coordinates1'] = list(zip(df1.x_coord, df1.y_coord))
df1['Coordinates1'] = df1['Coordinates1'].apply(Point)
df2['Coordinates2'] = list(zip(df2.x_coord, df2.y_coord))
df2['Coordinates2'] = df2['Coordinates2'].apply(Point)

outer = gpd.GeoDataFrame(df1, geometry='Coordinates1')
inner = gpd.GeoDataFrame(df2, geometry='Coordinates2')

from shapely.ops import nearest_points
pts3 = inner.geometry.unary_union #you could use inner.Coordinates2.unary_union

def near(point, pts=pts3):
    #you could use inner.Coordinates2
    nearest = inner.geometry == nearest_points(point, pts)[1]
    return inner[nearest].node.get_values()[0]

# apply or lambda doesnt translate geometry to Coordinates1
outer['Nearest'] = outer.apply(lambda row: near(row.Coordinates1), axis=1)
print(outer)

Production:

node  x_coord  y_coord   Coordinates1  Nearest
0     0        0      258  POINT (0 258)        3
1     1        0      259  POINT (0 259)        3
2     2        0      260  POINT (0 260)        3
3     3        0      261  POINT (0 261)        3
4     4        0      230  POINT (0 230)        4

Après, si vous avez un grand nombre de points je vous suggère d'utiliser cKDTree :

from scipy.spatial import cKDTree
def ckdnearest(gdA, gdB, bcol):
    nA = np.array(list(zip(gdA.geometry.x, gdA.geometry.y)))
    nB = np.array(list(zip(gdB.geometry.x, gdB.geometry.y)))
    btree = cKDTree(nB)
    dist, idx = btree.query(nA, k=1)
    df = pd.DataFrame.from_dict({'distance': dist.astype(int),
                                 'bcol': gdB.loc[idx, bcol].values})
    return df


df = ckdnearest(outer, inner, 'node')
print(df)

Production:

    distance  bcol            (bcol equal node of inner
0         1     3
1         0     3
2         1     3
3         2     3
4         2     4
2
Frenchy 17 mars 2019 à 08:23

Au cas où quelqu'un d'autre aurait du mal avec une ancienne version de géopandas. Voici la solution:

from scipy.spatial import cKDTree
def ckdnearest(gdA, gdB, bcol):
    nA = np.array(list(zip(gdA.geometry.map(lambda val: val.x), 
    gdA.geometry.map(lambda val: val.y))))
    nB = np.array(list(zip(gdB.geometry.map(lambda val: val.x), 
    gdB.geometry.map(lambda val: val.y))))
    btree = cKDTree(nB)
    dist, idx = btree.query(nA, k=1)
    df = pd.DataFrame.from_dict({'distance': dist.astype(int),
                                 'bcol': gdB.loc[idx, bcol].values})
    return df


df = ckdnearest(outer, inner, 'node')
print(df)
1
Emily 17 mars 2019 à 13:46