Обозначенные типы данных Python

Я вычисляю геодезические расстояния между точками и несколькими отрезками. Каждый сегмент линии имеет уникальный идентификационный номер. Я хочу вернуть расстояние от моей функции расстояний так, чтобы они оба были связаны друг с другом. Я также хотел бы поддерживать функциональность, как в сортировке расстояний, так и индексировать их либо ярлыком, либо позицией, а также возвращать как данные расстояния, так и метку. Что-то вроде серии Pandas с индексом, но я не могу использовать серию, потому что данные возвращаются в Pandas DataFrame, который затем расширяет серию и создает беспорядок. Вот пример:

In [1]: '''Note that all this happens inside an apply function of a Pandas Series''' labels = [25622, 25621, 25620, 25619, 25618] dist = vect_dist_funct(pt, labels) #vect_dist_funct does the computations, and returns distances in meters dist Out[1]: array([296780.2217658355, 296572.4476883276, 296364.21166884096, 296156.4366241771, 295948.6610171968], dtype=object) 

Однако, что я хочу, это что-то вроде этого dict, где метки и расстояния связаны друг от друга по своей сути:

 {25622 : 296780.2217658355, 25621 : 296572.4476883276, 25620 : 296364.21166884096, 25619 : 296156.4366241771, 25618 : 295948.6610171968} 

Но теперь я потерял функциональность значений. Я не могу легко сортировать их или сравнивать их или что-то еще. Я посмотрел на Numpy Structured Arrays , и они кажутся работоспособными, но если я не смогу сортировать расстояния и получить индекс ближайшего сегмента, это будет не очень полезно для меня. Есть ли другой тип данных, который я могу использовать?

Длинная история и история

Я пытаюсь сделать пространственное соединение. Я получаю индексы сегментов, точка, скорее всего, ближе к поиску в RTree ( пример ). Это индексы в ярлыках. Затем я просматриваю таблицу геометрии линий, чтобы найти геометрию линии для выбранных меток, и вычислить расстояния точек до каждого из сегментов линии.

Следующие шаги включают проверку работоспособности пространственного соединения. Ближайший не является лучшим кандидатом на присоединение в некоторых случаях, и соединение нужно оценивать по другим параметрам. Поэтому мой план состоит в том, чтобы работать из ближайшего сегмента наружу. Это будет включать сортировку на расстояниях и получение индексов ближайшего сегмента, а затем просмотр таблицы сегментов с этим индексом и извлечение других свойств строки для проверки. Если совпадение может быть подтверждено, указанный сегмент принят, иначе он будет отклонен, и алгоритм переместится в следующий ближайший сегмент.

Тип данных, который делает все это, я ищу, не нарушая связь между расстояниями, от сегмента, из которого он был вычислен.

Проблема с использованием Pandas

Так вот как фактически называется функция:

 joined = points['geometry'].apply(pointer, centroid=line['centroid'], tree_idx=tree_idx)) 

Затем внутри pointer это происходит:

 def pointer(point, centroid, tree_idx): intersect = list(tree_idx.intersection(point.bounds)) if len(intersect) > 0: points = pd.Series([point.coords[0]]*len(intersect)).values polygons = centroid.loc[intersect].values dist = vect_dist_funct(points, polygons) return pd.Series(dist, index=intercept, name='Dist').sort_values() else: return pd.Series(np.nan, index=[0], name='Dist') 

И вот, joined выглядит так:

Думаю, нет смысла копировать таблицу.

Это связано с тем, что расстояния между всеми точками (строки – это точки) и все строки (столбцы – это строки) не вычисляются. Это было бы слишком дорогостоящим (4M точек и 180k строк на каждое состояние и 50 состояний на весь набор данных). Кроме того, эта операция слияния DataFrame с созданным joined увеличивает время выполнения 7 раз, по сравнению с тем, когда я возвращаю два массива Numpy. Проблема с возвращением двух массивов Numpy заключается в том, что нелегко постоянно поддерживать расстояние и идентификаторы линий.

Примеры точек, линий, tree_idx

Обратите внимание, что это усеченный набор данных в столбцах и строках. Я включаю только столбцы релевантности, а не остальные данные:

точки:

  geometry id 88400001394219 0.00 POINT (-105.2363291 39.6988139) 0.25 POINT (-105.2372017334178 39.69899060448157) 0.50 POINT (-105.2380177896182 39.69933953105642) 0.75 POINT (-105.2387202141595 39.69988447162143) 1.00 POINT (-105.2393222 39.7005405) 88400002400701 0.00 POINT (-104.7102833 39.8318348) 0.25 POINT (-104.7102827 39.831966625) 0.50 POINT (-104.7102821 39.83209845) 0.75 POINT (-104.7102815 39.832230275) 1.00 POINT (-104.7102809 39.8323621) 

Таким образом, это в основном интерполированные точки на линиях. Идентификатор строки – это первый уровень индекса, а второй уровень – это процент, где точка была интерполирована. Это формирует первый набор данных, набор данных, к которому я хочу принести некоторые атрибуты из второго набора данных.

линия:

  geometry centroid id 71345 POLYGON ((-103.2077992965318 40.58026765162965... (-103.20073265160862, 40.576450381964975) 71346 POLYGON ((-103.2069505830457 40.58155121711739... (-103.19987394433825, 40.57774903464972) 71347 POLYGON ((-103.2061017677045 40.58283487609803... (-103.19901204453959, 40.57905245493993) 71348 POLYGON ((-103.2052000154291 40.58419853220472... (-103.19815200508097, 40.58035300329024) 71349 POLYGON ((-103.2043512639656 40.58548197865339... (-103.19729445792181, 40.58164972491414) 71350 POLYGON ((-103.2035025651746 40.5867652936463,... (-103.1964362470977, 40.5829473948391) 71351 POLYGON ((-103.2026535431035 40.58804903349249... (-103.19557847342394, 40.58424434094705) 71352 POLYGON ((-103.201804801526 40.58933229190573,... (-103.19472966696722, 40.58552767098465) 71353 POLYGON ((-103.2009557884142 40.59061590473365... (-103.19388484652855, 40.58680427447224) 71354 POLYGON ((-103.2001001699726 40.59190793446012... (-103.19303392095904, 40.5880882237994) 

Это часть второго набора данных (метки, упомянутые в начале этого ответа, являются индексом этого набора данных). Цель состоит в том, чтобы передавать атрибуты из этого набора данных в набор данных точек разумным образом. Первым шагом будет найти ближайшую линию к каждой из точек. Затем я сравню некоторые атрибуты из набора данных точек с набором данных линий и подтвержу или отклоняю соединение, как я уже упоминал.

tree_idx:

tree_idx создается с помощью следующего кода:

 import rtree lines_bounds = lines['geometry'].apply(lambda x: x.bounds) tree_idx = rtree.index.Index() for i in lines_bounds.index: tree_idx.insert(i, lines_bounds.loc[i]) 

3 Solutions collect form web for “Обозначенные типы данных Python”

Поэтому я думаю, что ваша общая проблема заключается в том, что вы создаете DataFrame где метка столбца является значением intercept . Я думаю, что вы хотите создать DataFrame где один столбец содержит значения перехвата, а другой содержит расстояния. Я постараюсь дать вам код, который, я думаю, поможет, но трудно быть уверенным, не имея исходных данных, поэтому вам нужно немного изменить его, чтобы он работал отлично.

Во-первых, я бы vect_dist_funct поэтому, если первый аргумент является скаляром, он создает список правильной длины, а если второй пустой, он возвращает NaN .

Затем я добавлю все полезные значения в виде столбцов в DataFrame:

 points['intersect'] = points['geometry'].apply(lambda x: np.array(tree_idx.intersection(x.bounds))) points['polygons'] = points['intersect'].apply(lambda x: centroid.loc[x].values) points['coords0'] = points['geometry'].apply(lambda x: x.coords[0]) points['dist'] = points.apply(lambda x: vect_dist_funct(x.coords0, x.polygons), axis=1) 

Это даст вам столбец со всеми его расстояниями. Если вы действительно хотите, чтобы значения перехвата были доступны, вы можете затем создать DataFrame только с перехватами и расстояниями, а затем перехватить в качестве другого уровня multiindex, чтобы избежать слишком большого количества значений NaN :

 pairs = points.apply(lambda x: pd.DataFrame([x['intersect'], x['dist']], index=['intersect', 'dist']).T.stack(), axis=1) pairs = pairs.stack(level=0).set_index('intersect', append=True) pairs.index = pairs.index.droplevel(level=2) 

Это должно дать вам Series где первым индексом является id, второй – процент, третий – пересечение, а значение – это расстояние.

Итак, я думаю, что кадр данных, индекс которого является ярлыками, вероятно, является самым простым

 distances = {25622 : 296780.2217658355, 25621 : 296572.4476883276, 25620 : 296364.21166884096, 25619 : 296156.4366241771, 25618 : 295948.6610171968} df = pd.DataFrame([tup for tup in distances.items()],columns=["label", "dist"]).sort_values('dist').set_index('label') df 

Выходы:

  dist label 25618 295948.661017 25619 296156.436624 25620 296364.211669 25621 296572.447688 25622 296780.221766 

Затем, если вы хотите получить доступ к расстоянию по названию ярлыка

 df.loc[25620] Out: dist 296364.211669 Name: 25620, dtype: float64 

И тогда, если вы хотите найти метки рядом с этой точкой, вы можете получить номер строки с помощью

 row_num = df.index.get_loc(25620) print(row_num) Out: 2 

И тогда вы можете получить доступ к «близким» точкам с помощью df.iloc[row_number]

 df.iloc[3] Out: dist 296572.447688 Name: 25621, dtype: float64 

Это покрывает все, что вам нужно?

После всего, и после попытки заставить ответ TheBlackCat работать около 3 часов, я решил использовать xarray . Итак, теперь функция pointer выглядит так:

 def pointer(point, centroid, tree_idx): intersect = list(tree_idx.intersection(point.bounds)) if len(intersect) > 0: points = pd.Series([point.coords[0]]*len(intersect)).values polygons = centroid.loc[intersect].values dist = vect_dist_funct(points, polygons) sorter = np.argsort(dist) return xr.DataArray(dist[sorter], [('dim0', np.asarray(intersect)[sorter])]) else: return xr.DataArray(np.nan) 

Готово. Это работает для моих нужд. У меня есть расстояния и идентификатор сегмента, из которого они были вычислены вместе, так что преобразования на одном, влияют на другое. И расстояния все еще работоспособны, и xarray также дает мне расширенную функциональность с точки зрения группировки, слияния и т. Д.

Кроме того, это занимает около минуты, чтобы работать на 0,1% данных для состояния и 10 минут для 10% данных. Поэтому я ожидаю, что 100% данных будет около 100 минут. Но, честно говоря, даже если для состояния потребовалось 3 часа, я могу закончить все 50 состояний в течение дня (используя многопоточность на 16-ядерном сервере). Так что пока я доволен этим. Спасибо всем моим предложениям. Особенно @TheBlackCat, @michael_j_ward и @hpaulj.

  • pandas: Вычислить процентиль по строке и грациозно обрабатывать неединственные значения?
  • pandas: несколько условий при индексировании кадра данных - неожиданное поведение
  • Пропустить gcf (). Autofmt_xdate () при создании сюжета панды
  • Python: ускоренная работа для индексирования
  • Данные и скорость передачи данных Pandas
  • Как сбросить нулевые значения в Pandas?
  • Как получить имена листов из файлов XLS без загрузки всего файла?
  • Преобразование списка в dict в серию
  • Python - лучший язык программирования в мире.