Python + GIS eGeopandas?

나는 최근에 "붉은 저택의 꿈"을 읽었고 Ning Rong의 두 번째 집은 첩 Yuan이 명령하여 Qingxu Temple에 가서 싸우라는 명령을 읽었습니다. Qingxu View에서 Zhang 판사는 Baoyu에게 키스를 하려고 하지만 마음에 Daiyu만 있는 Baoyu는 자연스럽게 역겹습니다. 둘째 날 바오위는 장도교의 말에 몹시 기분이 나빴고, 다이위의 열사병 때문에 우울했다. 이 때문에 특별히 다이유를 보기 위해 샤오샹 정자에 갔는데, 원래 의도가 좋은 방문인지는 몰랐는데 다이유의 편집증과 소심한 성격 탓에 둘 사이에 오해가 생겼다. 지금까지 대관원 소상정에 있는 두 사람은 울고 말썽을 피우며 마더 자까지 놀라게 했다. 같은 방에 있어도 한 마음으로 사랑에 빠진 두 사람은 얼굴을 가리고 울고, 또 한 사람은 하늘을 향해 한숨을 내쉬는 모습이 정말 보기 안타까웠다.

어떤 어린 소년과 소녀가 사랑에 빠졌고 그런 관계에서 서로 경쟁하지 않았다는 것은 놀라운 일이 아닙니다!

그것이 말했듯이 :

찡그린 눈썹 사이의 감정적 생각,

Ran Ran의 모습이 불쌍합니다.


오래전부터 저는 파이썬이 약형 언어로서 쓰기가 매우 어색하고 작성 방식이 항상 이상하다고 느꼈습니다. Java 또는 Golang의 선입견에 영향을 받았습니다. 나는 정말로 Python에 빠져들고 싶지 않다. 나는 문법이 느리고 "정통"이 아니라고 느낀다. 비록 그것이 매우 강력하고 문제를 날카롭게 해결하지만, 여전히 이것이 배울 가치가 있는 프로그래밍 언어가 아니라는 것을 느끼게 한다.

몇 줄의 코드로 문제를 해결하는 게시물을 읽기 전까지는 파이썬에 대한 제 생각이 갑자기 바뀌는 것처럼 보였습니다.

사실 도구로서 언어의 장단점은 없고 정적 언어든 동적 언어이든 모두 컴파일러의 어깨에 얹혀 있고 비즈니스 문제를 해결하기 위해 약간의 작업을 수행합니다. 고급 언어로서 Python의 간결한 구문과 강력한 타사 라이브러리가 가장 큰 장점이며 문제 해결에 편리함을 제공할 수만 있다면 좋은 도구입니다.

geopandas강력한 라이브러리 , 오늘 함께 배워봅시다 .

많은 타사 라이브러리 제한 서버를 설치하기 위해 pip를 사용하는 것이 외국에 있기 때문에 다운로드 속도가 매우 느립니다.

따라서 다운로드 속도를 높이기 위해 글로벌 pip 이미지 다운로드 소스를 구성할 수 있습니다.단계는 다음과 같습니다.

1. Python을 사용한 구성 단계:

  • 파일 관리자 열기 를 사용 win+E하여 주소 표시줄에 입력하십시오 %appdata%.
  • 이 디렉토리에 새 pip폴더 를 만드십시오.
  • pip文件夹下,新建pip.ini文件;
  • pip.ini文件内,输入以下内容:

[global]

timeout=6000 index-url = mirrors.aliyun.com/pypi/simple

trusted-host = mirrors.aliyun.com

至此,我们可以流畅的使用pip安装任何第三方库了。

2. 使用Anaconda的配置步骤:

  • 进入Anaconda安装目录的Scripts目录;
  • 右键启动cmd命令行窗口,输入以下命令,并回车;

conda config --add channels mirrors.tuna.tsinghua.edu.cn/anaconda/pk… conda config --add channels mirrors.tuna.tsinghua.edu.cn/anaconda/pk… conda config --add channels mirrors.tuna.tsinghua.edu.cn/anaconda/cl… #设置搜索时显示通道地址 conda config --set show_channel_urls yes

3. 查看配置结果;

conda config --show channels

About GeoPandas

GeoPandas is an open source project to make working with geospatial data in python easier. GeoPandas extends the datatypes used by pandas to allow spatial operations on geometric types. Geometric operations are performed by shapely. Geopandas further depends on fiona for file access and matplotlib for plotting.

geopandas包详情:

顾名思义,GeoPandas 通过添加对地理空间数据的支持来扩展流行的数据科学库 pandas。

GeoPandas 中的核心数据结构是 geopandas.GeoDataFrame,它是pandas.DataFrame 的子类,可以存储几何列并执行空间操作。 geopandas.GeoSeriespandas.Series 的子类,用于处理几何图形。因此,您的 GeoDataFramepandas.Series 与传统数据(数字、布尔值、文本等)和 geopandas.GeoSeries 与几何(点、多边形等)的组合。

Install

如果你使用Anaconda,那么键入以下命令即可:

conda install geopandas
复制代码

如果你是使用Python,那么首先去下面的网站下载对应的依赖,因为pip不会帮助我们自己安装依赖。

www.lfd.uci.edu/~gohlke/pyt…

依赖包根据自己的python版本和OS选择合适的即可,包括

Fiona
pyproj
rtrre
shapely
GDAL
复制代码

实际按照上面的顺序安装会报错,因此实际的安装顺序如下:

GDAL->Fiona->pyproj->shapely->rtree
复制代码

安装命令为,以GDAL为例,其它亦然:

pip install GDAL-3.4.2-cp37-cp37m-win_amd64.whl
复制代码

验证一下是否安装成功:

Example

注:以下代码均可单独运行,并输出结果至控制台


geopandas.GeoSeries

构造POINT

from shapely.geometry import Point
from geopandas import geopandas

s = geopandas.GeoSeries([Point(1, 1), Point(2, 2), Point(3, 3)])
print(s)
复制代码

构造具有坐标系的POINT

from shapely.geometry import Point
from geopandas import geopandas

s = geopandas.GeoSeries(
    [Point(1, 1), Point(2, 2), Point(3, 3)], crs="EPSG:3857")
复制代码

geopandas.GeoSeries.area

1. 构造地理集合,并量算面积

from shapely.geometry import Polygon, LineString, Point
s = geopandas.GeoSeries(
    [
        Polygon([(0, 0), (1, 1), (0, 1)]),
        Polygon([(10, 0), (10, 5), (0, 0)]),
        Polygon([(0, 0), (2, 2), (2, 0)]),
        LineString([(0, 0), (1, 1), (0, 1)]),
        Point(0, 1)
    ]
)
area = s.area
print(area)
复制代码

geopandas.GeoSeries.boundary

构造地理集合,并返回低维对象(抽稀)

from shapely.geometry import Polygon, LineString, Point

from geopandas import geopandas
s = geopandas.GeoSeries(
    [
        Polygon([(108.923166,35.363084), (109.322899,35.274691), (109.355755,35.283365),(108.936301,35.380966),(108.923166,35.363084)]),
        LineString([(0, 0), (1, 1), (1, 0)]),
        Point(0, 0),
    ]
)
boundary = s.boundary
print(boundary)
复制代码

geopandas.GeoSeries.x

获取地理对象的X值

from shapely.geometry import Point
from geopandas import geopandas

s = geopandas.GeoSeries([Point(1, 1), Point(2, 2), Point(3, 3)])
s.x
print(s.x)
复制代码

geopandas.GeoSeries.within

返回两个几何图形是否包含,值为bool

from shapely.geometry import Polygon, LineString, Point
from geopandas import geopandas

s1 = geopandas.GeoSeries(
    [
        Polygon([(0, 0), (2, 2), (0, 2)]),
        Polygon([(0, 0), (1, 2), (0, 2)]),
        LineString([(0, 0), (0, 2)]),
        Point(0, 1),
    ],
)
s2 = geopandas.GeoSeries(
    [
        Polygon([(0, 0), (1, 1), (0, 1)]),
        LineString([(0, 0), (0, 2)]),
        LineString([(0, 0), (0, 1)]),
        Point(0, 1),
    ],
    index=range(1, 5),
)

polygon = Polygon([(0, 0), (2, 2), (0, 2)])
within = s1.within(polygon)

print(within)

print(s1.within(s2))

print(s1.within(polygon))
复制代码

geopandas.GeoSeries.to_json

地理集合转json

from shapely.geometry import Point
s = geopandas.GeoSeries([Point(1, 1), Point(2, 2), Point(3, 3)])
s.to_json()
复制代码

geopandas.GeoDataFrame.set_crs

GeoDataFrame设置CRS

import os
import sys
import pyproj
from shapely.geometry import Point
from geopandas import geopandas

# os.environ['PROJ_LIB'] = os.path.dirname(sys.argv[0])
# os.environ['PROJ_LIB'] = "D:\ProgramData\Anaconda3\Library\share\proj\"

d = {'col1': ['name1', 'name2'], 'geometry': [Point(1, 2), Point(2, 1)]}
gdf = geopandas.GeoDataFrame(d)
print(gdf.crs)
gdf = gdf.set_crs('epsg:4490')
print(gdf.crs)
复制代码

geopandas.read_file

读取矢量文件

from geopandas import geopandas
from geopandas.geodataframe import GeoDataFrame

df = geopandas.GeoDataFrame.from_file("W:\desktop\葛瑶\毕业论文\GIS\shp\城六区遗址公园面状.shp")

head = df.head(6)
print(head)
复制代码

Missing and empty geometries

缺省和空值

from shapely.geometry import Polygon

from geopandas import geopandas

s = geopandas.GeoSeries([Polygon([(0, 0), (1, 1), (0, 1)]), None, Polygon([])])

print(s.area)
print(s.union(Polygon([(0, 0), (0, 1), (1, 1), (1, 0)])))
print(s.intersection(Polygon([(0, 0), (0, 1), (1, 1), (1, 0)])))
复制代码

1. Creating a GeoDataFrame from a DataFrame with coordinates

import pandas as pd
import geopandas
import matplotlib.pyplot as plt

df = pd.DataFrame(
    {'City': ['Buenos Aires', 'Brasilia', 'Santiago', 'Bogota', 'Caracas'],
     'Country': ['Argentina', 'Brazil', 'Chile', 'Colombia', 'Venezuela'],
     'Latitude': [-34.58, -15.78, -33.45, 4.60, 10.48],
     'Longitude': [-58.66, -47.91, -70.66, -74.08, -66.86]})

gdf = geopandas.GeoDataFrame(
    df, geometry=geopandas.points_from_xy(df.Longitude, df.Latitude))

print(gdf.head())

world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))

# We restrict to South America.
ax = world[world.continent == 'South America'].plot(
    color='white', edgecolor='black')

# We can now plot our ``GeoDataFrame``.
gdf.plot(ax=ax, color='red')

plt.show()
复制代码

运行结果如下:

2. create a Isodensity map

import pandas as pd
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import geopandas as gpd
from shapely.geometry import Point, geo  # 经纬度转换为点
import adjustText as aT
import mapclassify
import warnings

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

map_name = "西安市区域专题图"

warnings.filterwarnings('ignore')
# 读取数据为geodataframe格式
geo_ = gpd.GeoDataFrame.from_file('W:\Google_Download\西安市.json', encoding='utf-8')
print(geo_)
geo_.head(3)
df = pd.read_csv(r'C:\Users\王斌\Desktop\POI.csv', encoding='utf-8')

df['geometry'] = list(zip(df['wgs84_lon'], df['wgs84_lat']))  # 经纬度组合为新列geometry,与形状里的该列对应
df['geometry'] = df['geometry'].apply(Point)  # 经纬度转化为坐标点
gpd_df = gpd.GeoDataFrame(df)

base = geo_.plot(color='lightblue', edgecolor='grey', figsize=(15, 15))  # 利用形状信息画底图
gpd_df.plot(ax=base, color='red', marker="o", markersize=50, alpha=0.01)  # 在底图上添加出租房位置
plt.gca().xaxis.set_major_locator(plt.NullLocator())  # 去掉x轴刻度
plt.gca().yaxis.set_major_locator(plt.NullLocator())  # 去掉y轴刻度

geo_.plot(figsize=(8, 6),  # 图像大小
          column='name',  # 分级设色字段
          # scheme='quantiles',  # MapClassify-分级类型
          legend=True,  # 图例
          cmap='Pastel1_r',  # 渐变色带的名称#Set2
          edgecolor='k')  # 边框颜色
# 图名
plt.Artist

plt.title('{}'.format(map_name), fontsize=18, fontweight='bold')

# 显示网格,透明度为50%
plt.grid(True, alpha=0.5)

plt.show()
#plt.savefig('./image/{}.png'.format(map_name), dpi=300)
复制代码

如下为运行结果,红色斑块为西安市城六区的POI点,为21万余点。

Summary

geopandas的函数较多,这里我选了几个运行和学习,大家有兴趣可以根据自己的需要进行学习。

geopandas作为一个Python与GIS结合的库,根据官网的介绍其提供的功能还是比较丰富的,能够进行较多的地理数据处理,也可以快速绘制一些基础地图,并能够灵活的对地图进行设计。

我感觉可以满足大部分的GIS小场景,但是遇到比较复杂的业务场景或者功能,可能还得借助桌面端的软件来辅助完成。

总体来讲,我感觉在解决一些小的GIS问题上来说还是很锋利的。

值得一学!

Error Summary

这里额外记录一个错误,我排查、上网找资料好久才算解决。

这里记录下来供大家参考!

错误的原因就是使用geopandas读取矢量文件或者绘图时会引发pyproj库的无效投影错误,错误截图如下:

pyproj.ecception.CRSError: Invalid projection:epsg:2263:(Internal Proj Error:···)

这是在Proj官网上给出的一个常见错误排查方案,能提供思路,但是没有解决问题。

Why am I getting the error “Cannot find proj.db”?

The file proj.db must be readable for the library to properly function. Like other resource files, it is located using a set of search paths. In most cases, the following paths are checked in order:

  • A path provided by the environment variable PROJ_LIB.
  • A path built into PROJ as its resource installation directory (typically ../share/proj relative to the PROJ library).
  • The current directory.

Note that if you’re using conda, activating an environment sets PROJ_LIB to a resource directory located in that environment.

最后在根据在网上查看许久发现线索指向Proj.db,该文件可能有问题,因为报错总是提示SQLite error,具体来说是关于初始化查询的一个错误,说明 Proj.db可能是有问题的。

使用如下代码打印出目前pyproj的资源指向路径:

data_dir = pyproj.datadir.get_data_dir()
print(data_dir)
复制代码

在我的笔记本上该路径指向D:\ProgramData\Anaconda3\Lib\site-packages\pyproj\proj_dir\share\proj

经查看该文件下的Proj.db为7.7M左右,但是pyproj官方提示的在Anaconda的安装目录/share/proj下的Proj.db大小为5.36M。

实在想不到解决办法的我,大胆地把D:\ProgramData\Anaconda3\Lib\site-packages\pyproj\proj_dir\share\proj下的Proj.db替换为了Anaconda的安装目录/share/proj下的Proj.db

正所谓:“无心插柳柳成荫”,没想到问题好像解决了。程序可以正确的进行矢量文件读取和制图。

按道理来讲,由Anaconda下载的依赖,其中的依赖关系会被较好的处理,很难出现这样的错误。

我记得我在网上好像看到了Pyproj库是建立在EPSG数据库之上的,这个错误可能是由与版本冲突造成的吧。

希望后面可以搞清楚原因。

知道其中缘由的同学,一定要私信我哈~

추천

출처juejin.im/post/7079716000232374286