КПП в двух полигонах (улучшение кода)

Вопрос: Я хочу улучшить свой код, чтобы получить ID автомобилей началось и закончилось между заданными 2 зонами города.

У меня есть:

  1. `.csv файл, содержащий такие городские зоны:

    borders =
    
    zone longitude latitude multi
    12   3.5248    22.0952  MULTIPOLYGON(((3.4991688909 22.1096707778,3.4992650150 22.1094740107, ... ,3.4992922409 22.1094203597,3.4995744041 22.1087939694,3.4997139945 22.1081206986)))
    14   3.5139    22.111   MULTIPOLYGON(((12.4991688909 22.1096707778,3.4992650150 22.1094740107, ... ,32.4992922409 22.1094203597,3.4995744041 32.1087939694,3.4997139945 22.1081206986)))
    ...
    800  3.5273    22.1019  MULTIPOLYGON(((4.4991688909 15.1096707778,3.4992650150 22.1094740107, ... ,4.4992922409 75.1094203597,3.4995744041 22.1087939694,3.4997139945 22.1081206986)))
    

Таким образом, я хочу проверить,

  1. Файл .csv, содержащий данные об автомобилях такси:

    data = 
    
    ID      latitude longitude epoch        day_of_week
    
    e35f6   11.9125  3.7432    8765456787    Sunday
    e35f6   11.9125  3.7432    4567876545    Sunday
    ...
    fhg3g   23.9125  5.7432    2345434554    Sunday
    

Таким образом, я хочу проверить, ID моя машина начинает поездку в zone 12 и заканчивается в zone 14 (но я хочу проверить каждую зону)

Что я сделал до сих пор:

  • Я вручную перехожу к файлу border, выбираю 2 строки, создаю новый файл csv, вручную ввожу геоданные мультиполигона и конвертирую t в POINT (геопанды)
  • То же самое делать data

потом

  • Выбор первой и последней точки каждого идентификатора в data
  • я проверяю, если моя первая точка в пределах первой зоны и последняя точка в пределах второй зоны.
  • Затем слияние новых фреймов данных для проверки пересекающихся ID, чтобы увидеть, стартовала ли та же машина и закончилась ли она в зоне.

Но это очень трудоемкий процесс. Ищу улучшение. Вот мой код:

df_first = df.drop_duplicates(subset=['id_easy'], keep='first') # removed duplicates
df_last = df.drop_duplicates(subset=['id_easy'], keep='last') # removed duplicates

crs = {'init':'epsg:4326'}
geometry_first = [Point(xy) for xy in zip(df_first.longitude,df_first.latitude)]
df_first = gpd.GeoDataFrame(df_first,crs=crs,geometry=geometry_first)

geometry_last = [Point(xy) for xy in zip(df_last.longitude,df_last.latitude)]
df_last = gpd.GeoDataFrame(df_last,crs=crs,geometry=geometry_last)

border_1 = pd.read_csv("D:/anaconda path/PTV/1) Data preparation/between zones/zone1.csv")

geometry_1 = [Point(xy) for xy in zip(border_1.longitude,border_1.latitude)]
border_1 = gpd.GeoDataFrame(border_1,crs=crs,geometry=geometry_1)

border_2 = pd.read_csv("D:/anaconda path/PTV/1) Data preparation/between zones/zone2.csv")

geometry_2 = [Point(xy) for xy in zip(border_2.longitude,border_2.latitude)]
border_2 = gpd.GeoDataFrame(border_2,crs=crs,geometry=geometry_2)

turin_final_1 = Polygon([[p.x, p.y] for p in border_1.geometry])
first = df_first[df_first.geometry.within(turin_final_1)]

turin_final_2 = Polygon([[p.x, p.y] for p in border_2.geometry])
last = df_last[df_last.geometry.within(turin_final_2)]
first.epoch = pd.to_datetime(first.epoch,unit = 's')

first.index = pd.to_datetime(first.epoch)
last.index = pd.to_datetime(last.epoch)

first1 = first.between_time('0:00', '1:00')
last1 = last.between_time('0:00', '1:00') #till to 24

first1.to_csv(r'D:\anaconda path\PTV\1) Data preparation\between zones\df1\Saturday1_first1.csv',index=False)
last1.to_csv(r'D:\anaconda path\PTV\1) Data preparation\between zones\df2\Saturday1_last1.csv',index=False) #till to 24

os.chdir("D:/anaconda path/PTV/1) Data preparation/between zones/df1")

extension = 'csv'
all_filenames = [i for i in glob.glob('*.{}'.format(extension))]

df1 = pd.concat([pd.read_csv(f) for f in all_filenames ])
#export to csv
df1.to_csv( "df1.csv", index=False, encoding='utf-8-sig')

os.chdir("D:/anaconda path/PTV/1) Data preparation/between zones/df2")

extension = 'csv'
all_filenames = [i for i in glob.glob('*.{}'.format(extension))]

df2 = pd.concat([pd.read_csv(f) for f in all_filenames ])
#export to csv
df2.to_csv( "df2.csv", index=False, encoding='utf-8-sig')

df1 = pd.read_csv("D:/anaconda path/PTV/1) Data preparation/between zones/df1/df1.csv")
df2 = pd.read_csv("D:/anaconda path/PTV/1) Data preparation/between zones/df2/df2.csv")

df3 = (pd.concat((df1[df1.id_easy.isin(df2.id_easy)],
            df2[df2.id_easy.isin(df1.id_easy)]),
           ignore_index=True)
    .sort_values('id_easy'))

person Community    schedule 21.10.2019    source источник


Ответы (1)


Если я правильно понял, вы хотите присвоить номер зоны начальной и конечной точкам каждой машины. Поскольку у вас есть многоугольная информация о форме городских зон (несколько столбцов) в данных границ, я предлагаю вам использовать эту информацию для пространственного объединения в начальной / конечной точках, чтобы увидеть, в какой зоне автомобиль начинает / заканчивает поездку. Вот мое предложение более подробно:

Я предполагаю, что вы уже прочитали данные в border и data и что они отформатированы правильно (т.е. каждая ячейка в столбце multi в border содержит Shapley.Multipolygon). Я также предполагаю, что ваши зоны не пересекаются, то есть не перекрываются.

GeoDataFrame нужен столбец геометрии, поскольку он может распознавать только столбец с таким именем как геометрическую информацию:

border['geometry'] = border['multi']

Теперь мы также генерируем геометрическую информацию для точек, указанных в данных автомобиля в df:

df['geometry'] = df[['longitude', 'latitude']].apply(lambda x: Point(x[0], x[1]), axis=1)

Как вы это сделали, давайте теперь извлечем начальную и конечную точки:

df_first = df.drop_duplicates(subset=['id_easy'], keep='first')
df_last = df.drop_duplicates(subset=['id_easy'], keep='last')

Теперь мы можем выполнить пространственное соединение, чтобы получить нужные зоны каждой начальной и конечной точки:

df_first = gpd.sjoin(df_first, shp.loc[:, ['geometry', 'zone']], how='left', op='within')
df_last = gpd.sjoin(df_last, shp.loc[:, ['geometry', 'zone']], how='left', op='within')

Вот и все. Теперь у вас есть информация о зонах в столбце zone для каждой точки.

person bexi    schedule 31.10.2019