在Python中匿名化值列表

在Python中匿名化值列表,python,Python,假设您有一个类似CSV文件的数据集,其中包含轻度敏感的信息,例如谁在12年级的英语课上向谁传递了便条。虽然如果这些数据泄露出去并不是一场危机,但最好去掉识别信息,这样数据就可以公开,与合作者共享,等等。这些数据看起来像这样: from random import shuffle data = [("Anna", "Joe"), ("Anna", "Mark"), ("Mark", "Mindy"), ("Mindy", "Joe")] names = list(set(x for pair i

假设您有一个类似CSV文件的数据集,其中包含轻度敏感的信息,例如谁在12年级的英语课上向谁传递了便条。虽然如果这些数据泄露出去并不是一场危机,但最好去掉识别信息,这样数据就可以公开,与合作者共享,等等。这些数据看起来像这样:

from random import shuffle

data = [("Anna", "Joe"), ("Anna", "Mark"), ("Mark", "Mindy"), ("Mindy", "Joe")]
names = list(set(x for pair in data for x in pair))
shuffle(names)
aliases = dict((k, v) for v, k in enumerate(names))

munged = [(aliases[a], aliases[b]) for a, b in data] 
给予者、接受者:

安娜,乔
安娜,马克
马克,明迪
明迪,乔

您将如何处理此列表,为每个名称分配一个唯一但任意的标识符,然后去掉这些名称,并用Python中的所述标识符替换它们,从而最终得到如下结果:

>>> data
[('Anna', 'Joe'), ('Anna', 'Mark'), ('Mark', 'Mindy'), ('Mindy', 'Joe')]
>>> names
['Mindy', 'Joe', 'Anna', 'Mark']
>>> aliases
{'Mindy': 0, 'Joe': 1, 'Anna': 2, 'Mark': 3}
>>> munged
[(2, 1), (2, 3), (3, 0), (0, 1)]
1,2
1,3
3,4
4,2

您可以使用
hash()
生成唯一的任意标识符,它将始终为特定字符串返回相同的整数:

 with open("data1.txt") as f:
    lis=[x.split(",") for x in f]
    items=[map(lambda y:hash(y.strip()),x) for x in lis]
    for x in items:
        print ",".join(map(str,x))
   ....:         


-1319295970,1155173045
-1319295970,-1963774321
-1963774321,-1499251772
-1499251772,1155173045
或者,您也可以使用:

或者使用itertools的配方改进我之前的答案,您可以得到准确的答案:

In [84]: c=count(1)

In [85]: def unique_everseen(iterable, key=None):
        seen = set()
        seen_add = seen.add
        if key is None:
                for element in ifilterfalse(seen.__contains__, iterable):
                        seen_add(element)
                        yield element
                else:
                        for element in iterable:
                                k = key(element)
                                if k not in seen:
                                        seen_add(k)
                                        yield element
   ....:                         

In [86]: with open("data1.txt") as f:
    lis=[map(str.strip,x.split(",")) for x in f]
    dic={}
    for x in unique_everseen(chain(*lis)):
        dic.setdefault(x.strip(),next(c))
    for x in lis:    
        print ",".join(str(dic[y.strip()]) for y in x)
   ....:         
1,2
1,3
3,4
4,2

您可以使用
hash
为每个名称获取唯一的ID,您可以使用字典将名称映射到它们的值(如果您希望数字与示例中的数字相同):

运行时将给出:

{'Mindy': 4, 'Joe': 2, 'Anna': 1, 'Mark': 3}
[(1, 2), (1, 3), (3, 4), (4, 2)]

首先,将文件读入行列表:

import csv
with open('myFile.csv') as f:
    rows = [row for row in csv.reader(f)]
此时,您可以构建一个dict来保存映射:

nameSet = set()
for row in rows:
    for name in row:
        nameSet.add(name)
map = dict((name, i) for i, name in enumerate(nameSet))
output = [[map[name] for name in row] for row in rows]
或者,您可以直接构建dict:

nextID = 0
map = {}
for row in rows:
    for name in row:
        if name not in map:
            map[name] = nextID
            nextID += 1
无论哪种方式,您都要再次遍历这些行并应用映射:

nameSet = set()
for row in rows:
    for name in row:
        nameSet.add(name)
map = dict((name, i) for i, name in enumerate(nameSet))
output = [[map[name] for name in row] for row in rows]

要真正匿名化数据,需要为名称使用随机别名。散列很好,但如果您只想将每个名称映射为一个整数,可以执行以下操作:

from random import shuffle

data = [("Anna", "Joe"), ("Anna", "Mark"), ("Mark", "Mindy"), ("Mindy", "Joe")]
names = list(set(x for pair in data for x in pair))
shuffle(names)
aliases = dict((k, v) for v, k in enumerate(names))

munged = [(aliases[a], aliases[b]) for a, b in data] 
这会给你一些类似的东西:

>>> data
[('Anna', 'Joe'), ('Anna', 'Mark'), ('Mark', 'Mindy'), ('Mindy', 'Joe')]
>>> names
['Mindy', 'Joe', 'Anna', 'Mark']
>>> aliases
{'Mindy': 0, 'Joe': 1, 'Anna': 2, 'Mark': 3}
>>> munged
[(2, 1), (2, 3), (3, 0), (0, 1)]
然后,您可以(如果需要)从别名中获取名称,反之亦然:

>>> aliases["Joe"]
1
>>> names[2]
'Anna'

唯一标识符是否必须仅为1,2,3?@AshwiniChaudhary否-任何类型的标识符都可以。完全接受这个答案…虽然哈希可能会很顺利,但我不确定为什么我没有想到它。