Skupina lat/lon , pokud se vyskytují witin vymezovací rámeček

0

Otázka

Mám datovém takto:

1

Vytvořil jsem vymezovací rámeček 10 km do 10 km.

def create_space(lat, lon, s=10):
    n = (180/math.pi)*(500/6378137)*10
    return lat - n, lon - n, lat + n, lon + n

Teď bych chtěl vidět, pokud dva nebo více řádků v mém datovém (lat a lon) jsou uvnitř vymezovacího rámečku. Pokud některý lat a lon spadají do vymezovacího rámečku, já bych chtěl přidat událost. například, pokud index[9] na podzim v ohraničovacího rámečku index[0], výskyt by 6495+23 a index[9] by měla být zrušena.

Já mám tohle:

2

Snažil jsem se

step =0.1
to_bin = lambda x: np.floor(x / step) * step
df["latbin"] = df.lat.map(to_bin)
df["lonbin"] = df.lon.map(to_bin)
#groups = df.groupby(("latbin", "lonbin"))

Ale to didnot vyřešit můj problém a já dont vědět, jak se posunout dále.

bounding-box geopandas iteration pandas
2021-11-15 14:36:19
2
0

Moje řešení je vytvořit geopandas.geoseries.GeoSeries což představuje vašeho vymezovacího rámečku na mapě. Pak tam jsou stávající nástroje v jazyce Python, aby otestovat, zda je bod uvnitř, nebo ne.

Ale protože nemám data, tu používám jen nejjednodušší příklad, aby vám ukázat, jak moje kódy pracovat.

# import packages
import geopandas as gpd
from shapely.ops import cascaded_union
from shapely import geometry

# create a function to build the "geopandas.geoseries.GeoSeries" for your bounding box
def create_boundingbox(p1,p2,p3,p4): 
    '''provide four corner points as (lon,lat), 
       the order is bottom-left(p1), bottom-right(p2), top-right(p3),top-left(p4) on a map'''
    p1 = geometry.Point(p1)
    p2 = geometry.Point(p2)
    p3 = geometry.Point(p3)
    p4 = geometry.Point(p4)
    pointList = [p1, p2, p3, p4, p1]
    boundingbox = geometry.Polygon([[p.x, p.y] for p in pointList])
    boundingbox = gpd.GeoSeries(cascaded_union(boundingbox))
    return boundingbox

# use some simple points as an example

# construct your box
p1 = (0,0)
p2 = (1,0)
p3 = (1,1)
p4 = (0,1)

box1 = create_boundingbox(p1,p2,p3,p4)

# now test if these points are inside or not
p5 = geometry.Point(0.5,0.5)
p6 = geometry.Point(15,15)

print(box1.contains(p5)) # this is True
print(box1.contains(p6)) # this is False
2021-11-17 01:43:44
0

Všimněte si, že při použití lon-lat, jsou vaše čehož vyplývá, zeměkoule nějakého druhu, a že množina bodů popisuje dva možné sférické mnohoúhelníky na povrchu spehre. Tady předpokládám, že chceš menší. Pokud si objednáte bodů ve směru hodinových ručiček, pak můžete použít postup popsaný zde pomocí lineární algebry.

Toto vezme v úvahu podmínky, kde jste obeplutí tyč nebo antimeridian, a vypadá to na velké kruhy spojující body (úsečka spojující (000, 45) a (100, 45) ano ne následovat 45 ° paralelní. Takže, myslím, že pečlivě o tom, co máte na mysli tím, že na náměstí jako čtverce (tak, jak jsme normálně přemýšlet o nich) nemají závěs na kouli.

V závislosti na aplikaci, Jeremyho odpověď by mohla být dostačující, ale v některých případech to nemusí být.

Přístup naznačuji níže, je založen na odpověď na otázku, na kterou jsem se ptal tady, který vysvětluje matematiku, co jsem prováděcích zde.

Nejprve budete muset převést své body na vektory (můžete použít koule jednotky)

import numpy as np
def deg2rad(theta):
    return(theta * np.pi / 180)
def get_xyz(p):
    lon = deg2rad(p[0])
    lat = deg2rad(p[1])
        
    return(np.array([np.cos(lat) * np.cos(lon),
                     np.cos(lat) * np.sin(lon),
                     np.sin(lat)]))

Takže pro vaše čtyři body vytvořit čtyři vektory popisující umístění v kartézských souřadnicích. Například,

p1 = [ 170, -10]
p2 = [-170, -10]
p3 = [-170, 10]
p4 = [ 170, 10]
v1 = get_xyz(p1)
v2 = get_xyz(p2)
v3 = get_xyz(p3)
v4 = get_xyz(p4)

Každá strana mnohoúhelník je část velké kružnice a vektor kolmý k rovině, je n1 = np.cross(v1, v2)atd.:

n1 = np.cross(v1, v2)
n2 = np.cross(v2, v3)
n3 = np.cross(v3, v4)
n4 = np.cross(v4, v1)

Pokud nějaký bod v5 je uvnitř polygonu popsal v1, v2, v3, v4, pak skalární součin v5 s každou n-vektory bude větší než 1. (Pokud je na okraji jedné ze stran, pak se to bude rovnat 1.)

p5 = [180, 0]
v5 = get_xyz(p5)

in_poly = (np.dot(v5, n1)) > 0 and \
    (np.dot(v5, n2)) > 0 and \
    (np.dot(v5, n3)) > 0 and \
    (np.dot(v5, n4)) > 0

print(in_poly) # True

p5 = [180, 20]
v5 = get_xyz(p5) 

in_poly = (np.dot(v5, n1)) > 0 and \
    (np.dot(v5, n2)) > 0 and \
    (np.dot(v5, n3)) > 0 and \
    (np.dot(v5, n4)) > 0

print(in_poly) # False

EDIT:

Dnes ráno mi došlo, že jsem nevysvětlil, jak na bin data. Dávám si to ve slovníku, ale tady si můžete vytvořit sloupce v datovém udělat něco podobného. Také, není to můj grid boxy musí být konvexní (ne pacman tvary) a rohy vašeho bodu mřížky musí být poskytnuty v proti-směru hodinových ručiček.

def in_poly(poly, point):
   v_vec = [get_xyz(p) for p in poly]
   n_vec = [np.cross(v_vec[i], v_vec[(i+1)%len(v_vec)]) for i in range(len(v_vec))]
   v_p = get_xyz(point)
   dot_prod = [np.dot(n, v_p) for n in n_vec]
   if all(d > 0 for d in dot_prod):
      return True
   else:
      return False

p1 = [ 170, -10]
p2 = [-170, -10]
p3 = [-170,  10]
p4 = [ 170,  10]
p5 = [ 150, -10]
p6 = [ 150,  10]
P = {1: [p1, p2, p3, p4],
     2: [p1, p4, p6, p5]}
InBox = {1: 0, 2: 0}

Npts = 100
lonlim = [150, 190]
latlim = [-20, 20]
points = np.stack([np.random.randint(lonlim[0], lonlim[1], Npts),
                   np.random.randint(latlim[0], latlim[1], Npts)])


for i in range(Npts):
   for key in InBox.keys():
      if in_poly(P[key], points[:,i]):
         InBox[key] += 1

print(InBox) 
#{1: 25, 2: 22}
2021-11-17 15:19:19

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................