k-匿名,判断输入数据是否符合k-匿名,python,对公司员工信息进行k-匿名

代码:
def k_anonymization(data,k=3):
    # 标识
    logotype = ['员工姓名', '员工编号', '员工性别', '员工年龄', '工资年限', '薪资']
    length_data=len(data)#二维数组长度,后面用来遍历二维数组
    # 获取敏感属性的列索引
    global min_keys, min_count, record#定义三个全局变量
    #sensitive_attrs_index = [1, 3, 4 ,5]#需要泛化的敏感属性,这里多泛化工资
    sensitive_attrs_index = [1, 3, 4] # 需要泛化的敏感属性,这里选择不泛化工资

    # 对敏感属性进行泛化处理
    for record in data:#遍历二维数组的数组
        # 将中文姓名不输出
        record[0] = ''
        # 员工编号泛化后三位
        employee_id = ''.join(filter(str.isdigit, record[1]))
        record[1] = employee_id[:3] + '***'

        # 对年龄、(工资)以及工作时长使用一个区间来进行泛化
        # 使用整除运算符 // 将年龄除以 10 并向下取整,然后再乘以10得到年龄所在的整十位数。然后通过字符串拼接的方式将结果转换为字符串。
        # 计算该年龄段的上界(将年龄除以 10 并向下取整,再加一再乘以 10,减一得到该年龄段的上界),同样将结果转换为字符串。最后通过字符串拼接的方式将两个字符穿拼接成形如 '30-39' 的字符串存储在 age_range 变量中。
        age_range = str(record[3] // 10 * 10) + '-' + str((record[3] // 10 + 1) * 10 - 1)#对于年龄,我们使用每10岁一个区间的方式进行泛化
        work_years_range = str(record[4] // 3 * 3 + 1) + '-' + str((record[4] // 3 + 1) * 3)#对于工作时长,我们使用每3年一个区间的方式进行泛化
        #salary_range = str(int(record[5]) // 3000 * 3000) + '-' + str((int(record[5]) // 3000 + 1) * 3000 - 1)#对于工资,我们则使用每3000元一个区间进行泛化
        record[3] = age_range
        record[4] = work_years_range
        #record[5] = salary_range
        # 对性别进行泛化
        if record[2] != '*':
            record[2] = '*'
    # 按照敏感属性对数据进行排序
    sorted_data = []
    #对data数据进行处理,方便下面对敏感数据进行排序
    for record in data:
        # 将需要按敏感属性排序的部分存储为一个元组
        compare_tuple = tuple(record[i] for i in sensitive_attrs_index)  # 遍历敏感属性下标,在 record 记录中依次取出对应下标的各个属性值,并将这些属性值放在compare_tuple中
        # 加入到待排序列表中
        sorted_data.append((compare_tuple, record))  # 将这两个列表的数据,compare_tuple所匹配的record都插入进去

    sorted_data.sort(key=lambda x: x[0])#使用第零列敏感数据,对数组进行排列
    # 去掉待排序列表中的元组,只保留排序后的记录列表
    sorted_data = [record for _, record in sorted_data]
    # print(sorted_data)
    # 将数据分成若干组,三条记录依次分为一组
    groups = []
    for i in range(0, len(sorted_data), k):#从0开始,到sorted_data的长度结束,每次增加k值
        group = sorted_data[i:i + k]#三条记录为一组
        groups.append(group)
    values_count = {}
    # 对每个组进行处理
    for group in groups:
        # 统计每个属性值的出现次数
        #print(group)
        for record in group:#遍历每个组里面的值
            for attr_index in sensitive_attrs_index:#遍历索引表
                #print('record[attr_index]',record[attr_index])
                if record[attr_index] in values_count:#判断索引表中对应的数据是否在values_count中
                    values_count[record[attr_index]] += 1#在,则将对应的数据(即键)的值加一,即出现次数加一
                else:
                    values_count[record[attr_index]] = 1#不在,将该数据加入values_count,做为键,并将其对应的值置一,即出现次数设置为一
        # 找到出现次数最小的敏感属性值
        min_count = min(values_count.values())#找出字典values_count中,最小的值,即出现次数最小
        min_keys = []
        for w, v in values_count.items():
            if v == min_count:
                min_keys.append(w)
        # 创建一个空的 min_number 列表,用于记录最小值所在的列数
    min_number = []
    for m in min_keys:  # 遍历最小值
        print('出现次数最小的值:', m)
        for i in range(length_data):
            for j in range(5):#只遍历0到4列,要遍历工资,改为6即可
                if m in data[i][j]:  # 遍历 record 数组
                    print('最小值在输入数据第几列:', j)
                    min_number.append(j)
    Quasi_identifiers=[]#存储不合k匿名的准标识符
    min_numbers=list(set(min_number))#去掉重复数据
    min_numbers.sort(key=min_number.index)#改回原来的数据顺序
    for a in min_numbers:
        Quasi_identifiers.append(logotype[a])

    print('出现次数最小的值:',min_keys)
    print('出现次数最小:',min_count)
        #判断是否符合k匿名
    if(min_count<k):
        print('准标识符的{}的{}不符合{}匿名,只有{}条记录'.format(Quasi_identifiers,min_keys,k,min_count))

    # 将所有分组合并成一张表,并返回
    anonymized_data = []
    for group in groups:
        anonymized_data += group
    return anonymized_data


if __name__ == '__main__':

    # 示范数据
    employee_data = [
        ['张三', '12345', '男', 20, 1, 6000],
        ['李晓', '23455', '女', 47, 3, 7500],
        ['李静妮','12354', '女', 33, 4, 6500],
        ['于洋', '23476',  '女', 27, 4, 8900],
        ['李四', '23456', '男', 25, 2, 7000],
        ['王五', '12367', '女', 30, 3, 8000],
        ['赵六', '45678', '女', 35, 4, 9000],
        ['孙七', '45689', '男', 40, 5, 10000],
        ['周八', '45690', '男', 45, 6, 11000],
        ['吴九', '12301', '女', 50, 7, 12000],
        ['郑十', '23412', '女', 55, 8, 13000],
        ['柯晓阳','12378', '男', 34, 8,12000]
    ]

    # 对员工数据进行 k-匿名化
    anon_employee_data = k_anonymization(employee_data, k=3)#调用函数k_anonymization,这里的k是指使用k-匿名

    # 输出结果
    print("{:<15}{:^10}{:^15}{:^15}{:^10}".format("员工编号", "性别", "年龄",'工作时长', "工资"))
    for record in anon_employee_data:
        salary_range = str(record[5]).replace('****', '0-999')
        work_years_range = str(record[4]).replace('0-', '1-2').replace('3-', '3-5')
        print("{:<15}{:^10}{:^15}{:^15}{:^10}".format(record[1], record[2], record[3],record[4], salary_range))

上面的代码,员工编码可以选择不输出,或者将员工编码统一开头,或者不输出员工年龄或者工作年限,或者可能会被推测出身份

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值