假設您有一個類似於CSV文件的數據集,該文件包含溫和的敏感信息,例如誰在12級英語課程中向誰傳遞了筆記。儘管如果這些數據傳出並不是危機,那麼剝離標識信息以便數據可以公開,與合作者共享等是很好的。數據看起來像這樣:在Python中匿名化值列表
Giver,收件人:
安娜,喬
安娜,馬克
馬克,柯以敏
柯以敏,喬
你將如何通過這個列表處理,分配給每個名稱的唯一但任意標識,然後去掉名字並替換它們與所述標識符在Python使得你最終是這樣的:
1,2-
1,3-
3,4-
4,2
假設您有一個類似於CSV文件的數據集,該文件包含溫和的敏感信息,例如誰在12級英語課程中向誰傳遞了筆記。儘管如果這些數據傳出並不是危機,那麼剝離標識信息以便數據可以公開,與合作者共享等是很好的。數據看起來像這樣:在Python中匿名化值列表
Giver,收件人:
安娜,喬
安娜,馬克
馬克,柯以敏
柯以敏,喬
你將如何通過這個列表處理,分配給每個名稱的唯一但任意標識,然後去掉名字並替換它們與所述標識符在Python使得你最終是這樣的:
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
,或者您也可以使用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
接受這個答案的徹底性......雖然散列可能會游泳,但我不知道爲什麼我沒有想到它。 – Fomite
你可以使用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)]
首先,閱讀您的文件到行的列表:
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]
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
要真正匿名的數據,你需要的名字隨機別名。哈希值是適合這種模式,但如果你只是想每個名稱映射到一個整數,你可以做這樣的事情:
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否 - 任何種類的標識符都可以工作。 – Fomite