Агрегирование полигонов для удовлетворения требований конфиденциальности

10

У меня есть класс точечных объектов, представляющий офисы всех работодателей в определенной отрасли. Класс пространственных объектов имеет атрибут для хранения количества сотрудников, работающих в каждом офисе. Кто-то попросил использовать эти данные, пространственно объединенные с наименьшей возможной географической единицей - в данном случае - блоки переписи. Тем не менее, соглашение о конфиденциальности предотвращает выпуск данных как есть. Вместо этого оно должно быть подавлено, чтобы соответствовать двум критериям:

  1. Любой полигон должен содержать не менее 3 работодателей (баллов);
  2. Не более 80% от общей занятости в пределах многоугольника может быть у одного работодателя.

Я успешно написал сценарий, который пространственно объединяет пункты с блоками переписи, сохраняя сумму и максимальную занятость в каждом. Каждый, который не соответствует критериям подавления, помечается. (Полигоны, не содержащие точек, не помечаются, поскольку нет данных для подавления.) Затем я проверяю каждую группу блоков, чтобы увидеть, содержатся ли в ней какие-либо помеченные блоки. Группы блоков, содержащие только не отмеченные блоки, затем заменяются блоками. Полученный класс пространственных объектов затем проверяется на соответствие критериям подавления, чтобы проверить, адекватно ли подавили данные группы блоков.

Тот же процесс повторяется для трактов, и у меня остается набор данных, состоящий из трактов (некоторые помечены, а некоторые нет), групп блоков и блоков (все не помечены). Однако следующим шагом в географической иерархии является округ, который бесполезен для лица, запрашивающего эти данные.

Мой вопрос, таким образом, заключается в следующем: существуют ли общепринятые методы объединения полигонов в максимально возможное количество групп, чтобы все они соответствовали некоторым минимальным критериям?

Вот некоторые правила, которые я хотел бы применить к агрегации:

  • Когда это возможно, помеченные трактаты следует объединять только с другими помеченными трактатами;
  • Для помеченных Трактов, которые не соприкасаются с какими-либо другими (или изолированными группами, которые все еще не соответствуют критериям), они могут быть объединены с Трактами, которые уже соответствуют критериям, хотя могут быть Тракты без работодателей между ними, которые также будут должны быть включены.
  • Я хотел бы сохранить границы округов нетронутыми, за исключением случаев, когда это абсолютно невозможно (и я предполагаю сделать это путем разделения входных объектов на соответствующие округа перед их обработкой).
  • Решение должно быть на языке Python с использованием инструментов ArcGIS или библиотек Python с открытым исходным кодом.

В идеале, кто-то может указать мне на существующие средства реализации этой агрегации. Если нет, то я с удовольствием сам кодирую алгоритм, хотя список конкретных шагов / инструментов будет высоко ценится. Эта проблема поражает меня как особый случай перераспределения (с несмежными полигонами), и с этой целью я изучил использование алгоритмов регионализации PySAL , хотя мне не ясно, как проверить максимальный процент работодателя от общего числа сотрудников, используя эти ,

nmpeterson
источник

Ответы:

5

Для всех, кто интересуется, я придумал решение самостоятельно, используя алгоритм PySAL region.Maxp . По сути, Max-p позволяет мне генерировать набор регионов, который соответствует моему первому критерию (минимальное количество работодателей на регион), и я помещаю это в цикл while, который отклонит любое из решений Max-p, которое не удовлетворять второму критерию (процент занятости, вносимый крупнейшим работодателем в регионе). Я реализовал это как инструмент ArcGIS.

Я решил отказаться от работы, которую проделал ранее, чтобы пометить блоки / группы блоков / тракты и вместо этого запустить Max-p для блоков (хотя я проводил все свои тесты на трактах, поскольку скромное увеличение числа входных полигонов драматическое влияние на время обработки). Соответствующая часть моего кода выглядит следующим образом. «Шейп-файл», требуемый в качестве входных данных для generate_regions()функции (передаваемый в виде строки, содержащей полный путь шейп-файла), - это файл, в котором точечные объекты работодателей уже пространственно присоединены к нему, с количеством работодателей, максимальных сотрудников из одного работодателя. и общее количество сотрудников, сохраненных в качестве атрибута для каждой входной функции.

import arcpy, math, pysal, random
import numpy as np

# Suppression criteria:
MIN_EMP_CT = 3      # Minimum number of employers per polygon feature
MAX_EMP_FRAC = 0.8  # Maximum ratio of employees working for a single employer per polygon feature

def generate_regions(shapefile, min_emp_ct=MIN_EMP_CT, max_emp_frac=MAX_EMP_FRAC):
    '''Use pysal's region.Maxp method to generate regions that meet suppression criteria.'''
    w = pysal.rook_from_shapefile(shapefile, idVariable='GEOID10')
    dbf = pysal.open(shapefile[:-4] + '.dbf')
    ids = np.array((dbf.by_col['GEOID10']))
    vars = np.array((dbf.by_col[employer_count_fieldname],dbf.by_col[max_employees_fieldname],dbf.by_col[total_employees_fieldname]))
    employers = vars[0]
    vars = vars.transpose()
    vars_dict = {}
    for i in range(len(ids)):
        vars_dict[ids[i]] = [int(vars[i][0]),float(vars[i][1]),float(vars[i][2])]
    random.seed(100)     # Using non-random seeds ensures repeatability of results
    np.random.seed(100)  # Using non-random seeds ensures repeatability of results
    bump_iter = int(arcpy.GetParameterAsText(3)) # Number of failed iterations after which to increment the minimum number of employers per region (otherwise we could be stuck in the loop literally forever).
    iteration = 0
    tests_failed = 1
    while tests_failed:
        floor = int(min_emp_ct + math.floor(iteration / bump_iter))
        solution = pysal.region.Maxp(w,vars,floor,employers)
        regions_failed = 0
        for region in solution.regions:
            SUM_emp10sum = 0
            MAX_emp10max = 0
            for geo in region:
                emp10max = vars_dict[geo][1]
                emp10sum = vars_dict[geo][2]
                SUM_emp10sum += emp10sum
                MAX_emp10max = max(MAX_emp10max, emp10max)
            if SUM_emp10sum > 0:
                ratio = MAX_emp10max / SUM_emp10sum
            else:
                ratio = 1
            if ratio >= max_emp_frac:
                regions_failed += 1
        iteration += 1
        if regions_failed == 0:
            arcpy.AddMessage('Iteration ' + str(iteration) + ' (MIN_EMP_CT = ' + str(floor) +') - PASSED!')
            tests_failed = 0
        else:
            arcpy.AddMessage('Iteration ' + str(iteration) + ' (MIN_EMP_CT = ' + str(floor) +') - failed...')
    return solution

solution = generate_regions(spatially_joined_shapefile)

regions = solution.regions

### Write input-to-region conversion table to a CSV file.
csv = open(conversion_table,'w')
csv.write('"GEOID10","REGION_ID"\n')
for i in range(len(regions)):
    for geo in regions[i]:
        csv.write('"' + geo + '","' + str(i+1) + '"\n')
csv.close()
nmpeterson
источник
2

Я никогда не сталкивался с подобной ситуацией, и я полагаю, что более распространенный путь заключается в том, чтобы фактически сохранить те единицы измерения, которые вы выберете априори, а затем использовать различные методы, чтобы «обмануть» данные, чтобы защитить проблемы конфиденциальности.

Для ознакомления с множеством способов, которыми люди маскируют данные, я бы предложил эту статью;

Мэтьюз, Грегори Дж. И Офер Харел. 2011. Конфиденциальность данных: обзор методов ограничения статистического раскрытия и методов оценки конфиденциальности . Статистические исследования 5 : 1-29. PDF-файл свободно доступен в Project Euclid по вышеуказанной ссылке.

У меня также есть ссылки на другие статьи, в которых обсуждается «геомаскировка» этого тега в моей библиотеке citeulike ( хотя не все они строго связаны с географическими данными).

Хотя это не отвечает на ваш вопрос, возможно, что некоторые из методов, перечисленных в статье Мэтьюз и Офер, могут быть проще реализовать в соответствии с вашими потребностями. В частности, создание синтетических данных выглядит как логическое продолжение того, куда вы направлялись (внешние данные были бы заимствованы из окружающей группы блоков переписи или участка или округа, если это необходимо). Также некоторые типы обмена данными (в пространстве) также могут быть проще в реализации.

Энди У
источник
Спасибо за ответ / комментарий. Мне известно о существовании методов, позволяющих обманывать данные, чтобы сохранить статистическую достоверность при защите конфиденциальности, хотя этот документ помог мне немного лучше понять особенности. К сожалению, такие методы не кажутся особенно применимыми к моей ситуации, когда единственная информация, которую я публикую, - это количество работодателей и работников в определенной области: их перетасовка неизбежно повлияет на достоверность любого анализа, основанного на них, не так ли?
nmpeterson
Агрегация влияет на анализ потенциально аналогичным образом. Хотя сложно дать общий совет, и ваш конечный продукт должен руководствоваться тем, что люди впоследствии будут делать с данными. Я могу представить некоторые ситуации, когда создание конечных единиц переменных агрегации было бы проблематичным. Например, если бы мне было интересно сравнивать агломерацию / конкуренцию между работодателями, разные подразделения были бы проблемой, но, особенно, если я хочу продолжить и связать их с другими демографическими данными из переписи.
Энди У
В этом случае я предпочел бы иметь одну единицу анализа, в которую включено произвольное количество ошибок, но я уверен, что вы можете подумать о других применениях, где агрегирование и (теоретически) отсутствие ошибок было бы предпочтительным.
Энди У