2012-11-16 60 views
2

假設您有一個類似於CSV文件的數據集,該文件包含溫和的敏感信息,例如誰在12級英語課程中向誰傳遞了筆記。儘管如果這些數據傳出並不是危機,那麼剝離標識信息以便數據可以公開,與合作者共享等是很好的。數據看起來像這樣:在Python中匿名化值列表

Giver,收件人:

安娜,喬
安娜,馬克
馬克,柯以敏
柯以敏,喬

你將如何通過這個列表處理,分配給每個名稱的唯一但任意標識,然後去掉名字並替換它們與所述標識符在Python使得你最終是這樣的:

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

+0

唯一標識符必須僅爲1,2,3嗎? –

+0

@AshwiniChaudhary否 - 任何種類的標識符都可以工作。 – Fomite

回答

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 
+0

接受這個答案的徹底性......雖然散列可能會游泳,但我不知道爲什麼我沒有想到它。 – Fomite

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)] 
2

首先,閱讀您的文件到行的列表:

import csv 
with open('myFile.csv') as f: 
    rows = [row for row in csv.reader(f)] 

在這一點上,你可以建立一個字典舉行的映射:

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

或者,你可以建立字典直接:

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

無論哪種方式,你再次通過行並應用th E上映射:

output = [[map[name] for name in row] for row in rows] 
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

要真正匿名的數據,你需要的名字隨機別名。哈希值是適合這種模式,但如果你只是想每個名稱映射到一個整數,你可以做這樣的事情:

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'