Письма читателей
я был раньше 1. Сначала используйте растр Arcgis для преобразования точек. 2. Добавьте координаты xy к точке. 3. Добавьте к точкам атрибуты административного района после добавления координат xy через пространственную связь. 4. Наконец, рассчитайте центроид назначенной административной области. Предыдущее решение заключалось в использовании arcgis для выполнения первого и второго шагов. Хотя завершение было очень медленным, казалось, что большой проблемы не было. Но на третьем этапе arcgis зависнет, а затем и geopandas. Позже я узнал о dask-geopandas, но он вроде сообщал об ошибке после обработки около двух миллионов точек. Не знаю, есть ли проблема. с кодом, который я написал, или со мной. У меня проблемы с пониманием dask, и я хочу спросить у кого-нибудь совета.
Вопрос читателя включает в себя ряд шагов в операциях географической информационной системы (ГИС), включая преобразование растровых данных в точечные данные, добавление координат XY к этим точечным данным, добавление атрибутов административной области к этим точкам посредством пространственных связей и расчет обозначенных административных территорий. центр масс. Читатель не столкнулся с очевидными проблемами при использовании программного обеспечения ArcGIS для выполнения первых двух шагов, но столкнулся с узким местом в производительности при выполнении третьего шага, то есть система зависала при использовании ArcGIS и GeoPandas для выполнения операций пространственного соединения. Чтобы решить эту проблему, читатель попытался использовать dask-geopandas для обработки данных около двух миллионов точек, но, похоже, столкнулся с ошибкой.
В ответ на эту ситуацию мы можем проанализировать и внести предложения по нескольким аспектам:
Анализ узких мест производительности:
ArcGIS и GeoPandas могут испытывать проблемы с производительностью при обработке больших объемов данных, особенно при работе на скромном оборудовании. Это связано с тем, что эти операции часто требуют больших объемов памяти и ресурсов ЦП. Пространственное соединение, особенно при большом объеме точечных данных, является ресурсоемкой операцией, поскольку требует для каждой точки проверки ее пространственного соотношения с другими геометрическими объектами (например, границами административных округов). Использование dask-geopandas:
dask-geopandas направлен на решение аналогичных проблем с производительностью, повышая эффективность обработки крупномасштабных геопространственных данных посредством параллельных вычислений и отложенного выполнения. Если вы столкнулись с ошибками при использовании dask-geopandas, это может быть связано с множеством причин, включая, помимо прочего, проблемы с кодом, управлением памятью, планированием задач и т. д. Чтобы лучше диагностировать проблему, необходимо изучить конкретное содержание сообщения об ошибке. Это может указывать на проблему с конфигурацией, недостаточность ресурсов или логическую ошибку кода. Предложения по оптимизации:
Распределение ресурсов. Убедитесь, что имеется достаточно вычислительных ресурсов (ЦП и памяти) для обработки данных. Для dask-geopandas производительность можно оптимизировать, регулируя количество рабочих процессов и ограничения памяти Dask. Проверка кода. Тщательно проверьте код реализации, особенно часть dask-geopandas, чтобы убедиться, что функции параллельных вычислений и разделения данных используются правильно. Пакетная обработка: если возможно, старайтесь обрабатывать данные меньшими партиями, а не обрабатывать все точки одновременно. Это может помочь снизить нагрузку на память. Индексирование и оптимизация. Перед выполнением пространственных соединений создание пространственных индексов для данных административных округов может значительно повысить эффективность запросов.
Обратите внимание, что вам необходимо распаковать входной файл RAR перед запуском программы.
Потратив некоторые усилия на решение проблемы окружающей среды, выполните следующие действия, чтобы использовать dask_geopandas.
In [1]:
!pip install dask_geopandas -i https://pypi.mirrors.ustc.edu.cn/simple/
!pip install PyGEOS -i https://pypi.mirrors.ustc.edu.cn/simple/
!pip install --upgrade shapely https://pypi.mirrors.ustc.edu.cn/simple/
!pip install pyogrio -i https://pypi.mirrors.ustc.edu.cn/simpl
Преобразование DataFrame GeoPandas в DataFrame Dask-GeoPandas Сначала используйте GeoPandas для чтения файла географических данных:
питон импортировать геопанды df = geopandas.read_file('...') # Замените '...' своим путем к файлу Затем преобразуйте его в DataFrame Dask-GeoPandas:
python import dask_geopandas
ddf = dask_geopandas.from_geopandas(df, npartitions=4) По умолчанию это просто перераспределяет данные на основе строк. Однако вы также можете обеспечить пространственное разделение, чтобы воспользоваться преимуществами пространственной структуры GeoDataFrame.
python
ddf = ddf.spatial_shuffle() Знакомые пространственные свойства и методы из GeoPandas также доступны и будут рассчитываться параллельно:
python
ddf.geometry.area.compute()
ddf.within(многоугольник) Кроме того, если у вас есть распределенный dask.dataframe, вы можете передать столбец точек XY в метод set_geometry, чтобы установить геометрию.
python import dask.dataframe as dd import dask_geopandas
ddf = dd.read_csv('...') # Замените '...' своим путем к файлу
ddf = ddf.set_geometry( dask_geopandas.points_from_xy(ddf, 'долгота', 'широта') ) В настоящее время поддерживает запись (и обратное чтение) форматов файлов Parquet и Feather:
python
ddf.to_parquet("path/to/dir/")
ddf = dask_geopandas.read_parquet("путь/к/каталогу/") Традиционные форматы файлов ГИС можно считывать в секционированные GeoDataFrames (требуется pyogrio), но запись не поддерживается:
python
ddf = dask_geopandas.read_file("file.gpkg", npartitions=4) Выше приведен простой пример использования Dask-GeoPandas для эффективной обработки больших геопространственных данных.
In [2]:
import geopandas as gpd
import time # Добавить модуль времени
# Добавить модуль даск
import dask_geopandas
def process_row():
outwen = '/home/mw/input/dask6250/201105.shp'
bianjie = '/home/mw/input/dask6250/xian/2023xian.shp'
jiabianjie = './'
start_time3 = time.time()
# Чтение входных данных и границ обрезки shapefile
target_gdf = gpd.read_file(outwen)
join_gdf = gpd.read_file(bianjie)
# Перейти в рабочий режим
target_gdfnew = dask_geopandas.from_geopandas(target_gdf, npartitions=4)
# Перепроецируйте границы участвующих соединений, чтобы они соответствовали целевой геометрии. CRS
join_gdf = join_gdf.to_crs(target_gdf.crs)
# Перейти в рабочий режим
join_gdfnew = dask_geopandas.from_geopandas(join_gdf, npartitions=4)
# Найдите пересекающиеся части, используя пространство соединять
joined = gpd.sjoin(target_gdfnew, join_gdfnew, how='inner', predicate='intersects')
# Воля 'bianjie' Свойства в добавлены в 'outwen' середина
joined = joined.drop(columns='index_right') # Удаление избыточных столбцов индекса
result = target_gdfnew.merge(joined, how='left', on=target_gdfnew.columns.to_list())
# Сохранение результатов в границах вывода
result.to_file(jiabianjie, encoding='utf-8-sig') # Обязательно используйте правильную кодировку
end_time3 = time.time()
execution_time3 = end_time3 - start_time3
print(f"'{jiabianjie}' добавил границу, время начала: {start_time3:.2f}, время окончания: {end_time3:.2f}, время выполнения: {execution_time3:.2f} секунд ")
process_row()
print('finish')
Хорошо, память исчерпана после некоторого времени работы. Вам следует рассмотреть следующие стратегии оптимизации:
Ваш код сначала считывает шейп-файл с помощью geopandas, а затем преобразует его в объект dask_geopandas. Во время этого процесса исходные данные будут полностью загружены в память, что может быть одной из причин переполнения памяти. Вместо этого вам следует использовать dask_geopandas.read_file напрямую, чтобы избежать одновременной загрузки всего набора данных в память:
python
target_dgdf = dask_geopandas.read_file(outwen, npartitions=4)
join_dgdf = dask_geopandas.read_file(bianjie, npartitions=4)
Во время обработки данных постарайтесь сократить ненужное копирование данных. Например, перед операцией слияния или объединения тщательно подумайте, все ли столбцы должны участвовать в операции.
При использовании dask_geopandas для пространственных соединений убедитесь, что операция эффективна. Ваш код пытается использовать geopandas.sjoin, но следует использовать dask_geopandas.sjoin. Кроме того, перед выполнением пространственного соединения убедитесь, что два набора данных имеют совпадающие системы координат (CRS). Это позволяет избежать повторения дорогостоящих операций преобразования CRS в каждом разделе.
Выбор npartitions оказывает существенное влияние на производительность и использование памяти. Слишком малое количество разделов может привести к тому, что один раздел окажется слишком большим, а слишком большое количество разделов может увеличить затраты на планирование. Возможно, вам придется поэкспериментировать с разными значениями npartitions, чтобы найти лучший баланс.
Это также может вызвать проблемы с памятью, если вы попытаетесь записать весь обработанный набор данных в один файл при сохранении результатов. dask_geopandas в настоящее время может не поддерживать прямую запись в файлы таких форматов, как шейп-файлы, поскольку обычно это предполагает объединение наборов данных в один раздел. Возможно, вам придется сначала записать данные в такой формат, как Parquet, или записать их вручную вручную.
Измените параметры npartitions для своих ресурсов.
In [1]:
import dask_geopandas as dgd
import time
input_shapefile = '/home/mw/input/dask6250/201105.shp'
boundary_shapefile = '/home/mw/input/dask6250/xian/2023xian.shp'
output_directory = './output/'
def process_row(target_gdf, join_gdf, jiabianjie_pat):
start_time = time.time()
# Чтение шейп-файлов напрямую с помощью dask-geopandas
target_dgdf = dgd.read_file(input_shapefile, npartitions=16)
join_dgdf = dgd.read_file(boundary_shapefile, npartitions=16)
# Убедитесь, что шейп-файл границы соответствует CRS целевого шейп-файла.
join_dgdf = join_dgdf.to_crs(target_dgdf.crs)
# Найдите пересекающиеся части, используя пространство соединять
joined = dgd.sjoin(target_dgdf, join_dgdf, how='inner', predicate='intersects')
# Удаление избыточных столбцов индекса
joined = joined.drop(columns='index_right')
joined.compute().to_file(output_directory + 'result.shp', driver='ESRI Shapefile', encoding='utf-8')
# end_time = time.time()
# print(f"Границы были добавлены. Время начала: {start_time:.2f}, время окончания: {end_time:.2f}, время выполнения: {end_time - start_time:.2f} секунд")
if __name__ == "__main__":
process_row(input_shapefile,boundary_shapefile,output_directory)
print('finish')
In [ ]:
import dask_geopandas as dgd
import time
import gc # Импортируйте сборщик мусора
input_shapefile = '/home/mw/input/dask6250/201105.shp'
boundary_shapefile = '/home/mw/input/dask6250/xian/2023xian.shp'
output_directory = './'
def process_row(target_gdf, join_gdf, jiabianjie_pat):
start_time = time.time()
# В зависимости от конфигурации вашего оборудования nразделов, уменьшите количество разделов, чтобы уменьшить накладные расходы на Память
target_dgdf = dgd.read_file(input_shapefile,npartitions=16) # соответствующий Настроить nразделов
join_dgdf = dgd.read_file(boundary_shapefile,npartitions=16) # соответствующий Настроить nразделов
join_dgdf = join_dgdf.to_crs(target_dgdf.crs)
joined = dgd.sjoin(target_dgdf, join_dgdf, how='inner', predicate='intersects')
joined = joined.drop(columns='index_right')
# Запустите сбор мусора перед вычислением результата
gc.collect()
joined.compute().to_file(output_directory + 'result.shp', driver='ESRI Shapefile', encoding='utf-8')
# Вручную запустить выпуск сборки мусора Память
gc.collect()
end_time = time.time()
print(f"Границы были добавлены. Время начала: {start_time:.2f}, время окончания: {end_time:.2f}, время выполнения: {end_time - start_time:.2f} секунд")
if __name__ == "__main__":
process_row(input_shapefile, boundary_shapefile, output_directory)
print('finish')
/opt/conda/lib/python3.9/site-packages/geopandas/_compat.py:111: UserWarning: The Shapely GEOS version (3.10.0-CAPI-1.16.0) is incompatible with the GEOS version PyGEOS was compiled with (3.10.4-CAPI-1.16.2). Conversions between both will be slow.
warnings.warn(
/opt/conda/lib/python3.9/site-packages/geopandas/io/file.py:362: FutureWarning: pandas.Int64Index is deprecated and will be removed from pandas in a future version. Use pandas.Index with the appropriate dtype instead.
pd.Int64Index,
Пакетный запуск и сохранение с помощью gpkg
In [3]:
import dask_geopandas as dgd
import time
import gc
from dask import delayed, compute # отdaskсередина импортировать вычислительную функцию
input_shapefile = '/home/mw/input/dask6250/201105.shp'
boundary_shapefile = '/home/mw/input/dask6250/xian/2023xian.shp'
output_directory = './'
@delayed
def process_batch(batch, join_gdf, output_path):
# Воляграницаданные Преобразовать в Система координат целевых данных
join_gdf = join_gdf.to_crs(batch.crs)
# пространство исполнения соединять
joined = dgd.sjoin(batch, join_gdf, how='inner', predicate='intersects')
# Удалить ненужные столбцы
joined = joined.drop(columns='index_right')
# Рассчитайте и сохраните результаты
joined.compute().to_file(output_path, driver='GPKG', layer='result', encoding='utf-8') # Использование формата GeoPackage
def main():
start_time = time.time()
# Явно укажите npartitions
target_dgdf = dgd.read_file(input_shapefile, npartitions=16) # Задайте npartitions явно
join_dgdf = dgd.read_file(boundary_shapefile, npartitions=16) # Задайте npartitions явно
# Воля пакетная обработка набора целевых данных
batches = target_dgdf.to_delayed()
tasks = [process_batch(batch, join_dgdf, f"{output_directory}result_{i}.gpkg") for i, batch in enumerate(batches)]
# Используйте функцию вычислений dask для выполнения всех отложенных задач.
compute(*tasks)
gc.collect() # Вручную запустить выпуск сборки мусора Память
end_time = time.time()
print(f"Границы были добавлены. Время начала: {start_time:.2f}, время окончания: {end_time:.2f}, время выполнения: {end_time - start_time:.2f} секунд")
if __name__ == "__main__":
main()
print('finish')
/opt/conda/lib/python3.9/site-packages/geopandas/_compat.py:111: UserWarning: The Shapely GEOS version (3.10.0-CAPI-1.16.0) is incompatible with the GEOS version PyGEOS was compiled with (3.10.4-CAPI-1.16.2). Conversions between both will be slow.
warnings.warn(
Обратите внимание, что из-за ограничений ресурсов приведенный выше окончательный результат не был полностью выполнен. Вы можете видеть, что в каталоге проекта все еще есть часть gpkg. Поскольку размер выходного файла превышает лимит в 1 г, если вам интересно, запустите его на своем компьютере и измените параметры в соответствии с соответствующими ресурсами.
Кроме того, gpkg можно конвертировать в нужный шп с помощью геопанд.
In [ ]:
import geopandas as gpd
import pandas as pd
# Список документов GeoPackage
gpkg_files = ['path/to/your/first_file.gpkg', 'path/to/your/second_file.gpkg']
# Прочитать весь документ GeoPackage в список GeoDataFrameсередина
gdf_list = [gpd.read_file(gpkg) for gpkg in gpkg_files]
# Объединение объектов GeoDataFrame
merged_gdf = pd.concat(gdf_list, ignore_index=True)
# Укажите путь к выходному шейп-файлу
output_shp_path = 'path/to/your/output_file.shp'
# Воля Объединенный GeoDataFrame сохраняется как шейп-файл.
merged_gdf.to_file(output_shp_path, driver='ESRI Shapefile')
print(f"Объединенный шейп-файл был сохранен в: {output_shp_path}")
Нажмите ссылку, чтобы просмотреть полный код и работающий онлайн-код.