Контрольная точка в двухугольнике (улучшение кода) - PullRequest
1 голос
/ 21 октября 2019

Вопрос: Я хочу улучшить свой код, чтобы получить 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)))
    

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

.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
  • theb cheking, если моя первая точка в первой зоне и последний финт во второй зоне.
  • Затем объединяются новые фреймы данныхпроверить пересекающиеся ID s, чтобы увидеть, начиналась и заканчивалась ли та же машина в зоне.

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

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'))

1 Ответ

0 голосов
/ 31 октября 2019

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

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

A 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 для каждой точки.

...