5

次のおもちゃセットを考えてみましょう (列名が「キー」であり、「データ」に入れたいくつかの行にのみ関心がある CSV ファイルから):

keys = ['k1', 'k2', 'k3', 'k4']
data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]

次のように、各列のリストを含む辞書を取得したい:

{'k1': [1, 5, 9, 13], 'k2': [2, 6, 10, 14], 'k3': [3, 7, 11, 15], 'k4': [4, 8, 
12, 16]}

私のコードでは、最初に空のリストでディクショナリを初期化し、次に (キーの順序で) 繰り返して、リストに各項目を追加します。

my_dict = dict.fromkeys(keys, [])
for row in data:
    for i, k in zip(row, keys):
        my_dict[k].append(i)

しかし、うまくいきません。この辞書を構築します。

{'k3': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 'k2': [1, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], 'k1': [1, 2, 3, 4, 5, 6, 7, 8, 
9, 10, 11, 12, 13, 14, 15, 16], 'k4': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 
13, 14, 15, 16]}

各リストに 4 つの要素だけではなく、すべての要素がすべてのリストに含まれていることがわかります。ループ内で i, k を出力すると、アイテムとキーの正しいペアが実行されます。したがって、問題は、キー k のリストにアイテム i を追加するときだと思います。

すべての要素がすべてのリストに追加される理由と、辞書を作成する正しい方法を知っている人はいますか?

前もって感謝します

4

5 に答える 5

9

圧縮しますが、最初に転置します。

>>> keys = ['k1', 'k2', 'k3', 'k4']
>>> data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
>>> print dict(zip(keys, zip(*data)))
{'k3': (3, 7, 11, 15), 'k2': (2, 6, 10, 14), 'k1': (1, 5, 9, 13), 'k4': (4, 8, 12, 16)}

配列内のタプルではなくリストが必要な場合:

>>> print dict(zip(keys, [list(i) for i in zip(*data)]))

そして、あなたのバージョンを使用したい場合は、次のことではなく、辞書を理解するだけfromkeysです。

my_dict = { k : [] for k in keys }

my_dict同じ値で初期化する場合の問題:

>>> my_dict = dict.fromkeys(keys, [])
>>> my_dict
{'k3': [], 'k2': [], 'k1': [], 'k4': []}
>>> my_dict['k3'].append(1)
>>> my_dict
{'k3': [1], 'k2': [1], 'k1': [1], 'k4': [1]}

正しく行うと(辞書/リストの理解を使用):

>>> my_dict = dict((k, []) for k in keys )
>>> my_dict
{'k3': [], 'k2': [], 'k1': [], 'k4': []}
>>> my_dict['k3'].append(1)
>>> my_dict
{'k3': [1], 'k2': [], 'k1': [], 'k4': []}
于 2012-07-23T13:23:06.693 に答える
7

この回答で説明されている問題に遭遇しています。辞書は、すべての値に対して再利用された同じリストオブジェクトで初期化されています。単に使用する

dict(zip(keys, zip(*data)))

代わりは。これにより、行のリストが列のリストに転置され、キーと列がまとめて圧縮されます。

于 2012-07-23T13:16:49.477 に答える
4

私はそれdict(zip(keys, map(list,zip(*data)) ))がトリックを行うべきだと思います。

最初に、データを転置します ( zip(*data)) が、タプルを返します...リストが必要なので、map を使用してタプルからリストを作成します。次に、zip を再度使用して、キーをリスト内の項目と照合します。例えば(key1,list1), (key2,list2),...。これはまさにディクショナリ コンストラクターが期待するものなので、あなたはゴールデンです。

別の解決策は、次を使用することcollections.defaultdictです。

d=collections.defaultdict(list)
tdata=zip(*data)  #transpose your data
for k,v in zip(keys,tdata):
    d[k].extend(v)

もちろん、これにより、通常のものではなく defaultdict が残りますが、簡単に通常のものに変更できます d=dict(**d)

于 2012-07-23T13:16:40.860 に答える
0

それはうまくいくはずです:

keys = ['k1', 'k2', 'k3', 'k4']
data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
mydict = {}
for k in keys:
    b[k] = []
    for l in data:
        b[k].append(l[i])
    i += 1

index() は高価な関数であることに注意してください。膨大なデータ セットがある場合は使用しないでください。その場合、変数をインクリメントします。

編集:いいえ、そうではありません!すみません、ちょっと

編集:動作するようになりました!

于 2012-07-23T13:19:28.597 に答える
0
>>> keys = ['k1', 'k2', 'k3', 'k4']
>>> data = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]
>>> dict(zip(keys, zip(*data)))
{'k3': (3, 7, 11, 15), 'k2': (2, 6, 10, 14), 'k1': (1, 5, 9, 13), 'k4': (4, 8, 12, 16)}

本当にリストが必要な場合:

>>> dict(zip(keys, map(list, zip(*data))))
{'k3': [3, 7, 11, 15], 'k2': [2, 6, 10, 14], 'k1': [1, 5, 9, 13], 'k4': [4, 8, 12, 16]}

Python 2 を使用している場合は、 szipmap返しlistます。大規模なデータ セットを操作している場合は、 and を使用itertools.izipitertools.imapて効率を高め、中間リストの作成を避けることができます。

于 2012-07-23T13:22:43.610 に答える