在Python中匿名化值列表

时间:2012-11-16 07:32:59

标签: python

假设您的数据集类似于包含温和敏感信息的CSV文件,例如谁在12年级英语课程中传递了一个注释。虽然如果这些数据出来并不是危机,但最好删除识别信息,以便将数据公之于众,与合作者共享等等。数据看起来像这样:

给予者,收件人:

  

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

你将如何处理这个列表,为每个名称分配一个唯一但任意的标识符,然后删除名称并用Python中的所述标识符替换它们,这样你最终会得到类似的结果:

  

1,2-
1,3
  3,4-
4,2

5 个答案:

答案 0 :(得分:5)

您可以使用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

或者您也可以使用iterools.count

In [80]: c=count(1)

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

或使用itertools的unique_everseen食谱改进我以前的答案,你可以得到确切的答案:

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

答案 1 :(得分:3)

names = """
Anna,Joe
Anna,Mark
Mark,Mindy
Mindy,Joe
"""

nameset = set((",".join(names.strip().splitlines())).split(","))

for i,name in enumerate(nameset):
    names = names.replace(name,str(i))

print names

2,1
2,3
3,0
0,1

答案 2 :(得分:2)

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

data = [("Anna", "Joe"), ("Anna", "Mark"), ("Mark", "Mindy"), ("Mindy", "Joe")]

names = {}
def anon(name):
    if not name in names:
        names[name] = len(names) + 1
    return names[name]

result = []

for n1, n2 in data:
    result.append((anon(n1), anon(n2)))

print names
print result

运行时会给出:

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

答案 3 :(得分: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))

或者,您可以直接构建dict:

nextID = 0
map = {}
for row in rows:
    for name in row:
        if name not in map:
            map[name] = nextID
            nextID += 1

无论哪种方式,您再次遍历行并应用映射:

output = [[map[name] for name in row] for row in rows]

答案 4 :(得分:2)

要真正匿名化数据,您需要名称的随机别名。哈希对此有好处,但如果您只想将每个名称映射到整数,则可以执行以下操作:

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'