原書連結
7.7 Working with Excel files using openpyxl
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
可以添加索引擷取特定的工作表:
引用某個表中的行和列來處理單元格并且擷取值。首先引用單元格,之後才能擷取值:
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)開始疊代,直到讀取具有有效單元格值的最大列或行數,是使用工作表的
maxcol
或
maxrow
可以獲得的最大值。
由于單元格值可以為空,是以可能需要檢查單元格是否包含值,用于檢查單元格是否包含值的代碼為:
代碼可以被簡寫為:
前面用于處理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, ["[email protected]"]) 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
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"])
結果如下所示:
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)
結果是一個字元串:
格式可以通過使用dumps()函數的附加參數進行修改,包括縮進:
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被廣泛用作替代檔案格式,例如,使用
urllib
或
requests
。其次,您可以使用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()
函數的文法如下:
第一個參數是一個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字典。