Chia đa giác thành * n * số nhóm có số lượng bằng nhau với ArcPy?


10

Một trong những nhiệm vụ của tôi cho công việc là chia bưu kiện thành các nhóm. Các nhóm này sẽ được sử dụng bởi các đại lý để nói chuyện với chủ sở hữu tài sản. Mục tiêu là làm cho công việc của đại lý trở nên dễ dàng bằng cách nhóm các bưu kiện gần nhau, cũng như chia các bưu kiện thành số lượng bằng nhau để công việc được phân bổ đều. Số lượng đại lý có thể dao động từ một cặp vợ chồng đến 10+.

Hiện tại tôi thực hiện nhiệm vụ này bằng tay, nhưng muốn tự động hóa quy trình nếu có thể. Tôi đã khám phá nhiều công cụ ArcGIS khác nhau, nhưng dường như không có công cụ nào phù hợp với nhu cầu của tôi. Tôi đã thử một tập lệnh (bằng python) sử dụng near_analysisvà chọn đa giác, nhưng nó khá ngẫu nhiên và mất nhiều thời gian để hoàn thành một kết quả bán chính xác, sau đó tôi phải mất nhiều thời gian để sửa hơn so với khi tôi làm mọi thứ thủ công ngay từ đầu.

Có một phương pháp đáng tin cậy để tự động hóa nhiệm vụ này?

Ví dụ kết quả (hy vọng không có sự phân chia mà chúng ta thấy có màu vàng):

Bưu kiện chia


Bạn đã xem xét phân tích vị trí phân bổ? help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/ Kẻ
phloem

Bạn đã thử Phân tích nhóm (Thống kê không gian) chưa?
FelixIP

Tôi cũng đã đăng một mã giả của thủ tục thực tế mà tôi đang sử dụng, xem nó có giúp được gis.stackexchange.com/questions/123289/ không
FelixIP

@crmackey Tôi đánh giá cao liên kết đến câu trả lời của tôi, nhưng tôi không chắc làm thế nào bạn có thể điều chỉnh mã được liên kết (chia đa giác) để phù hợp với vấn đề này (nhóm đa giác).
phloem

Câu trả lời:


4

Bộ gốc:

nhập mô tả hình ảnh ở đây

Tạo giả sao chép (kéo CNTRL trong TOC) của nó và làm cho không gian nối từ một đến nhiều với bản sao. Trong trường hợp này tôi đã sử dụng khoảng cách 500m. Bảng đầu ra:

nhập mô tả hình ảnh ở đây

  1. Xóa các bản ghi khỏi bảng này trong đó PAR_ID = PAR_ID_1 - dễ dàng.

  2. Lặp lại qua bảng và xóa các bản ghi trong đó (PAR_ID, PAR_ID_1) = (PAR_ID_1, PAR_ID) của bất kỳ bản ghi nào phía trên nó. Không dễ dàng như vậy, sử dụng acrpy.

Tính toán trọng tâm lưu vực (UniqID = PAR_ID). Chúng là các nút hoặc mạng. Kết nối chúng bằng các đường bằng cách sử dụng bảng nối không gian. Đây là chủ đề riêng biệt chắc chắn được đề cập ở đâu đó trên diễn đàn này.

nhập mô tả hình ảnh ở đây

Kịch bản dưới đây giả định rằng bảng nút trông như thế: nhập mô tả hình ảnh ở đây

trong đó MUID đến từ bưu kiện, P2013 là lĩnh vực để tóm tắt. Trong trường hợp này = 1 chỉ tính. [rcvnode] - đầu ra tập lệnh để lưu trữ ID nhóm bằng NODEREC của nút đầu tiên trong nhóm / cụm được xác định.

Cấu trúc bảng liên kết với các trường quan trọng được tô sáng

nhập mô tả hình ảnh ở đây

Times lưu trữ trọng lượng liên kết / cạnh, tức là chi phí di chuyển từ nút này sang nút khác. Bằng 1 trong trường hợp này để chi phí đi lại cho tất cả hàng xóm là như nhau. [fi] và [ti] là số nút liên tiếp được kết nối. Để điền vào bảng này, hãy tìm kiếm diễn đàn này về cách gán từ và đến các nút để liên kết.

Script tùy chỉnh cho mxd bàn làm việc của riêng tôi. Phải được sửa đổi, mã hóa cứng với việc đặt tên của các trường và nguồn:

import arcpy, traceback, os, sys,time
import itertools as itt
scriptsPath=os.path.dirname(os.path.realpath(__file__))
os.chdir(scriptsPath)
import COMMON
sys.path.append(r'C:\Users\felix_pertziger\AppData\Roaming\Python\Python27\site-packages')
import networkx as nx
RATIO = int(arcpy.GetParameterAsText(0))

try:
    def showPyMessage():
        arcpy.AddMessage(str(time.ctime()) + " - " + message)
mxd = arcpy.mapping.MapDocument("CURRENT")
theT=COMMON.getTable(mxd)

TÌM KIẾM

theNodesLayer = COMMON.getInfoFromTable(theT,1)
theNodesLayer = COMMON.isLayerExist(mxd,theNodesLayer)

NHẬN LIÊN KẾT

    theLinksLayer = COMMON.getInfoFromTable(theT,9)
    theLinksLayer = COMMON.isLayerExist(mxd,theLinksLayer)
    arcpy.SelectLayerByAttribute_management(theLinksLayer, "CLEAR_SELECTION")        
    linksFromI=COMMON.getInfoFromTable(theT,14)
    linksToI=COMMON.getInfoFromTable(theT,13)
    G=nx.Graph()
    arcpy.AddMessage("Adding links to graph")
    with arcpy.da.SearchCursor(theLinksLayer, (linksFromI,linksToI,"Times")) as cursor:
            for row in cursor:
                (f,t,c)=row
                G.add_edge(f,t,weight=c)
            del row, cursor
    pops=[]
    pops=arcpy.da.TableToNumPyArray(theNodesLayer,("P2013"))
    length0=nx.all_pairs_shortest_path_length(G)
    nNodes=len(pops)
    aBmNodes=[]
    aBig=xrange(nNodes)
    host=[-1]*nNodes
    while True:
            RATIO+=-1
            if RATIO==0:
                    break
            aBig = filter(lambda x: x not in aBmNodes, aBig)
            p=itt.combinations(aBig, 2)
            pMin=1000000
            small=[]
            for a in p:
                    S0,S1=0,0
                    for i in aBig:
                            p=pops[i][0]
                            p0=length0[a[0]][i]
                            p1=length0[a[1]][i]
                            if p0<p1:
                                    S0+=p
                            else:
                                    S1+=p
                    if S0!=0 and S1!=0:
                            sMin=min(S0,S1)                        
                            sMax=max(S0,S1)
                            df=abs(float(sMax)/sMin-RATIO)
                            if df<pMin:
                                    pMin=df
                                    aBest=a[:]
                                    arcpy.AddMessage('%s %i %i' %(aBest,sMax,sMin))
                            if df<0.005:
                                    break
            lSmall,lBig,S0,S1=[],[],0,0
            arcpy.AddMessage ('Ratio %i' %RATIO)
            for i in aBig:
                    p0=length0[aBest[0]][i]
                    p1=length0[aBest[1]][i]
                    if p0<p1:
                            lSmall.append(i)
                            S0+=p0
                    else:
                            lBig.append(i)
                            S1+=p1
            if S0<S1:
                    aBmNodes=lSmall[:]
                    for i in aBmNodes:
                            host[i]=aBest[0]
                    for i in lBig:
                            host[i]=aBest[1]
            else:
                    aBmNodes=lBig[:]
                    for i in aBmNodes:
                            host[i]=aBest[1]
                    for i in lSmall:
                            host[i]=aBest[0]

    with arcpy.da.UpdateCursor(theNodesLayer, "rcvnode") as cursor:
            i=0
            for row in cursor:
                    row[0]=host[i]
                    cursor.updateRow(row)
                    i+=1

            del row, cursor
except:
    message = "\n*** PYTHON ERRORS *** "; showPyMessage()
    message = "Python Traceback Info: " + traceback.format_tb(sys.exc_info()[2])[0]; showPyMessage()
    message = "Python Error Info: " +  str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"; showPyMessage()

Ví dụ đầu ra cho 6 nhóm:

nhập mô tả hình ảnh ở đây

Bạn sẽ cần gói trang web NETWORKX http://networkx.github.io/documentation/development/install.html

Script lấy số cụm yêu cầu làm tham số (6 trong ví dụ trên). Nó đang sử dụng các nút và các bảng liên kết để tạo một biểu đồ có trọng lượng / khoảng cách các cạnh di chuyển bằng nhau (Times = 1). Nó xem xét sự kết hợp của tất cả các nút bằng 2 và tính tổng [P2013] trong hai nhóm lân cận. Khi đạt được tỷ lệ yêu cầu, ví dụ (6-1) / 1 ở lần lặp đầu tiên, tiếp tục với mục tiêu tỷ lệ giảm, tức là 4, v.v. cho đến 1. Điểm bắt đầu có tầm quan trọng rất lớn, vì vậy hãy đảm bảo các nút 'cuối' của bạn nằm ở trên cùng của bảng nút của bạn (sắp xếp?) Xem 3 nhóm đầu tiên trong đầu ra ví dụ. Nó giúp tránh 'cắt cành' ở mỗi lần lặp tiếp theo.

Tùy chỉnh tập lệnh để làm việc từ mxd:

  1. bạn không cần nhập hàng. Đó là điều của riêng tôi, đọc bảng môi trường của riêng tôi, trong đóNodesLayer, theLinksLayer, linksFromI, linksToI đã chỉ định. Thay thế các dòng có liên quan bằng cách đặt tên riêng của các nút và các lớp liên kết.
  2. Lưu ý rằng trường P2013 có thể lưu trữ bất cứ thứ gì, ví dụ như số lượng người thuê hoặc khu vực bưu kiện. Nếu vậy, bạn có thể gom các đa giác để giữ số lượng người bằng nhau, v.v.

Trong các nút thực tế và các lớp liên kết chỉ là những thứ trực quan. Bảng đã dọn sạch của phép nối không gian có thể dễ dàng thay thế bảng liên kết, bởi vì từ và đến các nút đã được gán. Bảng đa giác, có thể dễ dàng đóng vai trò là bảng nút, chỉ cần thêm trường ReceivingNode và chuyển các số liên tiếp từ nó trở lại 'links' [FromI] và [ToI].
FelixIP

Nhìn có vẻ tốt. Cảm ơn rất nhiều cho câu trả lời. Bạn có thể giải thích thêm về lý do tại sao, và không chỉ là làm thế nào? Nhận xét về mã của bạn sẽ rất lớn.
Emil Brundage

Vui lòng theo siêu liên kết trong bình luận trước đó của tôi cho câu hỏi của bạn. Tôi đã cố gắng giải thích cách tiếp cận, nếu đây là "tại sao" nghĩa là gì. Tôi rút lại nhận xét của mình về tầm quan trọng của nút bắt đầu, bởi vì sau khi đăng câu trả lời lên Q của bạn, tôi đã thay đổi ngẫu nhiên thứ tự hồ sơ để cố gắng giết tập lệnh. Không có gì xảy ra nó vẫn tạo ra kết quả hợp lý.
FelixIP

Để dọn sạch bảng tham gia không gian, đủ để xóa PAR_ID = PAR_ID_1, bởi vì cạnh / liên kết [0,2] trong đồ thị vô hướng của NETWORKX cạnh bằng [2,0]. Tôi có thể đăng kịch bản cập nhật, không chắc nó có ảnh hưởng đến danh tiếng của tôi không
FelixIP

@EmilBrundage hãy xem, nó có thể giúp giải thích tại sao câu hỏi gis.stackexchange.com/questions/165057/ trộm
FelixIP

2

Bạn nên sử dụng công cụ "Phân tích nhóm" để đạt được mục tiêu của mình. Công cụ này là một công cụ tuyệt vời từ hộp công cụ "thống kê không gian" như @phloem đã chỉ. Tuy nhiên, bạn nên tinh chỉnh công cụ để thích ứng với dữ liệu và vấn đề của bạn. Tôi đã tạo một kịch bản tương tự như kịch bản bạn đã đăng và nhận được phản hồi gần với mục tiêu của bạn.

Gợi ý: Sử dụng ArcGIS 10.2, khi tôi chạy công cụ, nó đã phàn nàn về gói python bị thiếu, "sáu". Vì vậy, hãy chắc chắn rằng bạn đã cài đặt Liên kết đầu tiên

Các bước:

  1. Thêm một trường cho lớp đa giác của bạn để giữ một giá trị duy nhất
  2. Thêm một trường loại ngắn khác với tên, ví dụ "Samegroup"
  3. bạn tính toán trường để gán 1 cho trường này cho tất cả các hàng. chỉ cần thay đổi một hàng thành 2. Đã thêm trường

  4. Đặt tham số công cụ "Phân tích nhóm" như thế này: Phân tích nhóm

cố gắng thay đổi tham số "Số hàng xóm" cho phù hợp với bạn cần.

Ảnh chụp kết quả:

Đa giác đầu vào mẫu

Kết quả phân tích nhóm


2
Tôi đã xem xét Phân tích nhóm trước. Nó liên quan đến không gian, nhưng không tính xa như tôi có thể nói. Tất cả kinh nghiệm của tôi từ việc đọc tài liệu, xem ví dụ của bạn và thực hiện các bài kiểm tra của riêng tôi không cho phép nhóm theo số lượng đa giác bằng nhau.
Emil Brundage

Tại sao bạn cần phải làm cho bằng nhau (ngoại khóa cho các đại lý)? Nhưng nếu chúng ta thêm ràng buộc đó thì tại sao phải phân cụm (nhóm) dữ liệu dựa trên mối quan hệ không gian!?
Farid Cheraghi

1
Vì sếp nói vậy. Ngoài ra, giảm thiểu thời gian đi lại.
Emil Brundage

1

về cơ bản bạn muốn một phương pháp phân cụm kích thước bằng nhau, vì vậy bạn có thể tìm kiếm với các từ khóa này trên web. Đối với tôi, có một câu trả lời hay về số liệu thống kê. Với việc triển khai Python trong một trong những câu trả lời. Nếu bạn quen thuộc với arcpy, bạn sẽ có thể sử dụng nó với dữ liệu của mình.

Trước tiên, bạn cần tính X và Y của các đa giác của bạn, sau đó bạn có thể nhập các tọa độ này trong tập lệnh và cập nhật bảng thuộc tính của chúng bằng con trỏ .da.


Liên kết mà bạn cung cấp có vẻ như đang đi đúng hướng, nhưng về cơ bản nó là ngôn ngữ mà tôi không hiểu. Đối với tập lệnh, tôi không biết đầu vào là gì và không thể giải mã bất kỳ mã hóa nào để hiểu chính xác điều gì đang xảy ra. Có rất ít lời giải thích.
Emil Brundage

0

Xin chào, tôi đã có một vấn đề tương tự như trước đây, vì vậy tôi đã đưa ra một số vấn đề, chưa bao giờ bắt đầu với một vấn đề khác, nhưng chỉ về phía thoery tôi đã nghĩ

ĐẦU VÀO

Hình dạng đầu vào

tôi đã nghĩ rằng bạn có thể tạo một fishnet trên hình dạng đầu vào

lưới cá fishnet với một giao điểm của hình dạng đầu vào của bạn sau đó sẽ

nhập vào khu vực

Sau đó, bạn có thể tính diện tích của các bưu kiện bên trong đa giác mới được xử lý

Khi bắt đầu tập lệnh của bạn, số lượng đa giác đầu vào diện tích / thứ n của các kích thước bằng nhau muốn

Sau đó, bạn sẽ cần một cách liên quan đến các bưu kiện để họ biết về những người được biên giới.

Sau đó, bạn có thể đi qua một con trỏ hàng tóm tắt các bưu kiện

Quy tắc là

* Nó có chung đường viền vào một mùa hè vừa qua * Nó chưa được tóm tắt * Một khi nó vượt qua giá trị được tính là diện tích bằng nhau, nó sẽ lùi lại và đây sẽ là một nhóm * Quá trình sẽ bắt đầu lại * nhóm cuối cùng có thể tổng số bưu kiện còn lại

Tôi nghĩ rằng việc thiết lập mối quan hệ giữa các bưu kiện có thể là điều khó khăn nhưng một khi điều này được thực hiện tôi nghĩ rằng có thể tự động hóa nó


Tôi sợ tôi không hiểu điều này có liên quan đến vấn đề của tôi. Việc cắt một đa giác bằng lưới cá có liên quan gì đến việc nhóm các đa giác không gian và với số lượng bằng nhau? Bạn có vẻ tập trung vào khu vực, không được tính. Diện tích (kích thước) của đa giác bưu kiện không phải là một yếu tố. Bất kể bưu kiện lớn hay nhỏ, nó vẫn chỉ là một chủ sở hữu tài sản để nói chuyện. Xem ví dụ của tôi trong đó màu đỏ là khu vực nông thôn và trải rộng, trong khi màu cam là đô thị và do đó có tổng diện tích nhỏ hơn nhiều.
Emil Brundage

xin chào bạn, xin lỗi tôi hoàn toàn đọc sai câu hỏi của bạn Tôi nghĩ rằng bài đăng radouxju có thể là cách để đi, nhưng liên kết đi qua đầu tôi một chút. Biến các đa giác thành các điểm có vẻ hợp lý và sau đó nhóm chúng lại. Có thể có một cách giới thiệu hệ thống đường là khoảng cách từ điểm đến đường và điểm tiếp theo có thể xác định yếu tố không gian
Jack Walker


0

Đây là giải pháp của tôi cho các sự kiện điểm. Không đảm bảo nó sẽ luôn hoạt động ...

  1. Trên lớp sự kiện điểm của bạn (gọi layer1), thêm các cột cho x (double), y (double) và uniqueid (số nguyên dài)
  2. Mở bảng thuộc tính cho lớp 1. Tính điểm tọa độ x cho điểm tọa độ x, y cho y và FID cho id duy nhất
  3. Thực thi Công cụ thống kê không gian> Cụm bản đồ> Phân tích nhóm
    • đặt layer1 làm các tính năng đầu vào
    • đặt uniqueid làm ID trường duy nhất
    • Xác định số lượng nhóm (chúng tôi sẽ nói 10)
    • Chọn x và y cho các trường phân tích
    • Chọn "NOinksATIAL_CONSTRAINT" cho các ràng buộc không gian
    • Nhấn vào OK
  4. Thực thi các công cụ thống kê không gian> Đo lường phân phối địa lý> Trung tâm trung bình
    • Chọn đầu ra từ # 3 làm Lớp tính năng đầu vào
    • Chọn SS_group làm Trường hợp trường hợp
    • Nhấn vào OK
  5. Nhà phân tích mạng mở> Công cụ phân bổ vị trí
    • Tải sản lượng số 4 làm cơ sở
    • Tải layer1 làm Điểm cầu
    • Mở thuộc tính và thiết lập
      • Loại vấn đề như tối đa hóa vùng phủ sóng điện dung
      • Các cơ sở để chọn là 10 (từ # 3 ở trên)
      • Dung lượng mặc định là tổng số tính năng trong lớp 1 chia cho các cơ sở để chọn làm tròn (vì vậy nếu 145 tính năng và 10 cơ sở / khu vực, được đặt là 15)
      • Nhấn vào OK
        • Giải quyết
        • Điểm nhu cầu của bạn nên được phân phối ít nhiều bằng nhau thành 10 cụm địa lý

Tôi bị kẹt ở bước năm của phương pháp của bạn. Tôi đã kiểm tra tiện ích mở rộng Phân tích mạng và thêm thanh công cụ Phân tích mạng. Nhưng hầu hết trong số đó có màu xám và tôi không thấy "Công cụ phân bổ vị trí". Tôi đang sử dụng 10.1.
Emil Brundage

0

Trước tiên, bạn cần tạo Bộ dữ liệu mạng bằng cách sử dụng các đường phố của mình. Tôi đã thử phương pháp được đề xuất này và cho đến nay đã có may mắn hơn khi thực hiện điều tương tự với Nhóm (bước 3), sử dụng tọa độ X, Y và phương tiện k cho các trường đầu vào (không hoàn hảo, nhưng nhanh hơn và gần hơn với tôi cần). Tôi mở cho người khác ý kiến ​​và phản hồi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.