Производительность геопанд при преобразовании из Pandas WKT

#python #pandas #geopandas

Вопрос:

У меня есть требование прочитать ок. 10 миллионов записей из базы данных PostGIS в фрейм данных GeoPandas. Чтение данных непосредственно из базы данных занимает ок. 15 минут с помощью следующих:

 geopandas.GeoDataFrame.from_postgis(sql, engine)
 

Это приемлемо, но я пытался улучшить производительность чтения, используя команду копирования PostgreSQL вместе с функцией SQLAlchemy copy_export. Чтение данных с помощью этого метода в фрейм данных Pandas занимает около 60 секунд, что является огромным улучшением:

 def read_data(engine, sql):
    with tempfile.TemporaryFile() as tmpFile:
        copy_sql = "COPY ({query}) TO STDOUT WITH CSV {head}".format(
            query=sql, head='HEADER'
        )
        con = engine.raw_connection()
        cur = con.cursor()
        cur.copy_expert(copy_sql, tmpFile)
        tmpFile.seek(0)
        df = pandas.read_csv(tmpFile)
        return df
 

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

 def read_data(engine, sql):
    with tempfile.NamedTemporaryFile(suffix='.csv') as tmpFile:
        copy_sql = "COPY ({query}) TO STDOUT WITH CSV {head}".format(
            query=sql, head='HEADER'
        )
        con = engine.raw_connection()
        cur = con.cursor()
        cur.copy_expert(copy_sql, tmpFile)
        tmpFile.seek(0)
        gdf = geopandas.read_file(tmpFile.name)
        return gdf
 
 fiona.errors.DriverError: C:Temp4tmpiuu6dvl4.csv: file used by other process
 

Я пробовал различные способы снятия блокировки с временного файла, но безуспешно, поэтому я вернулся к чтению данных в фрейм данных Pandas, а затем преобразовал столбец геометрии. Это работает, но занимает столько же времени, сколько просто чтение данных непосредственно из базы данных в фрейм данных GeoPandas:

 def read_data(engine, sql):
    with tempfile.TemporaryFile() as tmpFile:
        copy_sql = "COPY ({query}) TO STDOUT WITH CSV {head}".format(
            query=sql, head='HEADER'
        )
        con = engine.raw_connection()
        cur = con.cursor()
        cur.copy_expert(copy_sql, tmpFile)
        tmpFile.seek(0)
        df = pandas.read_csv(tmpFile)
        df['geom'] = geopandas.GeoSeries.from_wkt(df['geom'])
        return geopandas.GeoDataFrame(df, geometry='geom', crs='EPSG:3857')
 

Часть, которая занимает очень много времени, — это преобразование WKT в геосерии:

 df['geom'] = geopandas.GeoSeries.from_wkt(df['geom'])
 

Кто-нибудь знает решение для решения проблемы с заблокированными файлами или для ускорения преобразования WKT в GeoSeries?

Спасибо

Комментарии:

1. Не могли бы вы извлечь несколько строк из вашего csv-файла, пожалуйста?

Ответ №1:

ГеоПандас должен создавать геометрические объекты, вот что требует времени. Не имеет значения, используете ли вы GeoDataFrame.from_postgis или ваш пользовательский код, потому что даже если бы вы read_data работали, вы закончили бы представлением геометрии WKT/WKB и все равно должны были бы позвонить from_wkt .

В настоящее время преобразование GeoPandas зависит от shapely, но у него есть экспериментальная поддержка pygeos, которая, вероятно, будет быстрее. Убедитесь, что в вашем окружении есть pygeo, и повторите GeoDataFrame.from_postgis попытку. Этот код уже достаточно хорошо оптимизирован, поэтому я не уверен, что вы можете легко ускорить работу с помощью пользовательского кода.

Чтобы получить pygeos:

 # conda
conda install pygeos --channel conda-forge
# pip
pip install pygeos
 

Видишь https://geopandas.readthedocs.io/en/latest/getting_started/install.html#using-the-optional-pygeos-dependency

Комментарии:

1. Я знал, что GeoPandas должен создавать геометрию, полагаю, я надеялся, что, возможно, было что-то, что я мог бы сделать лучше для повышения производительности. Ранее я пытался установить pygeos, но мне было трудно сделать это в Windows. Наконец-то я смог установить и настроить pygeos, но производительность совсем не улучшилась. Похоже, что скорость, которую я сейчас набираю, — это лучшее, на что я могу надеяться, спасибо.