20-5-第七章 用于地理处理的基本Python模块和包 (5)

原书链接

7.7 Working with Excel files using openpyxl

EXCEL电子表格是一种广泛使用的数据处理格式,excel中不仅存储表格数据还可以存储图像、公式等,并且可以包含空行、空列等,这在数据库表中是不被支持的。

有几个模块支持再python中使用excel文件,arcgis pro自带的openpyxl不是python标准库的内容,xlrd包也可以处理而excel文档,或者使用Pandas去处理。

典型的Excel 文件与纯文本或CSV格式的表格数据有点不同。首先,Excel 可以包含多个工作表,每个工作表代表一个单独的表。除了打开Excel ,还必须指向特定的sheet工作表。其次,Excel工作表中的数据以单元格形式输入,单元格按行和列组织。
必须引用特定的单元格,然后获取其值,openpyxl模块具有用于这些任务的函数和类。

使用openpyxl打开一个EXCEL,可以使用openpyxl.load_wordbook()函数,如下所示:

import openpyxl
book = openpyxl.load_workbook("C:/Data/Example.xlsx")

这个函数返回一个wordbook对象。接下来,可以使用workbook对象的方法获取Excel 中的工作表。您可以使用sheetnames属性获取所有工作表的列表:

sheets = book.sheetnames

可以添加索引获取特定的工作表:

sheet = book.worksheets[0]

引用某个表中的行和列来处理单元格并且获取值。首先引用单元格,之后才能获取值:

b3 = sheet["B3"]
print(b3.value)

第一个代码返回一个Cell对象,并且value属性返回了这个单元格的值。一个可以替代的方式是获取特定行列位置的值:

b3 = sheet.cell(column=2, row=3)
print(b3.value)

这里的第一行第一列是从1开始的,并不是0。这里的2和3也不是索引,只是行和列关键词的参数。

一个更典型的场景是读取所有的单元格,而不是特定的单元格。可以通过使用iter_cols()方法迭代列或者iter_rows()方法来迭代行读取所有的单元格。以下示例使用iter_cols()读取工作表中的所有的单元格:

for col in sheet.iter_cols():
    for cell in col:
        print(cell.value)

使用iter_rows()方法遍历行的工作原理如下:

for row in sheet.iter_rows():
    for cell in row:
        print(cell.value)

遍历所有的行或者列都可以打印所有的值,但是一般选择逐行读取的方式。默认情况下,iter_cols()iter_rows()方法将继续,直到分别没有剩余的列或行具有有效的单元格值。当有空列时,这个方法不会停止读取,而是继续读取行和列,直到没有剩余的单元格值为止。

使用iter_cols()iter_rows()的另一种方法是从列或行的起始值(数字1)开始迭代,直到读取具有有效单元格值的最大列或行数,是使用工作表的maxcolmaxrow 可以获得的最大值。

由于单元格值可以为空,因此可能需要检查单元格是否包含值,用于检查单元格是否包含值的代码为:

if cell.value != None:

代码可以被简写为:

if cell.value:

前面用于处理CSV 的相同脚本如下所示,用于处理Excel 。作为提醒,脚本从文件读取坐标以创建点特征,该文件的Excel版本显示在图中:
在这里插入图片描述
使用openpyxl模块处理.xlsx格式Excel 的脚本如下:

import arcpy
import openpyxl
fgdb = "C:/Data/Demo.gdb"
infile = "C:/Data/points.xlsx"
fc = "points"
sr = arcpy.SpatialReference(26910)
arcpy.env.workspace = fgdb
arcpy.CreateFeatureclass_management(fgdb, fc, "Point", "", "", "", sr)
with arcpy.da.InsertCursor(fc, ["SHAPE@"]) as cursor:#使用插入游标
    point = arcpy.Point()
    book = openpyxl.load_workbook(infile)#打开excel文件
    sheet = book.worksheets[0]#打开特定sheet
    for i in range (1, sheet.max_row):
        point.ID = sheet.cell(row = i, column = 1).value
        point.X = sheet.cell(row = i, column = 2).value
        point.Y = sheet.cell(row = i, column = 3).value
        cursor.insertRow([point])

在此脚本解决方案中,load_workbook()函数打开Excel 。通过使用workbook[0]选择感兴趣的工作表,该工作表选择第一个工作表。接下来,脚本从第1行迭代工作表的行,直到没有剩余的行(max_row)。另一种迭代是使用sheet.iter_rows()。因为总共只有三列,所以在脚本中指定了列号。对于许多列,另一种解决方案是使用For row in sheet.iter_rows():For cell in col:对行和列进行迭代。最后,使用value属性获得单元值,并将这些值分配给Point对象的ID、X和Y属性。

7.8 working with JSON using json

JavaScript Object Notation (JSON) 是一种基于文本的数据格式,用于在应用程序之间共享数据。JSON起源于JavaScript编程语言。然而,JSON已经成为自己的标准,被认为是语言不可知的,这意味着它独立于特定的 编程语言。因此,它在不同平台上的许多不同编程语言中被广泛使用,并成为信息共享的事实标准,使用包括空间数据集。

考虑一个JSON 文件的简单示例,以下示例通过使用name、hobbies、age和children来描述一个人, 每个children也有名字和年龄:

{
    "firstName": "Jennifer",
    "lastName": "Smith",
    "hobbies": ["dancing", "tattoos", "geocaching"],
    "age": 42,
    "children": [
        {
            "firstName": "Mark",
            "age": 7
       },
       {
           "firstName": "Ashley",
           "age": 11
       }
    ]
}

注意,括号的缩进和使用与Python不同,因为它基于JavaScript,示例说明JSON支持数字和字符串等数据类型,以及列表和对象。还要注意,该结构看起来有点像Python字典。JSON构建在两种类型的结构上:(1)名称/值对的集合,以及(2)值的有序列表,这些类型是编程中的通用数据结构,这使得JSON可以与许多编程语言互换。

使用作为标准库一部分的JSON模块可以方便地直接处理JSON对象,这个模块可用于在JSON和Python之间进行转换。Python中的JSON对象是通过将整个对象作为字符串输入来创建的,下面的示例使用这个简化的 JSON:

{
    "name": "Joe",
    "languages": ["Python", "Java"]
}

由于JSON是文本格式的,所以JSON对象被创建为字符串,如下所示:

import json
person = '{"name": "Joe", "languages": ["Python", "Java"]}'

JSON对象可以使用JSON模块的loads()函数转换为Python字典,如下所示:

py_person = json.loads(person)
print(py_person["languages"])

结果如下所示:

['Python', 'Java']

JSON对象也可以存储为扩展名为.JSON 的文本文件。json模块的 load()函数可以读取此文件并将其转换为Python字典。在以下示例中,person.json 文件包含与前面引用的json对象相同的文本,内容如下:

import json
person = open("person.json")
py_person = json.load(person)
print(py_person["languages"])

Python字典可以使用JSON模块的dumps()函数转换为JSON对象,如下所示:

import json
person = {"name": "Joe", "languages": ["Python", "Java"]}
json_person = json.dumps(person)
print(json_person)

结果将整个JSON对象作为一个字符串。
dump()函数可用于将JSON对象写入文件,如下所示:

import json
person = '{"name": "Al", "languages": ["Python", "C"]}'
json_file = open("newperson.json", "w")# open() 函数用于打开一个文件,创建一个 file 对象
json.dump(person, json_file)
json_file.close()

为了提高JSON Ales的可读性,使用漂亮的打印JSON(也称为漂亮的JSON或PJSON)非常有用。例如,前面的示例将JSON对象打印为简单字符串,如下所示:

import json
person = {"name": "Joe", "languages": ["Python", "Java"]}
json_person = json.dumps(person)
print(json_person)

结果是一个字符串:

{"name": "Joe", "languages": ["Python", "Java"]}

格式可以通过使用dumps()函数的附加参数进行修改,包括缩进:

 json_person = json.dumps(person, indent=4)

result是一种更清晰地说明JSON对象组织的格式,如下所示:

 {
    "name": "Joe",
    "languages": [
        "Python",
        "Java"
    ]
}

通过添加参数sort_keys=True,可以完成其他排序。PJSON的使用对实际数据没有影响,当保存到文件时,文件扩展名是相同的。

JSON被广泛用于共享数据,并已成为地理空间社区中的流行格式。作为这种广泛接受的一个例子,ArcGIS Pro有标准工具可以转换为JSON 和JSON 转出为其他的,即Features to JSON和JSON to Features。JSON也用于使用ArcGIS REST API创建的服务。此外,GeoJSON格式已被开发为文件格式,以将地理数据表示为JSON。这两种格式都被广泛使用,许多应用程序可以使用这两种形式,JSON的文件扩展名为.JSON,而GeoJSON的文件扩展名为.GeoJSON。

以下是在Python脚本中处理JSON对象的几种方法。首先,当从在线资源下载数据时,JSON被广泛用作替代文件格式,例如,使用urllibrequests。其次,您可以使用ArcGIS Pro 中的标准工具(如Features to JSON)将现有空间数据转换为JSON .第三,可以直接在脚本中处理JSON对象,例如,使用arcpy.da模块的cursor或在脚本本身中创建JSON对象(如前面的示例所示)。
还有几个例子说明了其中的一些场景。
前面的JSON 文件示例不包含地理数据,因此继续使用一个包含地理数据的示例很有帮助。考虑具有单个多边形要素和少量属性的地块要素类。
在这里插入图片描述
将此多边形特性转换为JSON时,空间数据仅表示为文本,可以使用简单的文本编辑器查看。JSON 文件的第一部分包括关于属性表(FID和PARCEL_ID)中 的信息 、几何类型(esriGeometryPolygon)和空间参考(factory code 2277)。请注意,不包括Shape field,因为这些信息是通过几何类型、坐标系和实际坐标获取的。
在这里插入图片描述
JSON文件的第二部分包含有关特性的信息,在本例中,仅包含一个多边形,是由两个属性字段的值以及顶点的坐标组成的信息,共有5个顶点,但第一个和最后一个顶点具有相同的坐标值,并且重合 “rings”引用表示JSON支持使用外部和内部环来表示带有孔的多边形,但在本示例中只需要一个环。
在这里插入图片描述
必须详细查看JSON 文件的内容并不常见,但它说明了整个空间数据集(包括坐标系、属性结构、属性值和特征)是如何仅以文本表示的。

此处使用的格式使用PJSON来提高易读性。如果不使用其他格式,则整个JSON文件是一行很长的文本,这很难解释。以下是未格式化的JSON文件的外观说明。

{“displayFieldName”:“”,“AeldAliases”:
{“FID”:“FID”,“PARCEL_ID”:“PARCEL_ID”},“geometryType”:“esriGeometryPolygon”,“spatialReference”:
{“wkid”:102739,“latestWkid”:2277},“Aelds”:
[{“name”:“FID”,“type”:“esriFieldTypeOID”,“alias”:“FID”},
{“name”:“PARCEL_ID”,“type”:“esriFieldTypeString”,“alias”:“PARCEL_ID”,“length”:15}],“features”:[{“attributes”:
{“FID”:0,“PARCEL_ID”:“0206042001”},“geometry”:{“rings”:
[[[3116036.110156253,10071403.570008084],
[3115768.3600355834,10071482.069851086],
[3115847.3598775864,10071747.569976255],
[3116114.2300787568,10071667.570136249],
[3116036.110156253,10071403.570008084]]]}}]}

如本节前面所述,Python的json模块可以在json和Python对象之间进行转换,ArcGIS Pro中的地理处理工具可以在存储为文件的json对象和要素类之间进行转换。此外,ArcPy函数AsShape()可以在JSON对象和ArcPy几何对象之间进行转换。它的功能使得可以使用JSON对象来存储和创建空间数据,而无需将数据保存到文件。arcpy.AsShape()函数的语法如下:

AsShape(geojson_struct.{esri_json})

第一个参数是一个JSON对象,表示为Python字典。第二个参数表示对象是JSON(True)还是GeoJSON(False)对象。以下示例为具有坐标系的单点要素创建JSON对象,并将其转换为ArcPy point对象:

import arcpy
geo = {"x": -124.7548, "y": 46.5783,
        "spatialReference":
    {"wkid": 4326}}
point = arcpy.AsShape(geo, True)

AsShape()函数根据输入的JSON对象返回几何对象。通过使用“x”和“y”创建点。使用“paths”创建多段线,使用“rings”创建多边形。例如,以下示例基于坐标列表创建单个Polyline对象:

 import arcpy
geo = {
    "paths": [
        [[166.4359,19.5043], [166.4699,19.5098],
        [166.5086,19.4887], [166.5097,19.4668],
        [166.4933,19.4504], [166.4617,19.4410]]],
    "spatialReference": {"wkid":4326}}
polyline = arcpy.AsShape(geo, True)

PJSON在最后一个示例中并未完全保留其格式,以减少显示目的的行数。
到目前为止,使用的JSON对象相对简单,因为它们只有一个特性。使用多点特征的JSON对象示例如下:

{"features":[{"geometry":{"x":3116036,"y":10071403}},
             {"geometry":{"x":3115768,"y":10071482}},
             {"geometry":{"x":3115847,"y":10071747}}]}

JSON对象还可以使用load()loads()函数转换为Python字典,将每个点转换为几何对象需要在“features”键上进行迭代。
本节中的示例说明了如何通过将JSON对象写成Python字典来创建几何对象。更复杂的JSON对象可以从文本文件中读取,并使用JSON模块的load()函数转换为Python字典。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值