2

12年生の英語のクラスで誰が誰にメモを渡したかなど、やや機密性の高い情報を含むCSVファイルのようなデータセットがあるとします。このデータが出ても危機ではありませんが、識別情報を取り除いて、データを公開したり、共同編集者と共有したりできるようにすると便利です。データは次のようになります。

提供者、受信者:

アンナ、ジョー
アンナ、マーク
マーク、ミンディ
ミンディ、ジョー

このリストをどのように処理し、各名前に一意であるが任意の識別子を割り当て、名前を取り除き、Pythonでその識別子に置き換えて、次のようにします。

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

4

5 に答える 5

6

一意の任意の識別子を生成するために使用できます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
于 2012-11-16T07:42:20.893 に答える
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
于 2012-11-16T07:50:05.470 に答える
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'
于 2012-11-16T08:09:26.757 に答える
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)]
于 2012-11-16T07:46:42.213 に答える
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]
于 2012-11-16T07:46:48.370 に答える