参考文档:https://pythonhosted.org/Python%20Shapefile%20Library/,
https://blog.csdn.net/weixin_40450867/article/details/103800529
读取
import shapefile
fileRead = shapefile.Reader("{路径名}",encoding='utf-8') # 仅仅读取
fileWrite = shapefile.Writer("{路径名}",encoding='utf-8') # 仅仅写入
为写入shp创建新的字段
# 参数:字段名,字段类型,该字段的大小限制
# 字段类型可以为 Character, Numbers, Longs, Dates, or Memo.
# Memo是文档类型,似乎没什么用
fileWrite.field('Value_Type_Max','C','20')
fileWrite.field('Positive_or_Negative','N')
获取shp文件的字段值和地理要素
获取字段名
# 输出结果不仅包括了字段名,还包括了字段的类型和大小限制
fields = list(fileRead.fields)
获取shp内全部属性要素
shapeRecords=fileRead.shapeRecords() # 获取全部要素
# 对某个要素根据字段名单独取值
shapeRecords[0].record.字段名 # 这里的字段名就是你的shp文件里面的字段名
获取地理要素
shapes=fileRead.shapes()
dir(shapes[0])# shape拥有的属性
# 'bbox',
# 'parts',
# 'points',
# 'shapeType',
# 'shapeTypeName'
获取每一行的字典
# 循环的时候做下标的i
i = 10
# 定义字典和record
attr_dic = {}
record = shapeRecords[i].record
# 执行for循环
## 注意这里fields的下标是j+1
for j in range(len(fields)-1):
attr_dic[fields[j+1][0]] = record[j]
为什么fields的下标是j+1呢?因为我通过实验发现fields在最开始的位置会多出来一个字段,和shp文件中的略有出入。
以下是fields的前三个字段
以下是用QGIS打开shp文件的前三个字段
因此要跳过fields的第一个字段
属性值转换成dataframe
import pandas as pd
attr_dic_list = []
# 循环的时候做下标的i
for i in range(len(shapeRecords)):
# 定义字典和record
attr_dic = {}
record = shapeRecords[i].record
# 执行for循环
## 注意这里fields的下标是j+1
for j in range(len(fields)-1):
attr_dic[fields[j+1][0]] = record[j]
attr_dic_list.append(attr_dic)
pd.DataFrame(attr_dic_list)
shp文件的写入
写入有两个步骤,首先写入形状,接着写入属性。
写入形状要素
根据要素的类型不同,使用的函数也不一样
- 点要素
fileWrite.point
- 线要素
fileWrite.line
- 面要素
fileWrite.poly
具体可以看源码
写入属性
直接按照属性的顺序,放一个列表进去即可。(这块儿感觉讲的不清楚,可以看下面的示例代码)
fileWrite.record(*list(shapeRecords[i].record))
写入代码示例
接下来以copy一个shp文件+添加一列数据(不带投影,因为我还没搞懂咋弄)为例。原来的shp文件是面要素。
import shapefile
fileRead = shapefile.Reader("原始.shp",encoding='utf-8') # 新建数据存放位置
fileWrite = shapefile.Writer("输出.shp",encoding='utf-8') # 新建数据存放位置
# 获取原始shp的基本信息
fields = fileRead.fields
shapeRecords=fileRead.shapeRecords()
shapes=fileRead.shapes()
# 执行copy
## 首先定义fileWrite的属性字段
fileWrite.fields = list(fileRead.fields)
## 为原来的shp文件增加一列
fileWrite.field('Value_Type_Max','C','20')
## 接下来遍历原始shp的基本信息,同时写入fileWrite
for i in range(len(shapes)):
# 第一步:塞入形状
## 这个形状指的就是那些点的集合
## 由于源码中要求的输入是列表,因此就算只塞入一个,也要套一个列表
fileWrite.poly([shapes[i].points])
# 第二步:塞入属性值
fileWrite.record(*list(shapeRecords[i].record),'字符串')
# 保存结束
fileWrite.close()